Sequence numbers are now unsigned. Implement lenient parser for
authorTom Yu <tlyu@mit.edu>
Sun, 18 May 2003 05:16:05 +0000 (05:16 +0000)
committerTom Yu <tlyu@mit.edu>
Sun, 18 May 2003 05:16:05 +0000 (05:16 +0000)
sequence numbers which folds received negative sequence numbers into
positive unsigned numbers.  Constrain the space of initial sequence
numbers to facilitate backwards compatibility.

ticket: 1262
status: open

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15457 dc483132-0cff-0310-8789-dd5450dbe970

16 files changed:
src/include/ChangeLog
src/include/k5-int.h
src/include/krb5.hin
src/lib/krb5/asn.1/ChangeLog
src/lib/krb5/asn.1/asn1_decode.c
src/lib/krb5/asn.1/asn1_decode.h
src/lib/krb5/asn.1/asn1_k_decode.c
src/lib/krb5/asn.1/asn1_k_decode.h
src/lib/krb5/asn.1/krb5_decode.c
src/lib/krb5/asn.1/krb5_encode.c
src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/auth_con.h
src/lib/krb5/krb/gen_seqnum.c
src/tests/asn.1/ChangeLog
src/tests/asn.1/krb5_decode_test.c
src/tests/asn.1/utility.c

index 123ba7ea0bc164e13293b28b6836977dc839f7d9..05817aea1649c8f3e98bb6756784107f98a64206 100644 (file)
@@ -1,3 +1,9 @@
+2003-05-18  Tom Yu  <tlyu@mit.edu>
+
+       * k5-int.h: Sequence numbers are now unsigned.
+
+       * krb5.hin: Sequence numbers are now unsigned.
+
 2003-05-16  Ken Raeburn  <raeburn@mit.edu>
 
        * krb5.hin (KRB5_KPASSWD_ACCESSDENIED): New macro.
index 086b7df71423187379fac33cadbcaf6156e4e0e1..08c7a7a4fd89eb5d80cd73b7405affdc54b1401d 100644 (file)
@@ -1050,7 +1050,7 @@ typedef struct _krb5_safe {
     krb5_timestamp timestamp;          /* client time, optional */
     krb5_int32 usec;                   /* microsecond portion of time,
                                           optional */
-    krb5_int32 seq_number;             /* sequence #, optional */
+    krb5_ui_4 seq_number;              /* sequence #, optional */
     krb5_address *s_address;   /* sender address */
     krb5_address *r_address;   /* recipient address, optional */
     krb5_checksum *checksum;   /* data integrity checksum */
@@ -1066,7 +1066,7 @@ typedef struct _krb5_priv_enc_part {
     krb5_data user_data;               /* user data */
     krb5_timestamp timestamp;          /* client time, optional */
     krb5_int32 usec;                   /* microsecond portion of time, opt. */
-    krb5_int32 seq_number;             /* sequence #, optional */
+    krb5_ui_4 seq_number;              /* sequence #, optional */
     krb5_address *s_address;   /* sender address */
     krb5_address *r_address;   /* recipient address, optional */
 } krb5_priv_enc_part;
index 310eb39768a0a368860d499f69269809c000dc18..0bf822e4ab665fb34b6aacef3ae7a636021e22e2 100644 (file)
@@ -974,7 +974,7 @@ typedef struct _krb5_authenticator {
     krb5_int32 cusec;                  /* client usec portion */
     krb5_timestamp ctime;              /* client sec portion */
     krb5_keyblock *subkey;             /* true session key, optional */
-    krb5_int32 seq_number;             /* sequence #, optional */
+    krb5_ui_4 seq_number;              /* sequence #, optional */
     krb5_authdata **authorization_data; /* New add by Ari, auth data */
 } krb5_authenticator;
 
@@ -1100,7 +1100,7 @@ typedef struct _krb5_ap_rep_enc_part {
     krb5_timestamp ctime;              /* client time, seconds portion */
     krb5_int32 cusec;                  /* client time, microseconds portion */
     krb5_keyblock *subkey;             /* true session key, optional */
-    krb5_int32 seq_number;             /* sequence #, optional */
+    krb5_ui_4 seq_number;              /* sequence #, optional */
 } krb5_ap_rep_enc_part;
 
 typedef struct _krb5_response {
@@ -1644,7 +1644,7 @@ krb5_error_code krb5_generate_subkey
                const krb5_keyblock *, krb5_keyblock **);
 krb5_error_code krb5_generate_seq_number
        (krb5_context,
-               const krb5_keyblock *, krb5_int32 *);
+               const krb5_keyblock *, krb5_ui_4 *);
 #endif
 krb5_error_code KRB5_CALLCONV krb5_get_server_rcache
        (krb5_context,
index c4bd9bc08d6369faf275df87f93025730de176a1..dd85a3c7a673d2dac840823b9837787a608a1833 100644 (file)
@@ -1,3 +1,25 @@
+2003-05-18  Tom Yu  <tlyu@mit.edu>
+
+       * asn1_decode.c (asn1_decode_maybe_unsigned): New function; decode
+       negative 32-bit numbers into positive unsigned numbers for the
+       sake of backwards compatibility with old code.
+
+       * asn1_decode.h: Add prototype for asn1_decode_maybe_unsigned.
+
+       * asn1_k_decode.c (asn1_decode_seqnum): New function; wrapper
+       around asn1_decode_maybe_unsigned.
+
+       * asn1_k_decode.h: Add prototype for asn1_decode_seqnum.
+
+       * krb5_decode.c (decode_krb5_authenticator) 
+       (decode_krb5_ap_rep_enc_part, decode_krb5_enc_priv_part): Sequence
+       numbers are now unsigned.  Use asn1_decode_seqnum to handle
+       backwards compat with negative sequence numbers.
+
+       * krb5_encode.c (encode_krb5_authenticator) 
+       (encode_krb5_ap_rep_enc_part, encode_krb5_enc_priv_part): Sequence
+       numbers are now unsigned.
+
 2003-05-06  Sam Hartman  <hartmans@mit.edu>
 
        * krb5_decode.c (decode_krb5_etype_info2): New function; currently
index 56904c5eea1b29a1ec35a24da0fe97f53179b03b..65863202aab129da693849ae44ca0b4f91a7b64e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * src/lib/krb5/asn.1/asn1_decode.c
  * 
- * Copyright 1994 by the Massachusetts Institute of Technology.
+ * Copyright 1994, 2003 by the Massachusetts Institute of Technology.
  * All Rights Reserved.
  *
  * Export of this software from the United States of America may
@@ -106,6 +106,50 @@ asn1_error_code asn1_decode_unsigned_integer(asn1buf *buf, long unsigned int *va
   cleanup();
 }
 
+/*
+ * asn1_decode_maybe_unsigned
+ *
+ * This is needed because older releases of MIT krb5 have signed
+ * sequence numbers.  We want to accept both signed and unsigned
+ * sequence numbers, in the range -2^31..2^32-1, mapping negative
+ * numbers into their positive equivalents in the same way that C's
+ * normal integer conversions do, i.e., would preserve bits on a
+ * two's-complement architecture.
+ */
+asn1_error_code asn1_decode_maybe_unsigned(asn1buf *buf, unsigned long *val)
+{
+  setup();
+  asn1_octet o;
+  unsigned long n, bitsremain;
+  unsigned int i;
+
+  tag(ASN1_INTEGER);
+  o = 0;
+  n = 0;
+  bitsremain = ~0UL;
+  for (i = 0; i < length; i++) {
+    /* Accounts for u_long width not being a multiple of 8. */
+    if (bitsremain < 0xff) return ASN1_OVERFLOW;
+    retval = asn1buf_remove_octet(buf, &o);
+    if (retval) return retval;
+    if (bitsremain == ~0UL) {
+      if (i == 0)
+       n = (o & 0x80) ? ~0UL : 0UL; /* grab sign bit */
+      /*
+       * Skip leading zero or 0xFF octets to humor non-compliant encoders.
+       */
+      if (n == 0 && o == 0)
+       continue;
+      if (n == ~0UL && o == 0xff)
+       continue;
+    }
+    n = (n << 8) | o;
+    bitsremain >>= 8;
+  }
+  *val = n;
+  cleanup();
+}
+
 asn1_error_code asn1_decode_oid(asn1buf *buf, unsigned int *retlen, asn1_octet **val)
 {
   setup();
index 449a589003b72e97236a8dbdfa99629b10d3210d..cafbf3fd34846e49a997f8bebbfc651c852103ff 100644 (file)
@@ -62,6 +62,8 @@ asn1_error_code asn1_decode_integer
        (asn1buf *buf, long *val);
 asn1_error_code asn1_decode_unsigned_integer
        (asn1buf *buf, unsigned long *val);
+asn1_error_code asn1_decode_maybe_unsigned
+       (asn1buf *buf, unsigned long *val);
 asn1_error_code asn1_decode_null
        (asn1buf *buf);
 
index e56832a7b635e11c4f9e6fff0460eca1873a6e7d..f00cb01615118f1c9040219ab86b56a57fa15f6d 100644 (file)
@@ -320,6 +320,17 @@ integer_convert(asn1_decode_authdatatype,krb5_authdatatype)
 unsigned_integer_convert(asn1_decode_ui_2,krb5_ui_2)
 unsigned_integer_convert(asn1_decode_ui_4,krb5_ui_4)
 
+asn1_error_code asn1_decode_seqnum(asn1buf *buf, krb5_ui_4 *val)
+{
+  asn1_error_code retval;
+  unsigned long n;
+
+  retval = asn1_decode_maybe_unsigned(buf, &n);
+  if (retval) return retval;
+  *val = (krb5_ui_4)n & 0xffffffff;
+  return 0;
+}
+
 asn1_error_code asn1_decode_msgtype(asn1buf *buf, krb5_msgtype *val)
 {
   asn1_error_code retval;
index 8f8b0bcffe98451f81bf52d465688ff2c26a351d..e2639dda3b214c56caf97bd5fd216c39b98eaa65 100644 (file)
@@ -89,6 +89,8 @@ asn1_error_code asn1_decode_ui_2
        (asn1buf *buf, krb5_ui_2 *val);
 asn1_error_code asn1_decode_ui_4
        (asn1buf *buf, krb5_ui_4 *val);
+asn1_error_code asn1_decode_seqnum
+       (asn1buf *buf, krb5_ui_4 *val);
 asn1_error_code asn1_decode_kerberos_time
        (asn1buf *buf, krb5_timestamp *val);
 asn1_error_code asn1_decode_sam_flags
index b39bae5c41495e51056145242d828300cb5e6157..1ca57e93084f05d85f1bc383a0b915021573a3f4 100644 (file)
@@ -219,7 +219,7 @@ krb5_error_code decode_krb5_authenticator(const krb5_data *code, krb5_authentica
     get_field((*rep)->ctime,5,asn1_decode_kerberos_time);
     if(tagnum == 6){ alloc_field((*rep)->subkey,krb5_keyblock); }
     opt_field(*((*rep)->subkey),6,asn1_decode_encryption_key);
-    opt_field((*rep)->seq_number,7,asn1_decode_int32);
+    opt_field((*rep)->seq_number,7,asn1_decode_seqnum);
     opt_field((*rep)->authorization_data,8,asn1_decode_authorization_data);
     (*rep)->magic = KV5M_AUTHENTICATOR;
     end_structure();
@@ -440,7 +440,7 @@ krb5_error_code decode_krb5_ap_rep_enc_part(const krb5_data *code, krb5_ap_rep_e
     get_field((*rep)->cusec,1,asn1_decode_int32);
     if(tagnum == 2){ alloc_field((*rep)->subkey,krb5_keyblock); }
     opt_field(*((*rep)->subkey),2,asn1_decode_encryption_key);
-    opt_field((*rep)->seq_number,3,asn1_decode_int32);
+    opt_field((*rep)->seq_number,3,asn1_decode_seqnum);
     end_structure();
     (*rep)->magic = KV5M_AP_REP_ENC_PART;
   }
@@ -561,7 +561,7 @@ krb5_error_code decode_krb5_enc_priv_part(const krb5_data *code, krb5_priv_enc_p
     get_lenfield((*rep)->user_data.length,(*rep)->user_data.data,0,asn1_decode_charstring);
     opt_field((*rep)->timestamp,1,asn1_decode_kerberos_time);
     opt_field((*rep)->usec,2,asn1_decode_int32);
-    opt_field((*rep)->seq_number,3,asn1_decode_int32);
+    opt_field((*rep)->seq_number,3,asn1_decode_seqnum);
     alloc_field((*rep)->s_address,krb5_address);
     get_field(*((*rep)->s_address),4,asn1_decode_host_address);
     if(tagnum == 5){ alloc_field((*rep)->r_address,krb5_address); }
index 7412209f696e171effef3859c3581a1641206df6..eed6faf451563d2642f26d9829ddcbbb5bbdab7a 100644 (file)
@@ -166,7 +166,7 @@ krb5_error_code encode_krb5_authenticator(const krb5_authenticator *rep, krb5_da
 
   /* seq-number[7]             INTEGER OPTIONAL */
   if(rep->seq_number != 0)
-    krb5_addfield(rep->seq_number,7,asn1_encode_integer);
+    krb5_addfield(rep->seq_number,7,asn1_encode_unsigned_integer);
 
   /* subkey[6]                 EncryptionKey OPTIONAL */
   if(rep->subkey != NULL)
@@ -305,6 +305,7 @@ krb5_error_code encode_krb5_enc_kdc_rep_part(const krb5_enc_kdc_rep_part *rep, k
 #ifdef KRB5_ENCKRB5KDCREPPART_COMPAT
   krb5_apptag(26);
 #else
+  /* XXX WRONG!!! Should use 25 || 26, not the outer KDC_REP tags! */
   if (rep->msg_type == KRB5_AS_REP) { krb5_apptag(ASN1_KRB_AS_REP); }
   else if (rep->msg_type == KRB5_TGS_REP) { krb5_apptag(ASN1_KRB_TGS_REP); }
   else return KRB5_BADMSGTYPE;
@@ -395,7 +396,7 @@ krb5_error_code encode_krb5_ap_rep_enc_part(const krb5_ap_rep_enc_part *rep, krb
 
   /* seq-number[3]     INTEGER OPTIONAL */
   if(rep->seq_number)
-    krb5_addfield(rep->seq_number,3,asn1_encode_integer);
+    krb5_addfield(rep->seq_number,3,asn1_encode_unsigned_integer);
 
   /* subkey[2]         EncryptionKey OPTIONAL */
   if(rep->subkey != NULL)
@@ -510,7 +511,7 @@ krb5_error_code encode_krb5_enc_priv_part(const krb5_priv_enc_part *rep, krb5_da
 
   /* seq-number[3]     INTEGER OPTIONAL */
   if(rep->seq_number)
-    krb5_addfield(rep->seq_number,3,asn1_encode_integer);
+    krb5_addfield(rep->seq_number,3,asn1_encode_unsigned_integer);
 
   /* usec[2]           INTEGER OPTIONAL */
   if(rep->timestamp){
index 5ceee6685019cf57e05bba38c85c2ca887a265b4..8f34cf0bb517384c3d0b1f317f0bbe6f2fa02e43 100644 (file)
@@ -1,3 +1,10 @@
+2003-05-18  Tom Yu  <tlyu@mit.edu>
+
+       * auth_con.h: Sequence numbers are now unsigned.
+
+       * gen_seqnum.c (krb5_generate_seq_number): Constrain initial
+       sequence number space to facilitate backwards compatibility.
+
 2003-05-16  Ken Raeburn  <raeburn@mit.edu>
 
        * ser_ctx.c (krb5_context_internalize): Copy read-in OS context
index 1dcfc89e7b170acbdfd24e929e3bb9bd002cba34..362909ce775894ac995c43f8fb2fcd032b1aa319 100644 (file)
@@ -13,8 +13,8 @@ struct _krb5_auth_context {
     krb5_keyblock     * recv_subkey;
 
     krb5_int32         auth_context_flags;
-    krb5_int32         remote_seq_number;
-    krb5_int32         local_seq_number;
+    krb5_ui_4          remote_seq_number;
+    krb5_ui_4          local_seq_number;
     krb5_authenticator *authentp;              /* mk_req, rd_req, mk_rep, ...*/
     krb5_cksumtype     req_cksumtype;          /* mk_safe, ... */
     krb5_cksumtype     safe_cksumtype;         /* mk_safe, ... */
index 196a4374474e53da0ef584fb537a2faf6a1cd0c4..1dc8a58b13fc357f257d5942d98dedb9e939b7ad 100644 (file)
@@ -36,7 +36,7 @@
 #endif
 
 krb5_error_code
-krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_int32 *seqno)
+krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_ui_4 *seqno)
 {
     krb5_data seed;
     krb5_error_code retval;
@@ -48,5 +48,20 @@ krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_in
 
     seed.length = sizeof(*seqno);
     seed.data = (char *) seqno;
-    return(krb5_c_random_make_octets(context, &seed));
+    retval = krb5_c_random_make_octets(context, &seed);
+    if (retval)
+       return retval;
+    /*
+     * Work around implementation incompatibilities by not generating
+     * initial sequence numbers greater than 2^30.  Previous MIT
+     * implementations use signed sequence numbers, so initial
+     * sequence numbers 2^31 to 2^32-1 inclusive will be rejected.
+     * Letting the maximum initial sequence number be 2^30-1 allows
+     * for about 2^30 messages to be sent before wrapping into
+     * "negative" numbers.
+     */
+    *seqno &= 0x5ffffff;
+    if (*seqno == 0)
+       *seqno = 1;
+    return 0;
 }
index 2fefd05f36329fac81f0ffb9da8c16a92405d1ba..6bed2ccf6670e435cee1b434c3373795c06537ce 100644 (file)
@@ -1,3 +1,11 @@
+2003-05-18  Tom Yu  <tlyu@mit.edu>
+
+       * krb5_decode_test.c (main): Add new test cases for sequence
+       number compatibility.
+
+       * utility.c (krb5_data_hex_parse): Rewrite to be more lenient
+       about whitespace.
+
 2003-05-12  Ezra Peisach  <epeisach@mit.edu>
 
        * krb5_decode_test.c: Modify decode_run macro to take a cleanup
index b86c9fc8c093cf9f2e9405dc7e0128680a94bc80..c205232d9a27966d13d3697db5f442a2b335eff2 100644 (file)
@@ -60,6 +60,174 @@ int main(argc, argv)
 
     decode_run("authenticator","","62 81 A1 30 81 9E A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A7 03 02 01 11 A8 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72",decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
 
+    ref.seq_number = 0xffffff80;
+    decode_run("authenticator","(80 -> seq-number 0xffffff80)",
+              "62 81 A1 30 81 9E"
+              "   A0 03 02 01 05"
+              "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+              "   A2 1A 30 18"
+              "      A0 03 02 01 01"
+              "      A1 11 30 0F"
+              "         1B 06 68 66 74 73 61 69"
+              "         1B 05 65 78 74 72 61"
+              "   A3 0F 30 0D"
+              "      A0 03 02 01 01"
+              "      A1 06 04 04 31 32 33 34"
+              "   A4 05 02 03 01 E2 40"
+              "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+              "   A6 13 30 11"
+              "      A0 03 02 01 01"
+              "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+              "   A7 03 02 01 80"
+              "   A8 24 30 22"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xffffffff;
+    decode_run("authenticator","(FF -> seq-number 0xffffffff)",
+              "62 81 A1 30 81 9E"
+              "   A0 03 02 01 05"
+              "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+              "   A2 1A 30 18"
+              "      A0 03 02 01 01"
+              "      A1 11 30 0F"
+              "         1B 06 68 66 74 73 61 69"
+              "         1B 05 65 78 74 72 61"
+              "   A3 0F 30 0D"
+              "      A0 03 02 01 01"
+              "      A1 06 04 04 31 32 33 34"
+              "   A4 05 02 03 01 E2 40"
+              "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+              "   A6 13 30 11"
+              "      A0 03 02 01 01"
+              "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+              "   A7 03 02 01 FF"
+              "   A8 24 30 22"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xff;
+    decode_run("authenticator","(00FF -> seq-number 0xff)",
+              "62 81 A2 30 81 9F"
+              "   A0 03 02 01 05"
+              "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+              "   A2 1A 30 18"
+              "      A0 03 02 01 01"
+              "      A1 11 30 0F"
+              "         1B 06 68 66 74 73 61 69"
+              "         1B 05 65 78 74 72 61"
+              "   A3 0F 30 0D"
+              "      A0 03 02 01 01"
+              "      A1 06 04 04 31 32 33 34"
+              "   A4 05 02 03 01 E2 40"
+              "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+              "   A6 13 30 11"
+              "      A0 03 02 01 01"
+              "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+              "   A7 04 02 02 00 FF"
+              "   A8 24 30 22"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xffffffff;
+    decode_run("authenticator","(00FFFFFFFF -> seq-number 0xffffffff)",
+              "62 81 A5 30 81 A2"
+              "   A0 03 02 01 05"
+              "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+              "   A2 1A 30 18"
+              "      A0 03 02 01 01"
+              "      A1 11 30 0F"
+              "         1B 06 68 66 74 73 61 69"
+              "         1B 05 65 78 74 72 61"
+              "   A3 0F 30 0D"
+              "      A0 03 02 01 01"
+              "      A1 06 04 04 31 32 33 34"
+              "   A4 05 02 03 01 E2 40"
+              "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+              "   A6 13 30 11"
+              "      A0 03 02 01 01"
+              "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+              "   A7 07 02 05 00 FF FF FF FF"
+              "   A8 24 30 22"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0x7fffffff;
+    decode_run("authenticator","(7FFFFFFF -> seq-number 0x7fffffff)",
+              "62 81 A4 30 81 A1"
+              "   A0 03 02 01 05"
+              "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+              "   A2 1A 30 18"
+              "      A0 03 02 01 01"
+              "      A1 11 30 0F"
+              "         1B 06 68 66 74 73 61 69"
+              "         1B 05 65 78 74 72 61"
+              "   A3 0F 30 0D"
+              "      A0 03 02 01 01"
+              "      A1 06 04 04 31 32 33 34"
+              "   A4 05 02 03 01 E2 40"
+              "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+              "   A6 13 30 11"
+              "      A0 03 02 01 01"
+              "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+              "   A7 06 02 04 7F FF FF FF"
+              "   A8 24 30 22"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
+    ref.seq_number = 0xffffffff;
+    decode_run("authenticator","(FFFFFFFF -> seq-number 0xffffffff)",
+              "62 81 A4 30 81 A1"
+              "   A0 03 02 01 05"
+              "   A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55"
+              "   A2 1A 30 18"
+              "      A0 03 02 01 01"
+              "      A1 11 30 0F"
+              "         1B 06 68 66 74 73 61 69"
+              "         1B 05 65 78 74 72 61"
+              "   A3 0F 30 0D"
+              "      A0 03 02 01 01"
+              "      A1 06 04 04 31 32 33 34"
+              "   A4 05 02 03 01 E2 40"
+              "   A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A"
+              "   A6 13 30 11"
+              "      A0 03 02 01 01"
+              "      A1 0A 04 08 31 32 33 34 35 36 37 38"
+              "   A7 06 02 04 FF FF FF FF"
+              "   A8 24 30 22"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              "      30 0F"
+              "         A0 03 02 01 01"
+              "         A1 08 04 06 66 6F 6F 62 61 72"
+              ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator);
+
     ktest_destroy_checksum(&(ref.checksum));
     ktest_destroy_keyblock(&(ref.subkey));
     ref.seq_number = 0;
index 76fa79ef857cae794d374fd58f109059d2313cff..526cdce2d3d5d0f464b1fe4a1dc3c84bc0715a27 100644 (file)
@@ -2,6 +2,7 @@
 #include "utility.h"
 #include <stdlib.h>
 #include <stdio.h>
+#include <ctype.h>
 
 char hexchar (const unsigned int digit);
 
@@ -60,35 +61,40 @@ krb5_error_code krb5_data_parse(d, s)
   return 0;
 }
 
-krb5_error_code krb5_data_hex_parse(d, s)
-     krb5_data * d;
-     const char * s;
+krb5_error_code krb5_data_hex_parse(krb5_data *d, const char *s)
 {
-  int i, digit;
-  char *copy; 
-  char *pos;
+    int lo;
+    long v;
+    const char *cp;
+    char *dp;
+    char buf[2];
 
-    /* 
-     * Do a strdup() and use that, because some systems can't handle non
-     * writeable strings being passed to sscanf() --proven.
-     */
-    copy = strdup(s);
-  d->data = (char*)calloc((strlen(copy)+1)/3,sizeof(char));
-  if(d->data == NULL) return ENOMEM;
-  d->length = (strlen(copy)+1)/3;
-  for(i=0,pos=(char*)copy; i<d->length; i++,pos+=3){
-    if(!sscanf(pos,"%x",&digit)) {
-#ifdef KRB5_USE_ISODE
-           return EINVAL;
-#else
+    d->data = calloc((strlen(s) / 2 + 1), 1);
+    if (d->data == NULL)
+       return ENOMEM;
+    d->length = 0;
+    buf[1] = '\0';
+    for (lo = 0, dp = d->data, cp = s; *cp; cp++) {
+       if (*cp < 0)
            return ASN1_PARSE_ERROR;
-#endif
+       else if (isspace(*cp))
+           continue;
+       else if (isxdigit(*cp)) {
+           buf[0] = *cp;
+           v = strtol(buf, NULL, 16);
+       } else
+           return ASN1_PARSE_ERROR;
+       if (lo) {
+           *dp++ |= v;
+           lo = 0;
+       } else {
+           *dp = v << 4;
+           lo = 1;
+       }
     }
-    d->data[i] = (char)digit;
-  }
-  if (copy)
-    free(copy);
-  return 0;
+
+    d->length = dp - d->data;
+    return 0;
 }
 
 #if 0