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

📄 kerberos5.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 4 页
字号:
     * encryption).  Then the best encryption type for the KDC and     * last the best session key that shared between the client and     * KDC runtime enctypes.     */    ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,			  &ckey, &cetype);    if (ret) {	kdc_log(context, config, 0, 		"Client (%s) has no support for etypes", client_name);	goto out;    }	    ret = _kdc_get_preferred_key(context, config,				 server, server_name,				 &setype, &skey);    if(ret)	goto out;    /*      * Select a session enctype from the list of the crypto systems     * supported enctype, is supported by the client and is one of the     * enctype of the enctype of the krbtgt.     *     * The later is used as a hint what enctype all KDC are supporting     * to make sure a newer version of KDC wont generate a session     * enctype that and older version of a KDC in the same realm can't     * decrypt.     *     * But if the KDC admin is paranoid and doesn't want to have "no     * the best" enctypes on the krbtgt, lets save the best pick from     * the client list and hope that that will work for any other     * KDCs.     */    {	const krb5_enctype *p;	krb5_enctype clientbest = ETYPE_NULL;	int i, j;	p = krb5_kerberos_enctypes(context);	sessionetype = ETYPE_NULL;	for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {	    if (krb5_enctype_valid(context, p[i]) != 0)		continue;	    for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) {		Key *dummy;		/* check with client */		if (p[i] != b->etype.val[j])		    continue; 		/* save best of union of { client, crypto system } */		if (clientbest == ETYPE_NULL)		    clientbest = p[i];		/* check with krbtgt */		ret = hdb_enctype2key(context, &server->entry, p[i], &dummy);		if (ret) 		    continue;		sessionetype = p[i];	    }	}	/* if krbtgt had no shared keys with client, pick clients best */	if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) {	    sessionetype = clientbest;	} else if (sessionetype == ETYPE_NULL) {	    kdc_log(context, config, 0,		    "Client (%s) from %s has no common enctypes with KDC"		    "to use for the session key", 		    client_name, from); 	    goto out;	}    }    log_as_req(context, config, cetype, setype, b);    if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey       || (f.request_anonymous && !config->allow_anonymous)) {	ret = KRB5KDC_ERR_BADOPTION;	kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);	goto out;    }        rep.pvno = 5;    rep.msg_type = krb_as_rep;    copy_Realm(&client->entry.principal->realm, &rep.crealm);    if (f.request_anonymous)	_kdc_make_anonymous_principalname (&rep.cname);    else	_krb5_principal2principalname(&rep.cname, 				      client->entry.principal);    rep.ticket.tkt_vno = 5;    copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);    _krb5_principal2principalname(&rep.ticket.sname, 				  server->entry.principal);    /* java 1.6 expects the name to be the same type, lets allow that     * uncomplicated name-types. */#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)    if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))	rep.ticket.sname.name_type = b->sname->name_type;#undef CNT    et.flags.initial = 1;    if(client->entry.flags.forwardable && server->entry.flags.forwardable)	et.flags.forwardable = f.forwardable;    else if (f.forwardable) {	ret = KRB5KDC_ERR_POLICY;	kdc_log(context, config, 0,		"Ticket may not be forwardable -- %s", client_name);	goto out;    }    if(client->entry.flags.proxiable && server->entry.flags.proxiable)	et.flags.proxiable = f.proxiable;    else if (f.proxiable) {	ret = KRB5KDC_ERR_POLICY;	kdc_log(context, config, 0, 		"Ticket may not be proxiable -- %s", client_name);	goto out;    }    if(client->entry.flags.postdate && server->entry.flags.postdate)	et.flags.may_postdate = f.allow_postdate;    else if (f.allow_postdate){	ret = KRB5KDC_ERR_POLICY;	kdc_log(context, config, 0,		"Ticket may not be postdatable -- %s", client_name);	goto out;    }    /* check for valid set of addresses */    if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {	ret = KRB5KRB_AP_ERR_BADADDR;	kdc_log(context, config, 0,		"Bad address list requested -- %s", client_name);	goto out;    }    ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);    if (ret)	goto out;    copy_PrincipalName(&rep.cname, &et.cname);    copy_Realm(&rep.crealm, &et.crealm);        {	time_t start;	time_t t;		start = et.authtime = kdc_time;    	if(f.postdated && req->req_body.from){	    ALLOC(et.starttime);	    start = *et.starttime = *req->req_body.from;	    et.flags.invalid = 1;	    et.flags.postdated = 1; /* XXX ??? */	}	_kdc_fix_time(&b->till);	t = *b->till;	/* be careful not overflowing */	if(client->entry.max_life)	    t = start + min(t - start, *client->entry.max_life);	if(server->entry.max_life)	    t = start + min(t - start, *server->entry.max_life);#if 0	t = min(t, start + realm->max_life);#endif	et.endtime = t;	if(f.renewable_ok && et.endtime < *b->till){	    f.renewable = 1;	    if(b->rtime == NULL){		ALLOC(b->rtime);		*b->rtime = 0;	    }	    if(*b->rtime < *b->till)		*b->rtime = *b->till;	}	if(f.renewable && b->rtime){	    t = *b->rtime;	    if(t == 0)		t = MAX_TIME;	    if(client->entry.max_renew)		t = start + min(t - start, *client->entry.max_renew);	    if(server->entry.max_renew)		t = start + min(t - start, *server->entry.max_renew);#if 0	    t = min(t, start + realm->max_renew);#endif	    ALLOC(et.renew_till);	    *et.renew_till = t;	    et.flags.renewable = 1;	}    }    if (f.request_anonymous)	et.flags.anonymous = 1;        if(b->addresses){	ALLOC(et.caddr);	copy_HostAddresses(b->addresses, et.caddr);    }        et.transited.tr_type = DOMAIN_X500_COMPRESS;    krb5_data_zero(&et.transited.contents);          copy_EncryptionKey(&et.key, &ek.key);    /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded     * as 0 and as 0x80 (meaning indefinite length) apart, and is thus     * incapable of correctly decoding SEQUENCE OF's of zero length.     *     * To fix this, always send at least one no-op last_req     *     * If there's a pw_end or valid_end we will use that,     * otherwise just a dummy lr.     */    ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));    if (ek.last_req.val == NULL) {	ret = ENOMEM;	goto out;    }    ek.last_req.len = 0;    if (client->entry.pw_end	&& (config->kdc_warn_pwexpire == 0	    || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {	ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;	++ek.last_req.len;    }    if (client->entry.valid_end) {	ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;	++ek.last_req.len;    }    if (ek.last_req.len == 0) {	ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;	ek.last_req.val[ek.last_req.len].lr_value = 0;	++ek.last_req.len;    }    ek.nonce = b->nonce;    if (client->entry.valid_end || client->entry.pw_end) {	ALLOC(ek.key_expiration);	if (client->entry.valid_end) {	    if (client->entry.pw_end)		*ek.key_expiration = min(*client->entry.valid_end, 					 *client->entry.pw_end);	    else		*ek.key_expiration = *client->entry.valid_end;	} else	    *ek.key_expiration = *client->entry.pw_end;    } else	ek.key_expiration = NULL;    ek.flags = et.flags;    ek.authtime = et.authtime;    if (et.starttime) {	ALLOC(ek.starttime);	*ek.starttime = *et.starttime;    }    ek.endtime = et.endtime;    if (et.renew_till) {	ALLOC(ek.renew_till);	*ek.renew_till = *et.renew_till;    }    copy_Realm(&rep.ticket.realm, &ek.srealm);    copy_PrincipalName(&rep.ticket.sname, &ek.sname);    if(et.caddr){	ALLOC(ek.caddr);	copy_HostAddresses(et.caddr, ek.caddr);    }    ALLOC(rep.padata);    rep.padata->len = 0;    rep.padata->val = NULL;    reply_key = &ckey->key;#if PKINIT    if (pkp) {	ret = _kdc_pk_mk_pa_reply(context, config, pkp, client, 				  req, req_buffer, 				  &reply_key, rep.padata);	if (ret)	    goto out;	ret = _kdc_add_inital_verified_cas(context,					   config,					   pkp,					   &et);	if (ret)	    goto out;    }#endif    set_salt_padata (rep.padata, ckey->salt);    /* Add signing of alias referral */    if (f.canonicalize) {	PA_ClientCanonicalized canon;	krb5_data data;	PA_DATA pa;	krb5_crypto crypto;	size_t len;	memset(&canon, 0, sizeof(canon));	canon.names.requested_name = *b->cname;	canon.names.real_name = client->entry.principal->name;	ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,			   &canon.names, &len, ret);	if (ret) 	    goto out;	if (data.length != len)	    krb5_abortx(context, "internal asn.1 error");	/* sign using "returned session key" */	ret = krb5_crypto_init(context, &et.key, 0, &crypto);	if (ret) {	    free(data.data);	    goto out;	}	ret = krb5_create_checksum(context, crypto, 				   KRB5_KU_CANONICALIZED_NAMES, 0,				   data.data, data.length,				   &canon.canon_checksum);	free(data.data);	krb5_crypto_destroy(context, crypto);	if (ret)	    goto out;	  	ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length,			   &canon, &len, ret);	free_Checksum(&canon.canon_checksum);	if (ret) 	    goto out;	if (data.length != len)	    krb5_abortx(context, "internal asn.1 error");	pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;	pa.padata_value = data;	ret = add_METHOD_DATA(rep.padata, &pa);	free(data.data);	if (ret)	    goto out;    }    if (rep.padata->len == 0) {	free(rep.padata);	rep.padata = NULL;    }    /* Add the PAC */    if (send_pac_p(context, req)) {	krb5_pac p = NULL;	krb5_data data;	ret = _kdc_pac_generate(context, client, &p);	if (ret) {	    kdc_log(context, config, 0, "PAC generation failed for -- %s", 		    client_name);	    goto out;	}	if (p != NULL) {	    ret = _krb5_pac_sign(context, p, et.authtime,				 client->entry.principal,				 &skey->key, /* Server key */ 				 &skey->key, /* FIXME: should be krbtgt key */				 &data);	    krb5_pac_free(context, p);	    if (ret) {		kdc_log(context, config, 0, "PAC signing failed for -- %s", 			client_name);		goto out;	    }	    ret = _kdc_tkt_add_if_relevant_ad(context, &et,					      KRB5_AUTHDATA_WIN2K_PAC,					      &data);	    krb5_data_free(&data);	    if (ret)		goto out;	}    }    _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, 		       et.endtime, et.renew_till);    /* do this as the last thing since this signs the EncTicketPart */    ret = _kdc_add_KRB5SignedPath(context,				  config,				  server,				  setype,				  NULL,				  NULL,				  &et);    if (ret)	goto out;    ret = _kdc_encode_reply(context, config, 			    &rep, &et, &ek, setype, server->entry.kvno, 			    &skey->key, client->entry.kvno, 			    reply_key, &e_text, reply);    free_EncTicketPart(&et);    free_EncKDCRepPart(&ek);    if (ret)	goto out;    /* */    if (datagram_reply && reply->length > config->max_datagram_reply_length) {	krb5_data_free(reply);	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;	e_text = "Reply packet too large";    }out:    free_AS_REP(&rep);    if(ret){	krb5_mk_error(context,		      ret,		      e_text,		      (e_data.data ? &e_data : NULL),		      client_princ,		      server_princ,		      NULL,		      NULL,		      reply);	ret = 0;    }#ifdef PKINIT    if (pkp)	_kdc_pk_free_client_param(context, pkp);#endif    if (e_data.data)        free(e_data.data);    if (client_princ)	krb5_free_principal(context, client_princ);    free(client_name);    if (server_princ)	krb5_free_principal(context, server_princ);    free(server_name);    if(client)	_kdc_free_ent(context, client);    if(server)	_kdc_free_ent(context, server);    return ret;}/* * Add the AuthorizationData `data

⌨️ 快捷键说明

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