⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 krb5tgs.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 4 页
字号:
    if(f.request_anonymous && !config->allow_anonymous){	kdc_log(context, config, 0,		"Request for anonymous ticket");	return KRB5KDC_ERR_BADOPTION;    }#endif    return 0;}/* * */static krb5_error_codecheck_constrained_delegation(krb5_context context, 			     krb5_kdc_configuration *config,			     hdb_entry_ex *client,			     krb5_const_principal server){    const HDB_Ext_Constrained_delegation_acl *acl;    krb5_error_code ret;    int i;    ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);    if (ret) {	krb5_clear_error_string(context);	return ret;    }    if (acl) {	for (i = 0; i < acl->len; i++) {	    if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)		return 0;	}    }    kdc_log(context, config, 0,	    "Bad request for constrained delegation");    return KRB5KDC_ERR_BADOPTION;}/* * */static krb5_error_codeverify_flags (krb5_context context, 	      krb5_kdc_configuration *config,	      const EncTicketPart *et,	      const char *pstr){    if(et->endtime < kdc_time){	kdc_log(context, config, 0, "Ticket expired (%s)", pstr);	return KRB5KRB_AP_ERR_TKT_EXPIRED;    }    if(et->flags.invalid){	kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);	return KRB5KRB_AP_ERR_TKT_NYV;    }    return 0;}/* * */static krb5_error_codefix_transited_encoding(krb5_context context, 		       krb5_kdc_configuration *config,		       krb5_boolean check_policy,		       const TransitedEncoding *tr, 		       EncTicketPart *et, 		       const char *client_realm, 		       const char *server_realm, 		       const char *tgt_realm){    krb5_error_code ret = 0;    char **realms, **tmp;    int num_realms;    int i;    switch (tr->tr_type) {    case DOMAIN_X500_COMPRESS:	break;    case 0:	/*	 * Allow empty content of type 0 because that is was Microsoft	 * generates in their TGT.	 */	if (tr->contents.length == 0)	    break;	kdc_log(context, config, 0,		"Transited type 0 with non empty content");	return KRB5KDC_ERR_TRTYPE_NOSUPP;    default:	kdc_log(context, config, 0,		"Unknown transited type: %u", tr->tr_type);	return KRB5KDC_ERR_TRTYPE_NOSUPP;    }    ret = krb5_domain_x500_decode(context, 				  tr->contents,				  &realms, 				  &num_realms,				  client_realm,				  server_realm);    if(ret){	krb5_warn(context, ret,		  "Decoding transited encoding");	return ret;    }    if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {	/* not us, so add the previous realm to transited set */	if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {	    ret = ERANGE;	    goto free_realms;	}	tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));	if(tmp == NULL){	    ret = ENOMEM;	    goto free_realms;	}	realms = tmp;	realms[num_realms] = strdup(tgt_realm);	if(realms[num_realms] == NULL){	    ret = ENOMEM;	    goto free_realms;	}	num_realms++;    }    if(num_realms == 0) {	if(strcmp(client_realm, server_realm)) 	    kdc_log(context, config, 0,		    "cross-realm %s -> %s", client_realm, server_realm);    } else {	size_t l = 0;	char *rs;	for(i = 0; i < num_realms; i++)	    l += strlen(realms[i]) + 2;	rs = malloc(l);	if(rs != NULL) {	    *rs = '\0';	    for(i = 0; i < num_realms; i++) {		if(i > 0)		    strlcat(rs, ", ", l);		strlcat(rs, realms[i], l);	    }	    kdc_log(context, config, 0,		    "cross-realm %s -> %s via [%s]",		    client_realm, server_realm, rs);	    free(rs);	}    }    if(check_policy) {	ret = krb5_check_transited(context, client_realm, 				   server_realm, 				   realms, num_realms, NULL);	if(ret) {	    krb5_warn(context, ret, "cross-realm %s -> %s", 		      client_realm, server_realm);	    goto free_realms;	}	et->flags.transited_policy_checked = 1;    }    et->transited.tr_type = DOMAIN_X500_COMPRESS;    ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);    if(ret)	krb5_warn(context, ret, "Encoding transited encoding");  free_realms:    for(i = 0; i < num_realms; i++)	free(realms[i]);    free(realms);    return ret;}static krb5_error_codetgs_make_reply(krb5_context context, 	       krb5_kdc_configuration *config,	       KDC_REQ_BODY *b, 	       krb5_const_principal tgt_name,	       const EncTicketPart *tgt, 	       const EncryptionKey *serverkey,	       const krb5_keyblock *sessionkey,	       krb5_kvno kvno,	       AuthorizationData *auth_data,	       hdb_entry_ex *server, 	       const char *server_name, 	       hdb_entry_ex *client, 	       krb5_principal client_principal, 	       hdb_entry_ex *krbtgt,	       krb5_enctype krbtgt_etype,	       KRB5SignedPathPrincipals *spp,	       const krb5_data *rspac,	       const char **e_text,	       krb5_data *reply){    KDC_REP rep;    EncKDCRepPart ek;    EncTicketPart et;    KDCOptions f = b->kdc_options;    krb5_error_code ret;        memset(&rep, 0, sizeof(rep));    memset(&et, 0, sizeof(et));    memset(&ek, 0, sizeof(ek));        rep.pvno = 5;    rep.msg_type = krb_tgs_rep;    et.authtime = tgt->authtime;    _kdc_fix_time(&b->till);    et.endtime = min(tgt->endtime, *b->till);    ALLOC(et.starttime);    *et.starttime = kdc_time;        ret = check_tgs_flags(context, config, b, tgt, &et);    if(ret)	goto out;    /* We should check the transited encoding if:       1) the request doesn't ask not to be checked       2) globally enforcing a check       3) principal requires checking       4) we allow non-check per-principal, but principal isn't marked as allowing this       5) we don't globally allow this    */#define GLOBAL_FORCE_TRANSITED_CHECK		\    (config->trpolicy == TRPOLICY_ALWAYS_CHECK)#define GLOBAL_ALLOW_PER_PRINCIPAL			\    (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)#define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK			\    (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)/* these will consult the database in future release */#define PRINCIPAL_FORCE_TRANSITED_CHECK(P)		0#define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P)	0    ret = fix_transited_encoding(context, config, 				 !f.disable_transited_check ||				 GLOBAL_FORCE_TRANSITED_CHECK ||				 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||				 !((GLOBAL_ALLOW_PER_PRINCIPAL && 				    PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||				   GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),				 &tgt->transited, &et,				 *krb5_princ_realm(context, client_principal),				 *krb5_princ_realm(context, server->entry.principal),				 *krb5_princ_realm(context, krbtgt->entry.principal));    if(ret)	goto out;    copy_Realm(krb5_princ_realm(context, server->entry.principal), 	       &rep.ticket.realm);    _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal);    copy_Realm(&tgt_name->realm, &rep.crealm);/*    if (f.request_anonymous)	_kdc_make_anonymous_principalname (&rep.cname);    else */    copy_PrincipalName(&tgt_name->name, &rep.cname);    rep.ticket.tkt_vno = 5;    ek.caddr = et.caddr;    if(et.caddr == NULL)	et.caddr = tgt->caddr;    {	time_t life;	life = et.endtime - *et.starttime;	if(client && client->entry.max_life)	    life = min(life, *client->entry.max_life);	if(server->entry.max_life)	    life = min(life, *server->entry.max_life);	et.endtime = *et.starttime + life;    }    if(f.renewable_ok && tgt->flags.renewable &&        et.renew_till == NULL && et.endtime < *b->till){	et.flags.renewable = 1;	ALLOC(et.renew_till);	*et.renew_till = *b->till;    }    if(et.renew_till){	time_t renew;	renew = *et.renew_till - et.authtime;	if(client && client->entry.max_renew)	    renew = min(renew, *client->entry.max_renew);	if(server->entry.max_renew)	    renew = min(renew, *server->entry.max_renew);	*et.renew_till = et.authtime + renew;    }	        if(et.renew_till){	*et.renew_till = min(*et.renew_till, *tgt->renew_till);	*et.starttime = min(*et.starttime, *et.renew_till);	et.endtime = min(et.endtime, *et.renew_till);    }        *et.starttime = min(*et.starttime, et.endtime);    if(*et.starttime == et.endtime){	ret = KRB5KDC_ERR_NEVER_VALID;	goto out;    }    if(et.renew_till && et.endtime == *et.renew_till){	free(et.renew_till);	et.renew_till = NULL;	et.flags.renewable = 0;    }        et.flags.pre_authent = tgt->flags.pre_authent;    et.flags.hw_authent  = tgt->flags.hw_authent;    et.flags.anonymous   = tgt->flags.anonymous;    et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;	        if (auth_data) {	/* XXX Check enc-authorization-data */	et.authorization_data = calloc(1, sizeof(*et.authorization_data));	if (et.authorization_data == NULL) {	    ret = ENOMEM;	    goto out;	}	ret = copy_AuthorizationData(auth_data, et.authorization_data);	if (ret)	    goto out;	/* Filter out type KRB5SignedPath */	ret = find_KRB5SignedPath(context, et.authorization_data, NULL);	if (ret == 0) {	    if (et.authorization_data->len == 1) {		free_AuthorizationData(et.authorization_data);		free(et.authorization_data);		et.authorization_data = NULL;	    } else {		AuthorizationData *ad = et.authorization_data;		free_AuthorizationDataElement(&ad->val[ad->len - 1]);		ad->len--;	    }	}    }    if(rspac->length) {	/*	 * No not need to filter out the any PAC from the	 * auth_data since it's signed by the KDC.	 */	ret = _kdc_tkt_add_if_relevant_ad(context, &et,					  KRB5_AUTHDATA_WIN2K_PAC,					  rspac);	if (ret)	    goto out;    }    ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);    if (ret)	goto out;    et.crealm = tgt->crealm;    et.cname = tgt_name->name;	        ek.key = et.key;    /* MIT must have at least one last_req */    ek.last_req.len = 1;    ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));    if (ek.last_req.val == NULL) {	ret = ENOMEM;	goto out;    }    ek.nonce = b->nonce;    ek.flags = et.flags;    ek.authtime = et.authtime;    ek.starttime = et.starttime;    ek.endtime = et.endtime;    ek.renew_till = et.renew_till;    ek.srealm = rep.ticket.realm;    ek.sname = rep.ticket.sname;        _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, 		       et.endtime, et.renew_till);    /* Don't sign cross realm tickets, they can't be checked anyway */    {	char *r = get_krbtgt_realm(&ek.sname);	if (r == NULL || strcmp(r, ek.srealm) == 0) {	    ret = _kdc_add_KRB5SignedPath(context,					  config,					  krbtgt,					  krbtgt_etype,					  NULL,					  spp,					  &et);	    if (ret)		goto out;	}    }    /* It is somewhat unclear where the etype in the following       encryption should come from. What we have is a session       key in the passed tgt, and a list of preferred etypes       *for the new ticket*. Should we pick the best possible       etype, given the keytype in the tgt, or should we look       at the etype list here as well?  What if the tgt       session key is DES3 and we want a ticket with a (say)       CAST session key. Should the DES3 etype be added to the       etype list, even if we don't want a session key with       DES3? */    ret = _kdc_encode_reply(context, config, 			    &rep, &et, &ek, et.key.keytype,			    kvno, 			    serverkey, 0, &tgt->key, e_text, reply);out:    free_TGS_REP(&rep);    free_TransitedEncoding(&et.transited);    if(et.starttime)	free(et.starttime);    if(et.renew_till)	free(et.renew_till);    if(et.authorization_data) {	free_AuthorizationData(et.authorization_data);	free(et.authorization_data);    }    free_LastReq(&ek.last_req);    memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);    free_EncryptionKey(&et.key);    return ret;}static krb5_error_codetgs_check_authenticator(krb5_context context, 			krb5_kdc_configuration *config,	                krb5_auth_context ac,			KDC_REQ_BODY *b, 			const char **e_text,			krb5_keyblock *key){    krb5_authenticator auth;    size_t len;    unsigned char *buf;    size_t buf_size;    krb5_error_code ret;    krb5_crypto crypto;        krb5_auth_con_getauthenticator(context, ac, &auth);    if(auth->cksum == NULL){	kdc_log(context, config, 0, "No authenticator in request");	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;	goto out;    }    /*     * according to RFC1510 it doesn't need to be keyed,     * but according to the latest draft it needs to.     */    if (#if 0!krb5_checksum_is_keyed(context, auth->cksum->cksumtype)	||#endif !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {	kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", 		auth->cksum->cksumtype);	ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;	goto out;    }		    /* XXX should not re-encode this */    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);    if(ret){	kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", 		krb5_get_err_text(context, ret));	goto out;    }    if(buf_size != len) {	free(buf);	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");	*e_text = "KDC internal error";	ret = KRB5KRB_ERR_GENERIC;	goto out;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -