diff options
Diffstat (limited to 'src/lib/krb5/krb')
-rw-r--r-- | src/lib/krb5/krb/Imakefile | 3 | ||||
-rw-r--r-- | src/lib/krb5/krb/copy_tick.c | 15 | ||||
-rw-r--r-- | src/lib/krb5/krb/gc_via_tgt.c | 7 | ||||
-rw-r--r-- | src/lib/krb5/krb/get_in_tkt.c | 49 | ||||
-rw-r--r-- | src/lib/krb5/krb/in_tkt_pwd.c | 50 | ||||
-rw-r--r-- | src/lib/krb5/krb/in_tkt_sky.c | 8 | ||||
-rw-r--r-- | src/lib/krb5/krb/mk_priv.c | 38 | ||||
-rw-r--r-- | src/lib/krb5/krb/mk_req.c | 2 | ||||
-rw-r--r-- | src/lib/krb5/krb/mk_req_ext.c | 21 | ||||
-rw-r--r-- | src/lib/krb5/krb/mk_safe.c | 37 | ||||
-rw-r--r-- | src/lib/krb5/krb/pr_to_salt.c | 2 | ||||
-rw-r--r-- | src/lib/krb5/krb/rd_priv.c | 63 | ||||
-rw-r--r-- | src/lib/krb5/krb/rd_req_dec.c | 14 | ||||
-rw-r--r-- | src/lib/krb5/krb/rd_safe.c | 48 | ||||
-rw-r--r-- | src/lib/krb5/krb/send_tgs.c | 127 |
15 files changed, 337 insertions, 147 deletions
diff --git a/src/lib/krb5/krb/Imakefile b/src/lib/krb5/krb/Imakefile index f2f8555..885bead 100644 --- a/src/lib/krb5/krb/Imakefile +++ b/src/lib/krb5/krb/Imakefile @@ -40,6 +40,7 @@ OBJS= addr_comp.o \ mk_req_ext.o \ mk_safe.o \ parse.o \ + pr_to_salt.o \ princ_comp.o \ rd_error.o \ rd_priv.o \ @@ -84,6 +85,7 @@ SRCS= addr_comp.c \ mk_req_ext.c \ mk_safe.c \ parse.c \ + pr_to_salt.c \ princ_comp.c \ rd_error.c \ rd_priv.c \ @@ -98,3 +100,4 @@ SRCS= addr_comp.c \ walk_rtree.c OtherdirLibraryTarget($(TOP)/lib,krb5,$(OBJS)) +INCLUDES=-I../../include diff --git a/src/lib/krb5/krb/copy_tick.c b/src/lib/krb5/krb/copy_tick.c index c66d082..ec6a9d4 100644 --- a/src/lib/krb5/krb/copy_tick.c +++ b/src/lib/krb5/krb/copy_tick.c @@ -27,7 +27,6 @@ krb5_enc_tkt_part **partto; { krb5_error_code retval; krb5_enc_tkt_part *tempto; - krb5_data *scratch; if (!(tempto = (krb5_enc_tkt_part *)malloc(sizeof(*tempto)))) return ENOMEM; @@ -48,16 +47,20 @@ krb5_enc_tkt_part **partto; xfree(tempto); return retval; } - if (retval = krb5_copy_data(&partfrom->transited, &scratch)) { + tempto->transited = partfrom->transited; + tempto->transited.tr_contents.data = + malloc(sizeof(partfrom->transited.tr_contents.length)); + if (!tempto->transited.tr_contents.data) { krb5_free_principal(tempto->client); krb5_free_keyblock(tempto->session); xfree(tempto); return retval; } - tempto->transited = *scratch; - xfree(scratch); + memcpy((char *)tempto->transited.tr_contents.data, + (char *)partfrom->transited.tr_contents.data, + partfrom->transited.tr_contents.length); if (retval = krb5_copy_addresses(partfrom->caddrs, &tempto->caddrs)) { - xfree(tempto->transited.data); + xfree(tempto->transited.tr_contents.data); krb5_free_principal(tempto->client); krb5_free_keyblock(tempto->session); xfree(tempto); @@ -67,7 +70,7 @@ krb5_enc_tkt_part **partto; if (retval = krb5_copy_authdata(partfrom->authorization_data, &tempto->authorization_data)) { krb5_free_address(tempto->caddrs); - xfree(tempto->transited.data); + xfree(tempto->transited.tr_contents.data); krb5_free_principal(tempto->client); krb5_free_keyblock(tempto->session); xfree(tempto); diff --git a/src/lib/krb5/krb/gc_via_tgt.c b/src/lib/krb5/krb/gc_via_tgt.c index b05c6fd..99efd79 100644 --- a/src/lib/krb5/krb/gc_via_tgt.c +++ b/src/lib/krb5/krb/gc_via_tgt.c @@ -66,6 +66,7 @@ OLDDECLARG(krb5_creds *, cred) cred->server, tgt->addresses, cred->authdata, + 0, /* no padata */ 0, /* no second ticket */ tgt, &tgsrep)) return retval; @@ -116,6 +117,12 @@ OLDDECLARG(krb5_creds *, cred) dec_rep->enc_part2->session->length);\ krb5_free_kdc_rep(dec_rep); } + if (dec_rep->msg_type != KRB5_TGS_REP) { + retval = KRB5KRB_AP_ERR_MSG_TYPE; + cleanup(); + return retval; + } + /* now it's decrypted and ready for prime time */ if (!krb5_principal_compare(dec_rep->client, tgt->client)) { diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index e690f36..4571f66 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -52,7 +52,7 @@ static char rcsid_get_in_tkt_c[] = extern krb5_deltat krb5_clockskew; -#define in_clock_skew(date) (abs((date)-request.ctime) < krb5_clockskew) +#define in_clock_skew(date) (abs((date)-request.nonce) < krb5_clockskew) /* some typedef's for the function args to make things look a bit cleaner */ @@ -60,7 +60,8 @@ extern krb5_deltat krb5_clockskew; #include <krb5/widen.h> typedef krb5_error_code (*git_key_proc) PROTOTYPE((const krb5_keytype, krb5_keyblock **, - krb5_const_pointer )); + krb5_const_pointer, + krb5_pa_data **)); #include <krb5/narrow.h> typedef krb5_error_code (*git_decrypt_proc) PROTOTYPE((const krb5_keyblock *, @@ -95,13 +96,13 @@ OLDDECLARG(krb5_ccache, ccache) krb5_data *packet; krb5_data reply; krb5_keyblock *decrypt_key; + krb5_enctype etypes[1]; + krb5_timestamp time_now; request.msg_type = KRB5_AS_REQ; /* AS_REQ has no pre-authentication. */ - request.padata_type = 0; - request.padata.data = 0; - request.padata.length = 0; + request.padata = 0; request.kdc_options = options; request.client = creds->client; @@ -110,14 +111,20 @@ OLDDECLARG(krb5_ccache, ccache) request.from = creds->times.starttime; request.till = creds->times.endtime; request.rtime = creds->times.renew_till; - if (retval = krb5_timeofday(&request.ctime)) + if (retval = krb5_timeofday(&time_now)) return(retval); + /* XXX we know they are the same size... */ - request.nonce = (krb5_int32) request.ctime; - request.etype = etype; + request.nonce = (krb5_int32) time_now; + + etypes[0] = etype; + request.etype = etypes; + request.netypes = 1; request.addresses = (krb5_address **) addrs; request.second_ticket = 0; - request.authorization_data = 0; + request.authorization_data.ciphertext.length = 0; + request.authorization_data.ciphertext.data = 0; + request.unenc_authdata = 0; /* encode & send to KDC */ if (retval = encode_krb5_as_req(&request, &packet)) @@ -129,14 +136,12 @@ OLDDECLARG(krb5_ccache, ccache) /* now decode the reply...could be error or as_rep */ - if (!krb5_is_as_rep(&reply) && !krb5_is_krb_error(&reply)) - return KRB5KRB_AP_ERR_MSG_TYPE; - if (retval = decode_krb5_as_rep(&reply, &as_reply)) { - if (decode_krb5_error(&reply, &err_reply)) - return retval; /* some other reply--??? */ + if (krb5_is_krb_error(&reply)) { + if (retval = decode_krb5_error(&reply, &err_reply)) + return retval; /* some other reply--??? */ /* it was an error */ - if ((err_reply->ctime != request.ctime) || + if ((err_reply->ctime != request.nonce) || !krb5_principal_compare(err_reply->server, request.server) || !krb5_principal_compare(err_reply->client, request.client)) retval = KRB5_KDCREP_MODIFIED; @@ -149,10 +154,19 @@ OLDDECLARG(krb5_ccache, ccache) return retval; } + if (!krb5_is_as_rep(&reply)) + return KRB5KRB_AP_ERR_MSG_TYPE; + if (retval = decode_krb5_as_rep(&reply, &as_reply)) + return retval; /* some other reply--??? */ + + if (as_reply->msg_type != KRB5_AS_REP) + return KRB5KRB_AP_ERR_MSG_TYPE; + /* it was a kdc_rep--decrypt & check */ /* generate the key */ - if (retval = (*key_proc)(keytype, &decrypt_key, keyseed)) { + if (retval = (*key_proc)(keytype, &decrypt_key, keyseed, + as_reply->padata)) { krb5_free_kdc_rep(as_reply); return retval; } @@ -166,6 +180,9 @@ OLDDECLARG(krb5_ccache, ccache) } /* check the contents for sanity: */ + if (!as_reply->enc_part2->times.starttime) + as_reply->enc_part2->times.starttime = + as_reply->enc_part2->times.authtime; if (!krb5_principal_compare(as_reply->client, request.client) || !krb5_principal_compare(as_reply->enc_part2->server, request.server) || !krb5_principal_compare(as_reply->ticket->server, request.server) diff --git a/src/lib/krb5/krb/in_tkt_pwd.c b/src/lib/krb5/krb/in_tkt_pwd.c index 8c610e9..78b9ed6 100644 --- a/src/lib/krb5/krb/in_tkt_pwd.c +++ b/src/lib/krb5/krb/in_tkt_pwd.c @@ -34,42 +34,74 @@ extern char *krb5_default_pwd_prompt1; static krb5_error_code pwd_keyproc(DECLARG(const krb5_keytype, type), DECLARG(krb5_keyblock **, key), - DECLARG(krb5_const_pointer, keyseed)) + DECLARG(krb5_const_pointer, keyseed), + DECLARG(krb5_pa_data **,padata)) OLDDECLARG(const krb5_keytype, type) OLDDECLARG(krb5_keyblock **, key) OLDDECLARG(krb5_const_pointer, keyseed) +OLDDECLARG(krb5_pa_data **,padata) { + krb5_data salt; krb5_error_code retval; - struct pwd_keyproc_arg *arg, arg2; + const struct pwd_keyproc_arg *arg; + struct pwd_keyproc_arg arg2; char pwdbuf[BUFSIZ]; int pwsize = sizeof(pwdbuf); + char f_salt = 0, use_salt = 0; if (!valid_keytype(type)) return KRB5_PROG_KEYTYPE_NOSUPP; - arg = (struct pwd_keyproc_arg *)keyseed; + if (padata) { + krb5_pa_data **ptr; + + for (ptr = padata; *ptr; ptr++) + { + if ((*ptr)->pa_type == KRB5_PADATA_PW_SALT) + { + /* use KDC-supplied salt, instead of default */ + salt.length = (*ptr)->length; + salt.data = (char *)(*ptr)->contents; + use_salt = 1; + break; + } + } + } + arg = (const struct pwd_keyproc_arg *)keyseed; + if (!use_salt) { + /* need to use flattened principal */ + if (retval = krb5_principal2salt(arg->who, &salt)) + return(retval); + f_salt = 1; + } + if (!arg->password.length) { if (retval = krb5_read_password(krb5_default_pwd_prompt1, 0, - pwdbuf, &pwsize)) + pwdbuf, &pwsize)) { + if (f_salt) xfree(salt.data); return retval; + } arg2 = *arg; + arg2.password.length = pwsize; + arg2.password.data = pwdbuf; arg = &arg2; - arg->password.length = pwsize; - arg->password.data = pwdbuf; } *key = (krb5_keyblock *)malloc(sizeof(**key)); - if (!*key) + if (!*key) { + if (f_salt) xfree(salt.data); return ENOMEM; - + } if (retval = (*krb5_keytype_array[type]->system-> string_to_key)(type, *key, &arg->password, - arg->who)) { + &salt)) { free((char *) *key); + if (f_salt) xfree(salt.data); return(retval); } + if (f_salt) xfree(salt.data); return 0; } diff --git a/src/lib/krb5/krb/in_tkt_sky.c b/src/lib/krb5/krb/in_tkt_sky.c index 136188d..904ef62 100644 --- a/src/lib/krb5/krb/in_tkt_sky.c +++ b/src/lib/krb5/krb/in_tkt_sky.c @@ -22,7 +22,7 @@ static char rcsid_in_tkt_skey_c [] = #include <krb5/ext-proto.h> struct skey_keyproc_arg { - krb5_keyblock *key; + const krb5_keyblock *key; krb5_principal server; /* it's a pointer, really! */ }; @@ -34,10 +34,12 @@ struct skey_keyproc_arg { static krb5_error_code skey_keyproc(DECLARG(const krb5_keytype, type), DECLARG(krb5_keyblock **, key), - DECLARG(krb5_const_pointer, keyseed)) + DECLARG(krb5_const_pointer, keyseed), + DECLARG(krb5_pa_data **, padata)) OLDDECLARG(const krb5_keytype, type) OLDDECLARG(krb5_keyblock **, key) OLDDECLARG(krb5_const_pointer, keyseed) +OLDDECLARG(krb5_pa_data **,padata) { krb5_keyblock *realkey; const struct skey_keyproc_arg *arg; @@ -129,7 +131,7 @@ OLDDECLARG(krb5_creds *, creds) krb5_keytype keytype; if (key) { - arg.key = (krb5_keyblock *)key; + arg.key = key; arg.server = 0; keytype = key->keytype; } else { diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c index 5a89400..483b100 100644 --- a/src/lib/krb5/krb/mk_priv.c +++ b/src/lib/krb5/krb/mk_priv.c @@ -42,15 +42,19 @@ krb5_error_code krb5_mk_priv(DECLARG(const krb5_data *, userdata), DECLARG(const krb5_enctype, etype), DECLARG(const krb5_keyblock *, key), - DECLARG(const krb5_fulladdr *, sender_addr), - DECLARG(const krb5_fulladdr *, recv_addr), + DECLARG(const krb5_address *, sender_addr), + DECLARG(const krb5_address *, recv_addr), + DECLARG(krb5_int32, seq_number), + DECLARG(krb5_int32, priv_flags), DECLARG(krb5_pointer, i_vector), DECLARG(krb5_data *, outbuf)) OLDDECLARG(const krb5_data *, userdata) OLDDECLARG(const krb5_enctype, etype) OLDDECLARG(const krb5_keyblock *, key) -OLDDECLARG(const krb5_fulladdr *, sender_addr) -OLDDECLARG(const krb5_fulladdr *, recv_addr) +OLDDECLARG(const krb5_address *, sender_addr) +OLDDECLARG(const krb5_address *, recv_addr) +OLDDECLARG(krb5_int32, seq_number) +OLDDECLARG(krb5_int32, priv_flags) OLDDECLARG(krb5_pointer, i_vector) OLDDECLARG(krb5_data *, outbuf) { @@ -66,19 +70,21 @@ OLDDECLARG(krb5_data *, outbuf) privmsg.enc_part.kvno = 0; /* XXX allow user-set? */ privmsg_enc_part.user_data = *userdata; - privmsg_enc_part.s_address = sender_addr->address; - privmsg_enc_part.r_address = recv_addr->address; - - if (retval = krb5_ms_timeofday(&privmsg_enc_part.timestamp, - &privmsg_enc_part.msec)) - return retval; - - if (krb5_fulladdr_order(sender_addr, recv_addr) > 0) - privmsg_enc_part.msec = - (privmsg_enc_part.msec & MSEC_VAL_MASK) | MSEC_DIRBIT; + privmsg_enc_part.s_address = (krb5_address *)sender_addr; + if (recv_addr) + privmsg_enc_part.r_address = (krb5_address *)recv_addr; else - /* this should be a no-op, but just to be sure... */ - privmsg_enc_part.msec = privmsg_enc_part.msec & MSEC_VAL_MASK; + privmsg_enc_part.r_address = 0; + + if (!(priv_flags & KRB5_PRIV_NOTIME)) { + if (retval = krb5_us_timeofday(&privmsg_enc_part.timestamp, + &privmsg_enc_part.usec)) + return retval; + } + if (priv_flags & KRB5_PRIV_DOSEQUENCE) { + privmsg_enc_part.seq_number = seq_number; + } else + privmsg_enc_part.seq_number = 0; /* start by encoding to-be-encrypted part of the message */ diff --git a/src/lib/krb5/krb/mk_req.c b/src/lib/krb5/krb/mk_req.c index c539d64..24e5bc7 100644 --- a/src/lib/krb5/krb/mk_req.c +++ b/src/lib/krb5/krb/mk_req.c @@ -73,6 +73,8 @@ krb5_data *outbuf; checksum, &creds.times, krb5_kdc_default_options, + 0, /* no sequence number */ + 0, /* no sub-key */ ccache, &creds, 0, /* We don't need the authenticator */ diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index 1041fdc..6a5ce9c 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -58,15 +58,19 @@ static char rcsid_mk_req_ext_c[] = */ static krb5_error_code generate_authenticator PROTOTYPE((krb5_authenticator *, const krb5_creds *, - const krb5_checksum *)); + const krb5_checksum *, + krb5_keyblock *, + krb5_int32 )); krb5_error_code -krb5_mk_req_extended(ap_req_options, checksum, times, kdc_options, ccache, - creds, authentp, outbuf) +krb5_mk_req_extended(ap_req_options, checksum, times, kdc_options, + sequence, newkey, ccache, creds, authentp, outbuf) const krb5_flags ap_req_options; const krb5_checksum *checksum; const krb5_ticket_times *times; const krb5_flags kdc_options; +krb5_int32 sequence; +krb5_keyblock *newkey; krb5_ccache ccache; krb5_creds *creds; krb5_authenticator *authentp; @@ -107,7 +111,8 @@ krb5_data *outbuf; return(retval); #define cleanup_ticket() krb5_free_ticket(request.ticket) - if (retval = generate_authenticator(&authent, creds, checksum)) { + if (retval = generate_authenticator(&authent, creds, checksum, newkey, + sequence)) { cleanup_ticket(); return retval; } @@ -203,13 +208,17 @@ request.authenticator.ciphertext.data = 0;} } static krb5_error_code -generate_authenticator(authent, creds, cksum) +generate_authenticator(authent, creds, cksum, key, seq_number) krb5_authenticator *authent; const krb5_creds *creds; const krb5_checksum *cksum; +krb5_keyblock *key; +krb5_int32 seq_number; { authent->client = creds->client; authent->checksum = (krb5_checksum *)cksum; + authent->subkey = key; + authent->seq_number = seq_number; - return(krb5_ms_timeofday(&authent->ctime, &authent->cmsec)); + return(krb5_us_timeofday(&authent->ctime, &authent->cusec)); } diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c index 975d0cb..12fb963 100644 --- a/src/lib/krb5/krb/mk_safe.c +++ b/src/lib/krb5/krb/mk_safe.c @@ -41,14 +41,18 @@ krb5_error_code krb5_mk_safe(DECLARG(const krb5_data *, userdata), DECLARG(const krb5_cksumtype, sumtype), DECLARG(const krb5_keyblock *, key), - DECLARG(const krb5_fulladdr *, sender_addr), - DECLARG(const krb5_fulladdr *, recv_addr), + DECLARG(const krb5_address *, sender_addr), + DECLARG(const krb5_address *, recv_addr), + DECLARG(krb5_int32, seq_number), + DECLARG(krb5_int32, safe_flags), DECLARG(krb5_data *, outbuf)) OLDDECLARG(const krb5_data *, userdata) OLDDECLARG(const krb5_cksumtype, sumtype) OLDDECLARG(const krb5_keyblock *, key) -OLDDECLARG(const krb5_fulladdr *, sender_addr) -OLDDECLARG(const krb5_fulladdr *, recv_addr) +OLDDECLARG(const krb5_address *, sender_addr) +OLDDECLARG(const krb5_address *, recv_addr) +OLDDECLARG(krb5_int32, seq_number) +OLDDECLARG(krb5_int32, safe_flags) OLDDECLARG(krb5_data *, outbuf) { krb5_error_code retval; @@ -59,20 +63,25 @@ OLDDECLARG(krb5_data *, outbuf) if (!valid_cksumtype(sumtype)) return KRB5_PROG_SUMTYPE_NOSUPP; + if (!is_coll_proof_cksum(sumtype) || !is_keyed_cksum(sumtype)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; safemsg.user_data = *userdata; - safemsg.s_address = sender_addr->address; - safemsg.r_address = recv_addr->address; - - if (retval = krb5_ms_timeofday(&safemsg.timestamp, &safemsg.msec)) - return retval; - - if (krb5_fulladdr_order(sender_addr, recv_addr) > 0) - safemsg.msec = (safemsg.msec & MSEC_VAL_MASK) | MSEC_DIRBIT; + safemsg.s_address = (krb5_address *)sender_addr; + if (recv_addr) + safemsg.r_address = (krb5_address *)recv_addr; else - /* this should be a no-op, but just to be sure... */ - safemsg.msec = safemsg.msec & MSEC_VAL_MASK; + safemsg.r_address = 0; + if (!(safe_flags & KRB5_SAFE_NOTIME)) { + if (retval = krb5_us_timeofday(&safemsg.timestamp, &safemsg.usec)) + return retval; + } + if (safe_flags & KRB5_SAFE_DOSEQUENCE) { + safemsg.seq_number = seq_number; + } else + safemsg.seq_number = 0; + /* to do the checksum stuff, we need to encode the message with a zero-length zero-type checksum, then checksum the encoding, then re-encode with the diff --git a/src/lib/krb5/krb/pr_to_salt.c b/src/lib/krb5/krb/pr_to_salt.c index 4060202..74013fb 100644 --- a/src/lib/krb5/krb/pr_to_salt.c +++ b/src/lib/krb5/krb/pr_to_salt.c @@ -30,7 +30,7 @@ krb5_const_principal pr; krb5_data *ret; { int size, offset; - krb5_data **prp; + krb5_data * const * prp; if (pr == 0) { diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index 8cc22df..78607bf 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -49,14 +49,18 @@ Returns system errors, integrity errors. krb5_error_code krb5_rd_priv(DECLARG(const krb5_data *, inbuf), DECLARG(const krb5_keyblock *, key), - DECLARG(const krb5_fulladdr *, sender_addr), - DECLARG(const krb5_fulladdr *, recv_addr), + DECLARG(const krb5_address *, sender_addr), + DECLARG(const krb5_address *, recv_addr), + DECLARG(krb5_int32, seq_number), + DECLARG(krb5_int32, priv_flags), DECLARG(krb5_pointer, i_vector), DECLARG(krb5_data *, outbuf)) OLDDECLARG(const krb5_data *, inbuf) OLDDECLARG(const krb5_keyblock *, key) -OLDDECLARG(const krb5_fulladdr *, sender_addr) -OLDDECLARG(const krb5_fulladdr *, recv_addr) +OLDDECLARG(const krb5_address *, sender_addr) +OLDDECLARG(const krb5_address *, recv_addr) +OLDDECLARG(krb5_int32, seq_number) +OLDDECLARG(krb5_int32, priv_flags) OLDDECLARG(krb5_pointer, i_vector) OLDDECLARG(krb5_data *, outbuf) { @@ -66,7 +70,6 @@ OLDDECLARG(krb5_data *, outbuf) krb5_priv_enc_part *privmsg_enc_part; krb5_data scratch; krb5_timestamp currenttime; - krb5_ui_2 computed_direction; if (!krb5_is_krb_priv(inbuf)) return KRB5KRB_AP_ERR_MSG_TYPE; @@ -142,25 +145,28 @@ OLDDECLARG(krb5_data *, outbuf) #define cleanup_data() {(void)memset(privmsg_enc_part->user_data.data,0,privmsg_enc_part->user_data.length); (void)xfree(privmsg_enc_part->user_data.data);} #define cleanup_mesg() {(void)xfree(privmsg_enc_part);} - if (retval = krb5_timeofday(¤ttime)) { - cleanup_data(); - cleanup_mesg(); - return retval; - } - if (!in_clock_skew(privmsg_enc_part->timestamp)) { - cleanup_data(); - cleanup_mesg(); - return KRB5KRB_AP_ERR_SKEW; + if (!(priv_flags & KRB5_PRIV_NOTIME)) { + if (retval = krb5_timeofday(¤ttime)) { + cleanup_data(); + cleanup_mesg(); + return retval; + } + if (!in_clock_skew(privmsg_enc_part->timestamp)) { + cleanup_data(); + cleanup_mesg(); + return KRB5KRB_AP_ERR_SKEW; + } + /* replay detection goes here... XXX */ } - /* - * check with the replay cache should be inserted here !!!! - */ - + if (priv_flags & KRB5_PRIV_DOSEQUENCE) + if (privmsg_enc_part->seq_number != seq_number) { + cleanup_data(); + cleanup_mesg(); + return KRB5KRB_AP_ERR_BADSEQ; + } - if (sender_addr) { - krb5_fulladdr temp_sender; - krb5_fulladdr temp_recip; + if (privmsg_enc_part->r_address) { krb5_address **our_addrs; if (retval = krb5_os_localaddr(&our_addrs)) { @@ -175,21 +181,8 @@ OLDDECLARG(krb5_data *, outbuf) return KRB5KRB_AP_ERR_BADADDR; } krb5_free_address(our_addrs); - - temp_recip = *recv_addr; - temp_recip.address = privmsg_enc_part->r_address; - - temp_sender = *sender_addr; - temp_sender.address = privmsg_enc_part->s_address; - - computed_direction = ((krb5_fulladdr_order(&temp_sender, &temp_recip) > - 0) ? MSEC_DIRBIT : 0); - if (computed_direction != (privmsg_enc_part->msec & MSEC_DIRBIT)) { - cleanup_data(); - cleanup_mesg(); - return KRB5KRB_AP_ERR_BADDIRECTION; - } } + /* XXX check sender's address */ /* everything is ok - return data to the user */ diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c index cce02cb..0028ca7 100644 --- a/src/lib/krb5/krb/rd_req_dec.c +++ b/src/lib/krb5/krb/rd_req_dec.c @@ -81,11 +81,10 @@ krb5_tkt_authent *tktauthent; krb5_error_code retval; krb5_keyblock *tkt_key; krb5_keyblock tkt_key_real; - krb5_timestamp currenttime; + krb5_timestamp currenttime, starttime; - if ((server != NULL) && - (!krb5_principal_compare(server, req->ticket->server))) + if (server && !krb5_principal_compare(server, req->ticket->server)) return KRB5KRB_AP_WRONG_PRINC; /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY) @@ -162,7 +161,14 @@ krb5_tkt_authent *tktauthent; return retval; } tktauthent->ticket = 0; - if (req->ticket->enc_part2->times.starttime - currenttime > krb5_clockskew) { + + /* if starttime is not in ticket, then treat it as authtime */ + if (req->ticket->enc_part2->times.starttime != 0) + starttime = req->ticket->enc_part2->times.starttime; + else + starttime = req->ticket->enc_part2->times.authtime; + + if (starttime - currenttime > krb5_clockskew) { clean_authenticator(); return KRB5KRB_AP_ERR_TKT_NYV; /* ticket not yet valid */ } diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c index cd194e5..b6ab7dd 100644 --- a/src/lib/krb5/krb/rd_safe.c +++ b/src/lib/krb5/krb/rd_safe.c @@ -38,16 +38,17 @@ extern krb5_deltat krb5_clockskew; returns system errors, integrity errors */ krb5_error_code -krb5_rd_safe(inbuf, key, sender_addr, recv_addr, outbuf) +krb5_rd_safe(inbuf, key, sender_addr, recv_addr, seq_number, safe_flags, outbuf) const krb5_data *inbuf; const krb5_keyblock *key; -const krb5_fulladdr *sender_addr; -const krb5_fulladdr *recv_addr; +const krb5_address *sender_addr; +const krb5_address *recv_addr; +krb5_int32 seq_number; +krb5_int32 safe_flags; krb5_data *outbuf; { krb5_error_code retval; krb5_safe *message; - krb5_ui_2 computed_direction; krb5_checksum our_cksum, *his_cksum; krb5_octet zero_octet = 0; krb5_data *scratch; @@ -63,22 +64,30 @@ krb5_data *outbuf; if (!valid_cksumtype(message->checksum->checksum_type)) return KRB5_PROG_SUMTYPE_NOSUPP; + if (!is_coll_proof_cksum(message->checksum->checksum_type) || + !is_keyed_cksum(message->checksum->checksum_type)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; if (retval = krb5_timeofday(¤ttime)) { cleanup(); return retval; } - /* in_clock_skew #defined above */ - if (!in_clock_skew(message->timestamp)) { - cleanup(); - return KRB5KRB_AP_ERR_SKEW; + if (!(safe_flags & KRB5_SAFE_NOTIME)) { + /* in_clock_skew #defined above */ + if (!in_clock_skew(message->timestamp)) { + cleanup(); + return KRB5KRB_AP_ERR_SKEW; + } + /* replay detection goes here... XXX */ } - /* replay detection goes here... XXX */ + if (safe_flags & KRB5_SAFE_DOSEQUENCE) + if (message->seq_number != seq_number) { + cleanup(); + return KRB5KRB_AP_ERR_BADSEQ; + } - if (sender_addr) { - krb5_fulladdr temp_sender; - krb5_fulladdr temp_recip; + if (message->r_address) { krb5_address **our_addrs; if (retval = krb5_os_localaddr(&our_addrs)) { @@ -91,21 +100,10 @@ krb5_data *outbuf; return KRB5KRB_AP_ERR_BADADDR; } krb5_free_address(our_addrs); - - temp_recip = *recv_addr; - temp_recip.address = message->r_address; - - temp_sender = *sender_addr; - temp_sender.address = message->s_address; - - computed_direction = ((krb5_fulladdr_order(&temp_sender, &temp_recip) > - 0) ? MSEC_DIRBIT : 0); - if (computed_direction != (message->msec & MSEC_DIRBIT)) { - cleanup(); - return KRB5KRB_AP_ERR_BADDIRECTION; - } } + /* XXX check sender's address */ + /* verify the checksum */ /* to do the checksum stuff, we need to re-encode the message with a zero-length zero-type checksum, then checksum the encoding, and verify. diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c index 9e8d159..164c677 100644 --- a/src/lib/krb5/krb/send_tgs.c +++ b/src/lib/krb5/krb/send_tgs.c @@ -24,7 +24,7 @@ static char rcsid_send_tgs_c[] = Sends a request to the TGS and waits for a response. options is used for the options in the KRB_TGS_REQ. timestruct values are used for from, till, rtime " " " - etype is used for etype " " " + etype is used for etype " " ", and to encrypt the authorization data, if present sumtype is used for the checksum in the AP_REQ in the KRB_TGS_REQ sname is used for sname " " " addrs, if non-NULL, is used for addresses " " " @@ -47,6 +47,7 @@ krb5_send_tgs(DECLARG(const krb5_flags, kdcoptions), DECLARG(krb5_const_principal, sname), DECLARG(krb5_address * const *, addrs), DECLARG(krb5_authdata * const *,authorization_data), + DECLARG(krb5_pa_data * const *, padata), DECLARG(const krb5_data *,second_ticket), DECLARG(krb5_creds *,usecred), DECLARG(krb5_response *,rep)) @@ -57,6 +58,7 @@ OLDDECLARG(const krb5_cksumtype, sumtype) OLDDECLARG(krb5_const_principal, sname) OLDDECLARG(krb5_address * const *, addrs) OLDDECLARG(krb5_authdata * const *,authorization_data) +OLDDECLARG(krb5_pa_data * const *, padata) OLDDECLARG(const krb5_data *,second_ticket) OLDDECLARG(krb5_creds *,usecred) OLDDECLARG(krb5_response *,rep) @@ -64,9 +66,16 @@ OLDDECLARG(krb5_response *,rep) krb5_error_code retval; krb5_kdc_req tgsreq; krb5_checksum ap_checksum; - krb5_data *scratch; + krb5_data *scratch, scratch2; krb5_ticket *sec_ticket = 0; krb5_ticket *sec_ticket_arr[2]; + krb5_enctype etypes[1]; + krb5_timestamp time_now; + krb5_pa_data **combined_padata; + krb5_pa_data ap_req_padata; + + if (!valid_etype(etype)) + return KRB5_PROG_ETYPE_NOSUPP; memset((char *)&tgsreq, 0, sizeof(tgsreq)); @@ -76,17 +85,73 @@ OLDDECLARG(krb5_response *,rep) tgsreq.from = timestruct->starttime; tgsreq.till = timestruct->endtime; tgsreq.rtime = timestruct->renew_till; - if (retval = krb5_timeofday(&tgsreq.ctime)) + if (retval = krb5_timeofday(&time_now)) return(retval); /* XXX we know they are the same size... */ - tgsreq.nonce = (krb5_int32) tgsreq.ctime; + tgsreq.nonce = (krb5_int32) time_now; + + etypes[0] = etype; + tgsreq.etype = etypes; + tgsreq.netypes = 1; - tgsreq.etype = etype; tgsreq.addresses = (krb5_address **) addrs; - tgsreq.authorization_data = (krb5_authdata **)authorization_data; + + if (authorization_data) { + /* need to encrypt it in the request */ + + krb5_encrypt_block eblock; + + if (retval = encode_krb5_authdata(authorization_data, &scratch)) + return(retval); + krb5_use_cstype(&eblock, etype); + tgsreq.authorization_data.ciphertext.length = + krb5_encrypt_size(scratch->length, + eblock.crypto_entry); + /* add padding area, and zero it */ + if (!(scratch->data = realloc(scratch->data, + tgsreq.authorization_data.ciphertext.length))) { + /* may destroy scratch->data */ + xfree(scratch); + return ENOMEM; + } + memset(scratch->data + scratch->length, 0, + tgsreq.authorization_data.ciphertext.length - scratch->length); + if (!(tgsreq.authorization_data.ciphertext.data = + malloc(tgsreq.authorization_data.ciphertext.length))) { + krb5_free_data(scratch); + return ENOMEM; + } + if (retval = krb5_process_key(&eblock, &usecred->keyblock)) { + krb5_free_data(scratch); + return retval; + } + /* call the encryption routine */ + if (retval = krb5_encrypt((krb5_pointer) scratch->data, + (krb5_pointer) tgsreq.authorization_data.ciphertext.data, + scratch->length, &eblock, 0)) { + (void) krb5_finish_key(&eblock); + xfree(tgsreq.authorization_data.ciphertext.data); + krb5_free_data(scratch); + return retval; + } + krb5_free_data(scratch); + if (retval = krb5_finish_key(&eblock)) { + xfree(tgsreq.authorization_data.ciphertext.data); + return retval; + } + } +#define cleanup_authdata() { if (tgsreq.authorization_data.ciphertext.data) {\ + (void) memset(tgsreq.authorization_data.ciphertext.data, 0,\ + tgsreq.authorization_data.ciphertext.length); \ + xfree(tgsreq.authorization_data.ciphertext.data);}} + + + if (second_ticket) { - if (retval = decode_krb5_ticket(second_ticket, &sec_ticket)) + if (retval = decode_krb5_ticket(second_ticket, &sec_ticket)) { + cleanup_authdata(); return retval; + } sec_ticket_arr[0] = sec_ticket; sec_ticket_arr[1] = 0; tgsreq.second_ticket = sec_ticket_arr; @@ -100,6 +165,7 @@ OLDDECLARG(krb5_response *,rep) if (retval) { if (sec_ticket) krb5_free_ticket(sec_ticket); + cleanup_authdata(); return(retval); } @@ -108,6 +174,7 @@ OLDDECLARG(krb5_response *,rep) if (sec_ticket) krb5_free_ticket(sec_ticket); krb5_free_data(scratch); + cleanup_authdata(); return ENOMEM; } @@ -121,6 +188,7 @@ OLDDECLARG(krb5_response *,rep) krb5_free_ticket(sec_ticket); xfree(ap_checksum.contents); krb5_free_data(scratch); + cleanup_authdata(); return retval; } /* done with body */ @@ -130,8 +198,6 @@ OLDDECLARG(krb5_response *,rep) if (sec_ticket) krb5_free_ticket(sec_ticket);} /* attach ap_req to the tgsreq */ - tgsreq.padata_type = KRB5_PADATA_AP_REQ; - /* * Get an ap_req. */ @@ -139,25 +205,62 @@ OLDDECLARG(krb5_response *,rep) &ap_checksum, 0, /* don't need times */ 0L, /* don't need kdc_options for this */ + 0, /* no initial sequence */ + 0, /* no new key */ 0, /* no ccache--already have creds */ usecred, 0, /* don't need authenticator */ - &tgsreq.padata)) { + &scratch2)) { cleanup(); + cleanup_authdata(); return retval; } + ap_req_padata.pa_type = KRB5_PADATA_AP_REQ; + ap_req_padata.length = scratch2.length; + ap_req_padata.contents = (krb5_octet *)scratch2.data; + + /* combine in any other supplied padata */ + if (padata) { + krb5_pa_data * const * counter; + register int i = 0; + for (counter = padata; *counter; counter++, i++); + combined_padata = (krb5_pa_data **)malloc(i+2); + if (!combined_padata) { + cleanup(); + cleanup_authdata(); + return ENOMEM; + } + combined_padata[0] = &ap_req_padata; + for (i = 1, counter = padata; *counter; counter++, i++) + combined_padata[i] = (krb5_pa_data *) *counter; + combined_padata[i] = 0; + } else { + combined_padata = (krb5_pa_data **)malloc(2*sizeof(*combined_padata)); + if (!combined_padata) { + cleanup(); + cleanup_authdata(); + return ENOMEM; + } + combined_padata[0] = &ap_req_padata; + combined_padata[1] = 0; + } + tgsreq.padata = combined_padata; /* the TGS_REQ is assembled in tgsreq, so encode it */ if (retval = encode_krb5_tgs_req(&tgsreq, &scratch)) { cleanup(); + cleanup_authdata(); + xfree(combined_padata); return(retval); } if (sec_ticket) krb5_free_ticket(sec_ticket); + cleanup_authdata(); + xfree(combined_padata); +#undef cleanup_authdata #undef cleanup -#define cleanup() {(void) free(tgsreq.padata.data); \ - xfree(ap_checksum.contents);} +#define cleanup() {xfree(ap_checksum.contents);} /* now send request & get response from KDC */ retval = krb5_sendto_kdc(scratch, krb5_princ_realm(sname), |