4 static krb5_boolean chk_heimdal_seqnum(krb5_ui_4, krb5_ui_4);
7 actx_copy_addr(krb5_context context, const krb5_address *inad, krb5_address **outad)
11 if (!(tmpad = (krb5_address *)malloc(sizeof(*tmpad))))
14 if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
18 memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length);
23 krb5_error_code KRB5_CALLCONV
24 krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context)
27 (krb5_auth_context)calloc(1, sizeof(struct _krb5_auth_context));
31 /* Default flags, do time not seq */
32 (*auth_context)->auth_context_flags =
33 KRB5_AUTH_CONTEXT_DO_TIME | KRB5_AUTH_CONN_INITIALIZED;
35 (*auth_context)->req_cksumtype = context->default_ap_req_sumtype;
36 (*auth_context)->safe_cksumtype = context->default_safe_sumtype;
37 (*auth_context)->checksum_func = NULL;
38 (*auth_context)->checksum_func_data = NULL;
39 (*auth_context)->negotiated_etype = ENCTYPE_NULL;
40 (*auth_context)->magic = KV5M_AUTH_CONTEXT;
44 krb5_error_code KRB5_CALLCONV
45 krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context)
47 if (auth_context->local_addr)
48 krb5_free_address(context, auth_context->local_addr);
49 if (auth_context->remote_addr)
50 krb5_free_address(context, auth_context->remote_addr);
51 if (auth_context->local_port)
52 krb5_free_address(context, auth_context->local_port);
53 if (auth_context->remote_port)
54 krb5_free_address(context, auth_context->remote_port);
55 if (auth_context->authentp)
56 krb5_free_authenticator(context, auth_context->authentp);
57 if (auth_context->keyblock)
58 krb5_free_keyblock(context, auth_context->keyblock);
59 if (auth_context->send_subkey)
60 krb5_free_keyblock(context, auth_context->send_subkey);
61 if (auth_context->recv_subkey)
62 krb5_free_keyblock(context, auth_context->recv_subkey);
63 if (auth_context->rcache)
64 krb5_rc_close(context, auth_context->rcache);
65 if (auth_context->permitted_etypes)
66 krb5_xfree(auth_context->permitted_etypes);
72 krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr)
74 krb5_error_code retval;
76 /* Free old addresses */
77 if (auth_context->local_addr)
78 (void) krb5_free_address(context, auth_context->local_addr);
79 if (auth_context->remote_addr)
80 (void) krb5_free_address(context, auth_context->remote_addr);
84 retval = actx_copy_addr(context,
86 &auth_context->local_addr);
88 auth_context->local_addr = NULL;
90 if (!retval && remote_addr)
91 retval = actx_copy_addr(context,
93 &auth_context->remote_addr);
95 auth_context->remote_addr = NULL;
100 krb5_error_code KRB5_CALLCONV
101 krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr)
103 krb5_error_code retval;
106 if (local_addr && auth_context->local_addr) {
107 retval = actx_copy_addr(context,
108 auth_context->local_addr,
111 if (!retval && (remote_addr) && auth_context->remote_addr) {
112 retval = actx_copy_addr(context,
113 auth_context->remote_addr,
119 krb5_error_code KRB5_CALLCONV
120 krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port)
122 krb5_error_code retval;
124 /* Free old addresses */
125 if (auth_context->local_port)
126 (void) krb5_free_address(context, auth_context->local_port);
127 if (auth_context->remote_port)
128 (void) krb5_free_address(context, auth_context->remote_port);
132 retval = actx_copy_addr(context,
134 &auth_context->local_port);
136 auth_context->local_port = NULL;
138 if (!retval && remote_port)
139 retval = actx_copy_addr(context,
141 &auth_context->remote_port);
143 auth_context->remote_port = NULL;
150 * This function overloads the keyblock field. It is only useful prior to
151 * a krb5_rd_req_decode() call for user to user authentication where the
152 * server has the key and needs to use it to decrypt the incoming request.
153 * Once decrypted this key is no longer necessary and is then overwritten
154 * with the session key sent by the client.
156 krb5_error_code KRB5_CALLCONV
157 krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock)
159 if (auth_context->keyblock)
160 krb5_free_keyblock(context, auth_context->keyblock);
161 return(krb5_copy_keyblock(context, keyblock, &(auth_context->keyblock)));
164 krb5_error_code KRB5_CALLCONV
165 krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
167 if (auth_context->keyblock)
168 return krb5_copy_keyblock(context, auth_context->keyblock, keyblock);
173 krb5_error_code KRB5_CALLCONV
174 krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
176 return krb5_auth_con_getsendsubkey(context, auth_context, keyblock);
179 krb5_error_code KRB5_CALLCONV
180 krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
182 return krb5_auth_con_getrecvsubkey(context, auth_context, keyblock);
185 krb5_error_code KRB5_CALLCONV
186 krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
188 if (ac->send_subkey != NULL)
189 krb5_free_keyblock(ctx, ac->send_subkey);
190 ac->send_subkey = NULL;
192 return krb5_copy_keyblock(ctx, keyblock, &ac->send_subkey);
197 krb5_error_code KRB5_CALLCONV
198 krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
200 if (ac->recv_subkey != NULL)
201 krb5_free_keyblock(ctx, ac->recv_subkey);
202 ac->recv_subkey = NULL;
203 if (keyblock != NULL)
204 return krb5_copy_keyblock(ctx, keyblock, &ac->recv_subkey);
209 krb5_error_code KRB5_CALLCONV
210 krb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
212 if (ac->send_subkey != NULL)
213 return krb5_copy_keyblock(ctx, ac->send_subkey, keyblock);
218 krb5_error_code KRB5_CALLCONV
219 krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
221 if (ac->recv_subkey != NULL)
222 return krb5_copy_keyblock(ctx, ac->recv_subkey, keyblock);
227 krb5_error_code KRB5_CALLCONV
228 krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
230 auth_context->req_cksumtype = cksumtype;
235 krb5_auth_con_set_safe_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
237 auth_context->safe_cksumtype = cksumtype;
241 krb5_error_code KRB5_CALLCONV
242 krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
244 *seqnumber = auth_context->local_seq_number;
248 krb5_error_code KRB5_CALLCONV
249 krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, krb5_authenticator **authenticator)
251 return (krb5_copy_authenticator(context, auth_context->authentp,
256 krb5_error_code KRB5_CALLCONV
257 krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
259 *seqnumber = auth_context->remote_seq_number;
263 krb5_error_code KRB5_CALLCONV
264 krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context)
268 if (auth_context->keyblock) {
271 if ((ret = krb5_c_block_size(context, auth_context->keyblock->enctype,
274 if ((auth_context->i_vector = (krb5_pointer)calloc(1,blocksize))) {
279 return EINVAL; /* XXX need an error for no keyblock */
283 krb5_auth_con_setivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer ivector)
285 auth_context->i_vector = ivector;
290 krb5_auth_con_getivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer *ivector)
292 *ivector = auth_context->i_vector;
296 krb5_error_code KRB5_CALLCONV
297 krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags)
299 auth_context->auth_context_flags = flags;
303 krb5_error_code KRB5_CALLCONV
304 krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 *flags)
306 *flags = auth_context->auth_context_flags;
310 krb5_error_code KRB5_CALLCONV
311 krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache)
313 auth_context->rcache = rcache;
318 krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache *rcache)
320 *rcache = auth_context->rcache;
325 krb5_auth_con_setpermetypes(krb5_context context, krb5_auth_context auth_context, const krb5_enctype *permetypes)
327 krb5_enctype * newpe;
330 for (i=0; permetypes[i]; i++)
332 i++; /* include the zero */
334 if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype)))
338 if (auth_context->permitted_etypes)
339 krb5_xfree(auth_context->permitted_etypes);
341 auth_context->permitted_etypes = newpe;
343 memcpy(newpe, permetypes, i*sizeof(krb5_enctype));
349 krb5_auth_con_getpermetypes(krb5_context context, krb5_auth_context auth_context, krb5_enctype **permetypes)
351 krb5_enctype * newpe;
354 if (! auth_context->permitted_etypes) {
359 for (i=0; auth_context->permitted_etypes[i]; i++)
361 i++; /* include the zero */
363 if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype)))
369 memcpy(newpe, auth_context->permitted_etypes, i*sizeof(krb5_enctype));
374 krb5_error_code KRB5_CALLCONV
375 krb5_auth_con_set_checksum_func( krb5_context context,
376 krb5_auth_context auth_context,
377 krb5_mk_req_checksum_func func,
380 auth_context->checksum_func = func;
381 auth_context->checksum_func_data = data;
385 krb5_error_code KRB5_CALLCONV
386 krb5_auth_con_get_checksum_func( krb5_context context,
387 krb5_auth_context auth_context,
388 krb5_mk_req_checksum_func *func,
391 *func = auth_context->checksum_func;
392 *data = auth_context->checksum_func_data;
397 * krb5int_auth_con_chkseqnum
399 * We use a somewhat complex heuristic for validating received
400 * sequence numbers. We must accommodate both our older
401 * implementation, which sends negative sequence numbers, and the
402 * broken Heimdal implementation (at least as of 0.5.2), which
403 * violates X.690 BER for integer encodings. The requirement of
404 * handling negative sequence numbers removes one of easier means of
405 * detecting a Heimdal implementation, so we resort to this mess
408 * X.690 BER (and consequently DER, which are the required encoding
409 * rules in RFC1510) encode all integer types as signed integers.
410 * This means that the MSB being set on the first octet of the
411 * contents of the encoding indicates a negative value. Heimdal does
412 * not prepend the required zero octet to unsigned integer encodings
413 * which would otherwise have the MSB of the first octet of their
416 * Our ASN.1 library implements a special decoder for sequence
417 * numbers, accepting both negative and positive 32-bit numbers but
418 * mapping them both into the space of positive unsigned 32-bit
419 * numbers in the obvious bit-pattern-preserving way. This maintains
420 * compatibility with our older implementations. This also means that
421 * encodings emitted by Heimdal are ambiguous.
423 * Heimdal counter value received uint32 value
425 * 0x00000080 0xFFFFFF80
426 * 0x000000FF 0xFFFFFFFF
427 * 0x00008000 0xFFFF8000
428 * 0x0000FFFF 0xFFFFFFFF
429 * 0x00800000 0xFF800000
430 * 0x00FFFFFF 0xFFFFFFFF
431 * 0xFF800000 0xFF800000
432 * 0xFFFFFFFF 0xFFFFFFFF
434 * We use two auth_context flags, SANE_SEQ and HEIMDAL_SEQ, which are
435 * only set after we can unambiguously determine the sanity of the
436 * sending implementation. Once one of these flags is set, we accept
437 * only the sequence numbers appropriate to the remote implementation
438 * type. We can make the determination in two different ways. The
439 * first is to note the receipt of a "negative" sequence number when a
440 * "positive" one was expected. The second is to note the receipt of
441 * a sequence number that wraps through "zero" in a weird way. The
442 * latter corresponds to the receipt of an initial sequence number in
443 * the ambiguous range.
445 * There are 2^7 + 2^15 + 2^23 + 2^23 = 16810112 total ambiguous
446 * initial Heimdal counter values, but we receive them as one of 2^23
447 * possible values. There is a ~1/256 chance of a Heimdal
448 * implementation sending an intial sequence number in the ambiguous
451 * We have to do special treatment when receiving sequence numbers
452 * between 0xFF800000..0xFFFFFFFF, or when wrapping through zero
453 * weirdly (due to ambiguous initial sequence number). If we are
454 * expecting a value corresponding to an ambiguous Heimdal counter
455 * value, and we receive an exact match, we can mark the remote end as
459 krb5int_auth_con_chkseqnum(
461 krb5_auth_context ac,
466 exp_seq = ac->remote_seq_number;
469 * If sender is known to be sane, accept _only_ exact matches.
471 if (ac->auth_context_flags & KRB5_AUTH_CONN_SANE_SEQ)
472 return in_seq == exp_seq;
475 * If sender is not known to be sane, first check the ambiguous
476 * range of received values, 0xFF800000..0xFFFFFFFF.
478 if ((in_seq & 0xFF800000) == 0xFF800000) {
480 * If expected sequence number is in the range
481 * 0xFF800000..0xFFFFFFFF, then we can't make any
482 * determinations about the sanity of the sending
485 if ((exp_seq & 0xFF800000) == 0xFF800000 && in_seq == exp_seq)
488 * If sender is not known for certain to be a broken Heimdal
489 * implementation, check for exact match.
491 if (!(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)
492 && in_seq == exp_seq)
495 * Now apply hairy algorithm for matching sequence numbers
496 * sent by broken Heimdal implementations. If it matches, we
497 * know for certain it's a broken Heimdal sender.
499 if (chk_heimdal_seqnum(exp_seq, in_seq)) {
500 ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
507 * Received value not in the ambiguous range? If the _expected_
508 * value is in the range of ambiguous Hemidal counter values, and
509 * it matches the received value, sender is known to be sane.
511 if (in_seq == exp_seq) {
512 if (( exp_seq & 0xFFFFFF80) == 0x00000080
513 || (exp_seq & 0xFFFF8000) == 0x00008000
514 || (exp_seq & 0xFF800000) == 0x00800000)
515 ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ;
520 * Magic wraparound for the case where the intial sequence number
521 * is in the ambiguous range. This means that the sender's
522 * counter is at a different count than ours, so we correct ours,
523 * and mark the sender as being a broken Heimdal implementation.
526 && !(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)) {
531 ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
542 chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq)
544 if (( exp_seq & 0xFF800000) == 0x00800000
545 && (in_seq & 0xFF800000) == 0xFF800000
546 && (in_seq & 0x00FFFFFF) == exp_seq)
548 else if (( exp_seq & 0xFFFF8000) == 0x00008000
549 && (in_seq & 0xFFFF8000) == 0xFFFF8000
550 && (in_seq & 0x0000FFFF) == exp_seq)
552 else if (( exp_seq & 0xFFFFFF80) == 0x00000080
553 && (in_seq & 0xFFFFFF80) == 0xFFFFFF80
554 && (in_seq & 0x000000FF) == exp_seq)
561 krb5_auth_con_get_subkey_enctype(krb5_context context,
562 krb5_auth_context auth_context,
565 *etype = auth_context->negotiated_etype;