From: Greg Hudson Date: Sat, 2 Apr 2011 17:30:45 +0000 (+0000) Subject: In libkrb5, move krb5int_auth_con_chkseqnum to a new file privsafe.c, X-Git-Tag: krb5-1.10-alpha1~502 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=cc81afac0c3fa99f02ae7f38c09d00cf3f24d3cf;p=krb5.git In libkrb5, move krb5int_auth_con_chkseqnum to a new file privsafe.c, renamed to k5_privsafe_check_seqnum. Declare it in int-proto.h rather than k5-int.h. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24805 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 85cd71763..5e1324b2e 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -2013,9 +2013,6 @@ krb5_encode_kdc_rep(krb5_context, krb5_msgtype, const krb5_enc_kdc_rep_part *, int using_subkey, const krb5_keyblock *, krb5_kdc_rep *, krb5_data ** ); -krb5_boolean -krb5int_auth_con_chkseqnum(krb5_context ctx, krb5_auth_context ac, - krb5_ui_4 in_seq); /* * [De]Serialization Handle and operations. */ diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 8270fd436..6a0faf29d 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -79,6 +79,7 @@ STLIBOBJS= \ preauth2.o \ gic_opt_set_pa.o \ princ_comp.o \ + privsafe.o \ rd_cred.o \ rd_error.o \ rd_priv.o \ @@ -181,6 +182,7 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ $(OUTPRE)preauth2.$(OBJEXT) \ $(OUTPRE)gic_opt_set_pa.$(OBJEXT) \ $(OUTPRE)princ_comp.$(OBJEXT) \ + $(OUTPRE)privsafe.$(OBJEXT) \ $(OUTPRE)rd_cred.$(OBJEXT) \ $(OUTPRE)rd_error.$(OBJEXT) \ $(OUTPRE)rd_priv.$(OBJEXT) \ @@ -283,6 +285,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/preauth2.c \ $(srcdir)/gic_opt_set_pa.c \ $(srcdir)/princ_comp.c \ + $(srcdir)/privsafe.c \ $(srcdir)/rd_cred.c \ $(srcdir)/rd_error.c \ $(srcdir)/rd_priv.c \ diff --git a/src/lib/krb5/krb/auth_con.c b/src/lib/krb5/krb/auth_con.c index 42e548271..2ffe345eb 100644 --- a/src/lib/krb5/krb/auth_con.c +++ b/src/lib/krb5/krb/auth_con.c @@ -28,8 +28,6 @@ #include "int-proto.h" #include "auth_con.h" -static krb5_boolean chk_heimdal_seqnum(krb5_ui_4, krb5_ui_4); - krb5_error_code KRB5_CALLCONV krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context) { @@ -425,170 +423,6 @@ krb5_auth_con_get_checksum_func( krb5_context context, return 0; } -/* - * krb5int_auth_con_chkseqnum - * - * We use a somewhat complex heuristic for validating received - * sequence numbers. We must accommodate both our older - * implementation, which sends negative sequence numbers, and the - * broken Heimdal implementation (at least as of 0.5.2), which - * violates X.690 BER for integer encodings. The requirement of - * handling negative sequence numbers removes one of easier means of - * detecting a Heimdal implementation, so we resort to this mess - * here. - * - * X.690 BER (and consequently DER, which are the required encoding - * rules in RFC1510) encode all integer types as signed integers. - * This means that the MSB being set on the first octet of the - * contents of the encoding indicates a negative value. Heimdal does - * not prepend the required zero octet to unsigned integer encodings - * which would otherwise have the MSB of the first octet of their - * encodings set. - * - * Our ASN.1 library implements a special decoder for sequence - * numbers, accepting both negative and positive 32-bit numbers but - * mapping them both into the space of positive unsigned 32-bit - * numbers in the obvious bit-pattern-preserving way. This maintains - * compatibility with our older implementations. This also means that - * encodings emitted by Heimdal are ambiguous. - * - * Heimdal counter value received uint32 value - * - * 0x00000080 0xFFFFFF80 - * 0x000000FF 0xFFFFFFFF - * 0x00008000 0xFFFF8000 - * 0x0000FFFF 0xFFFFFFFF - * 0x00800000 0xFF800000 - * 0x00FFFFFF 0xFFFFFFFF - * 0xFF800000 0xFF800000 - * 0xFFFFFFFF 0xFFFFFFFF - * - * We use two auth_context flags, SANE_SEQ and HEIMDAL_SEQ, which are - * only set after we can unambiguously determine the sanity of the - * sending implementation. Once one of these flags is set, we accept - * only the sequence numbers appropriate to the remote implementation - * type. We can make the determination in two different ways. The - * first is to note the receipt of a "negative" sequence number when a - * "positive" one was expected. The second is to note the receipt of - * a sequence number that wraps through "zero" in a weird way. The - * latter corresponds to the receipt of an initial sequence number in - * the ambiguous range. - * - * There are 2^7 + 2^15 + 2^23 + 2^23 = 16810112 total ambiguous - * initial Heimdal counter values, but we receive them as one of 2^23 - * possible values. There is a ~1/256 chance of a Heimdal - * implementation sending an intial sequence number in the ambiguous - * range. - * - * We have to do special treatment when receiving sequence numbers - * between 0xFF800000..0xFFFFFFFF, or when wrapping through zero - * weirdly (due to ambiguous initial sequence number). If we are - * expecting a value corresponding to an ambiguous Heimdal counter - * value, and we receive an exact match, we can mark the remote end as - * sane. - */ -krb5_boolean -krb5int_auth_con_chkseqnum( - krb5_context ctx, - krb5_auth_context ac, - krb5_ui_4 in_seq) -{ - krb5_ui_4 exp_seq; - - exp_seq = ac->remote_seq_number; - - /* - * If sender is known to be sane, accept _only_ exact matches. - */ - if (ac->auth_context_flags & KRB5_AUTH_CONN_SANE_SEQ) - return in_seq == exp_seq; - - /* - * If sender is not known to be sane, first check the ambiguous - * range of received values, 0xFF800000..0xFFFFFFFF. - */ - if ((in_seq & 0xFF800000) == 0xFF800000) { - /* - * If expected sequence number is in the range - * 0xFF800000..0xFFFFFFFF, then we can't make any - * determinations about the sanity of the sending - * implementation. - */ - if ((exp_seq & 0xFF800000) == 0xFF800000 && in_seq == exp_seq) - return 1; - /* - * If sender is not known for certain to be a broken Heimdal - * implementation, check for exact match. - */ - if (!(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ) - && in_seq == exp_seq) - return 1; - /* - * Now apply hairy algorithm for matching sequence numbers - * sent by broken Heimdal implementations. If it matches, we - * know for certain it's a broken Heimdal sender. - */ - if (chk_heimdal_seqnum(exp_seq, in_seq)) { - ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ; - return 1; - } - return 0; - } - - /* - * Received value not in the ambiguous range? If the _expected_ - * value is in the range of ambiguous Hemidal counter values, and - * it matches the received value, sender is known to be sane. - */ - if (in_seq == exp_seq) { - if (( exp_seq & 0xFFFFFF80) == 0x00000080 - || (exp_seq & 0xFFFF8000) == 0x00008000 - || (exp_seq & 0xFF800000) == 0x00800000) - ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ; - return 1; - } - - /* - * Magic wraparound for the case where the intial sequence number - * is in the ambiguous range. This means that the sender's - * counter is at a different count than ours, so we correct ours, - * and mark the sender as being a broken Heimdal implementation. - */ - if (exp_seq == 0 - && !(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)) { - switch (in_seq) { - case 0x100: - case 0x10000: - case 0x1000000: - ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ; - exp_seq = in_seq; - return 1; - default: - return 0; - } - } - return 0; -} - -static krb5_boolean -chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq) -{ - if (( exp_seq & 0xFF800000) == 0x00800000 - && (in_seq & 0xFF800000) == 0xFF800000 - && (in_seq & 0x00FFFFFF) == exp_seq) - return 1; - else if (( exp_seq & 0xFFFF8000) == 0x00008000 - && (in_seq & 0xFFFF8000) == 0xFFFF8000 - && (in_seq & 0x0000FFFF) == exp_seq) - return 1; - else if (( exp_seq & 0xFFFFFF80) == 0x00000080 - && (in_seq & 0xFFFFFF80) == 0xFFFFFF80 - && (in_seq & 0x000000FF) == exp_seq) - return 1; - else - return 0; -} - krb5_error_code krb5_auth_con_get_subkey_enctype(krb5_context context, krb5_auth_context auth_context, diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h index fe1461575..39f4c300d 100644 --- a/src/lib/krb5/krb/int-proto.h +++ b/src/lib/krb5/krb/int-proto.h @@ -152,4 +152,8 @@ krb5int_validate_times(krb5_context, krb5_ticket_times *); krb5_error_code krb5int_copy_authdatum(krb5_context, const krb5_authdata *, krb5_authdata **); +krb5_boolean +k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac, + krb5_ui_4 in_seq); + #endif /* KRB5_INT_FUNC_PROTO__ */ diff --git a/src/lib/krb5/krb/privsafe.c b/src/lib/krb5/krb/privsafe.c new file mode 100644 index 000000000..1a7722df8 --- /dev/null +++ b/src/lib/krb5/krb/privsafe.c @@ -0,0 +1,192 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/privsafe.c - Shared logic for KRB-SAFE and KRB-PRIV messages */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + * k5_privsafe_check_seqnum + * + * We use a somewhat complex heuristic for validating received + * sequence numbers. We must accommodate both our older + * implementation, which sends negative sequence numbers, and the + * broken Heimdal implementation (at least as of 0.5.2), which + * violates X.690 BER for integer encodings. The requirement of + * handling negative sequence numbers removes one of easier means of + * detecting a Heimdal implementation, so we resort to this mess + * here. + * + * X.690 BER (and consequently DER, which are the required encoding + * rules in RFC1510) encode all integer types as signed integers. + * This means that the MSB being set on the first octet of the + * contents of the encoding indicates a negative value. Heimdal does + * not prepend the required zero octet to unsigned integer encodings + * which would otherwise have the MSB of the first octet of their + * encodings set. + * + * Our ASN.1 library implements a special decoder for sequence + * numbers, accepting both negative and positive 32-bit numbers but + * mapping them both into the space of positive unsigned 32-bit + * numbers in the obvious bit-pattern-preserving way. This maintains + * compatibility with our older implementations. This also means that + * encodings emitted by Heimdal are ambiguous. + * + * Heimdal counter value received uint32 value + * + * 0x00000080 0xFFFFFF80 + * 0x000000FF 0xFFFFFFFF + * 0x00008000 0xFFFF8000 + * 0x0000FFFF 0xFFFFFFFF + * 0x00800000 0xFF800000 + * 0x00FFFFFF 0xFFFFFFFF + * 0xFF800000 0xFF800000 + * 0xFFFFFFFF 0xFFFFFFFF + * + * We use two auth_context flags, SANE_SEQ and HEIMDAL_SEQ, which are + * only set after we can unambiguously determine the sanity of the + * sending implementation. Once one of these flags is set, we accept + * only the sequence numbers appropriate to the remote implementation + * type. We can make the determination in two different ways. The + * first is to note the receipt of a "negative" sequence number when a + * "positive" one was expected. The second is to note the receipt of + * a sequence number that wraps through "zero" in a weird way. The + * latter corresponds to the receipt of an initial sequence number in + * the ambiguous range. + * + * There are 2^7 + 2^15 + 2^23 + 2^23 = 16810112 total ambiguous + * initial Heimdal counter values, but we receive them as one of 2^23 + * possible values. There is a ~1/256 chance of a Heimdal + * implementation sending an intial sequence number in the ambiguous + * range. + * + * We have to do special treatment when receiving sequence numbers + * between 0xFF800000..0xFFFFFFFF, or when wrapping through zero + * weirdly (due to ambiguous initial sequence number). If we are + * expecting a value corresponding to an ambiguous Heimdal counter + * value, and we receive an exact match, we can mark the remote end as + * sane. + */ + +static krb5_boolean +chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq) +{ + if (( exp_seq & 0xFF800000) == 0x00800000 + && (in_seq & 0xFF800000) == 0xFF800000 + && (in_seq & 0x00FFFFFF) == exp_seq) + return 1; + else if (( exp_seq & 0xFFFF8000) == 0x00008000 + && (in_seq & 0xFFFF8000) == 0xFFFF8000 + && (in_seq & 0x0000FFFF) == exp_seq) + return 1; + else if (( exp_seq & 0xFFFFFF80) == 0x00000080 + && (in_seq & 0xFFFFFF80) == 0xFFFFFF80 + && (in_seq & 0x000000FF) == exp_seq) + return 1; + else + return 0; +} + +krb5_boolean +k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac, + krb5_ui_4 in_seq) +{ + krb5_ui_4 exp_seq; + + exp_seq = ac->remote_seq_number; + + /* + * If sender is known to be sane, accept _only_ exact matches. + */ + if (ac->auth_context_flags & KRB5_AUTH_CONN_SANE_SEQ) + return in_seq == exp_seq; + + /* + * If sender is not known to be sane, first check the ambiguous + * range of received values, 0xFF800000..0xFFFFFFFF. + */ + if ((in_seq & 0xFF800000) == 0xFF800000) { + /* + * If expected sequence number is in the range + * 0xFF800000..0xFFFFFFFF, then we can't make any + * determinations about the sanity of the sending + * implementation. + */ + if ((exp_seq & 0xFF800000) == 0xFF800000 && in_seq == exp_seq) + return 1; + /* + * If sender is not known for certain to be a broken Heimdal + * implementation, check for exact match. + */ + if (!(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ) + && in_seq == exp_seq) + return 1; + /* + * Now apply hairy algorithm for matching sequence numbers + * sent by broken Heimdal implementations. If it matches, we + * know for certain it's a broken Heimdal sender. + */ + if (chk_heimdal_seqnum(exp_seq, in_seq)) { + ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ; + return 1; + } + return 0; + } + + /* + * Received value not in the ambiguous range? If the _expected_ + * value is in the range of ambiguous Hemidal counter values, and + * it matches the received value, sender is known to be sane. + */ + if (in_seq == exp_seq) { + if (( exp_seq & 0xFFFFFF80) == 0x00000080 + || (exp_seq & 0xFFFF8000) == 0x00008000 + || (exp_seq & 0xFF800000) == 0x00800000) + ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ; + return 1; + } + + /* + * Magic wraparound for the case where the intial sequence number + * is in the ambiguous range. This means that the sender's + * counter is at a different count than ours, so we correct ours, + * and mark the sender as being a broken Heimdal implementation. + */ + if (exp_seq == 0 + && !(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)) { + switch (in_seq) { + case 0x100: + case 0x10000: + case 0x1000000: + ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ; + exp_seq = in_seq; + return 1; + default: + return 0; + } + } + return 0; +} diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index 64b191af8..e8fa200b0 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -25,6 +25,7 @@ */ #include "k5-int.h" +#include "int-proto.h" #include "cleanup.h" #include "auth_con.h" @@ -244,8 +245,7 @@ krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { - if (!krb5int_auth_con_chkseqnum(context, auth_context, - replaydata.seq)) { + if (!k5_privsafe_check_seqnum(context, auth_context, replaydata.seq)) { retval = KRB5KRB_AP_ERR_BADORDER; goto error; } diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c index baeb281e3..74e7e9497 100644 --- a/src/lib/krb5/krb/rd_safe.c +++ b/src/lib/krb5/krb/rd_safe.c @@ -25,6 +25,7 @@ */ #include "k5-int.h" +#include "int-proto.h" #include "cleanup.h" #include "auth_con.h" @@ -250,8 +251,7 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { - if (!krb5int_auth_con_chkseqnum(context, auth_context, - replaydata.seq)) { + if (!k5_privsafe_check_seqnum(context, auth_context, replaydata.seq)) { retval = KRB5KRB_AP_ERR_BADORDER; goto error; }