]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
acceptor subkeys; fix flag bits; test CFX_EXERCISE
authorKen Raeburn <raeburn@mit.edu>
Sat, 6 Dec 2003 00:03:08 +0000 (00:03 +0000)
committerKen Raeburn <raeburn@mit.edu>
Sat, 6 Dec 2003 00:03:08 +0000 (00:03 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/raeburn-gssapi-cfx@15863 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/gssapi/krb5/accept_sec_context.c
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/krb5/k5sealv3.c

index 55e9c2a9a3927b641d171f05c88dabf794bf005a..716e12686bbccd2a0f82638413340eb6246b5cb4 100644 (file)
 #endif
 #include <assert.h>
 
+#ifdef CFX_EXERCISE
+#define CFX_ACCEPTOR_SUBKEY (time(0) & 1)
+#else
+#define CFX_ACCEPTOR_SUBKEY 1
+#endif
+
 /* Decode, decrypt and store the forwarded creds in the local ccache. */
 static krb5_error_code
 rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
@@ -715,6 +721,25 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
    if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
        unsigned char * ptr3;
        krb5_ui_4 seq_temp;
+       int cfx_generate_subkey;
+
+       if (ctx->proto == 1)
+          cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY;
+       else
+          cfx_generate_subkey = 0;
+
+       if (cfx_generate_subkey) {
+          krb5_int32 acflags;
+          code = krb5_auth_con_getflags(context, auth_context, &acflags);
+          if (code == 0) {
+              acflags |= KRB5_AUTH_CONTEXT_USE_SUBKEY;
+              code = krb5_auth_con_setflags(context, auth_context, acflags);
+          }
+          if (code) {
+              major_status = GSS_S_FAILURE;
+              goto fail;
+          }
+       }
 
        if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
           major_status = GSS_S_FAILURE;
@@ -724,6 +749,25 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
        krb5_auth_con_getlocalseqnumber(context, auth_context, &seq_temp);
        ctx->seq_send = seq_temp & 0xffffffffL;
 
+       if (cfx_generate_subkey) {
+          /* Get the new acceptor subkey.  With the code above, there
+             should always be one if we make it to this point.  */
+          code = krb5_auth_con_getsendsubkey(context, auth_context,
+                                             &ctx->acceptor_subkey);
+          if (code != 0) {
+              major_status = GSS_S_FAILURE;
+              goto fail;
+          }
+          code = krb5int_c_mandatory_cksumtype(context,
+                                               ctx->acceptor_subkey->enctype,
+                                               &ctx->acceptor_subkey_cksumtype);
+          if (code) {
+              major_status = GSS_S_FAILURE;
+              goto fail;
+          }
+          ctx->have_acceptor_subkey = 1;
+       }
+
        /* the reply token hasn't been sent yet, but that's ok. */
        ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
        ctx->established = 1;
index 9fdc7b07dc1f40fb5624e3cc97f88febef66e76f..4a06a208dc18c096a1b68f54d560c0bf027d4d74 100644 (file)
@@ -819,7 +819,12 @@ mutual_auth(
        /* Keep acceptor's subkey.  */
        ctx->have_acceptor_subkey = 1;
        code = krb5_copy_keyblock(context, ap_rep_data->subkey,
-                                &ctx->subkey);
+                                &ctx->acceptor_subkey);
+       if (code)
+          goto fail;
+       code = krb5int_c_mandatory_cksumtype(context,
+                                           ctx->acceptor_subkey->enctype,
+                                           &ctx->acceptor_subkey_cksumtype);
        if (code)
           goto fail;
    }
index 670dbe56808ea81976bfb21dfde57ee93c501252..706d57c4549532248dcb4062ec641fd0bb529048 100644 (file)
@@ -35,9 +35,9 @@ rotate_left (void *ptr, size_t bufsiz, size_t rc)
 
 static const gss_buffer_desc empty_message = { 0, 0 };
 
-#define FLAG_SENDER_IS_ACCEPTOR        0x80
-#define FLAG_WRAP_CONFIDENTIAL 0x40
-#define FLAG_ACCEPTOR_SUBKEY   0x20
+#define FLAG_SENDER_IS_ACCEPTOR        0x01
+#define FLAG_WRAP_CONFIDENTIAL 0x02
+#define FLAG_ACCEPTOR_SUBKEY   0x04
 
 void
 _log_block(const char *file, int line, const char *label,
@@ -61,6 +61,8 @@ _log_block(const char *file, int line, const char *label,
 #endif
 }
 
+#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
+
 krb5_error_code
 gss_krb5int_make_seal_token_v3 (krb5_context context,
                                krb5_gss_ctx_id_rec *ctx,
@@ -77,11 +79,12 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
     size_t rrc, ec;
     unsigned short tok_id;
     krb5_checksum sum;
+    krb5_keyblock *key;
 
     assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
     assert(ctx->big_endian == 0);
 
-    acceptor_flag = ctx->initiate ? 0 : 0x80;
+    acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
     key_usage = (toktype == KG_TOK_WRAP_MSG
                 ? (ctx->initiate
                    ? KG_USAGE_INITIATOR_SIGN
@@ -89,8 +92,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
                 : (ctx->initiate
                    ? KG_USAGE_INITIATOR_SEAL
                    : KG_USAGE_ACCEPTOR_SEAL));
-
-#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
+    if (ctx->have_acceptor_subkey) {
+       _log("%s:%d: using acceptor subkey\n", SFILE, __LINE__);
+       key = ctx->acceptor_subkey;
+    } else {
+       _log("%s:%d: using main key\n", SFILE, __LINE__);
+       key = ctx->enc;
+    }
 
     _log("%s:%d: wrap input token: %d @%p toktype=0x%x\n", SFILE, __LINE__,
         message->length, message->value, toktype);
@@ -114,8 +122,12 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        ec_max = SIZE_MAX - message->length - 300;
        if (ec_max > 0xffff)
            ec_max = 0xffff;
+#ifdef CFX_EXERCISE
        /* For testing only.  For performance, always set ec = 0.  */
        ec = ec_max & rand();
+#else
+       ec = 0;
+#endif
        _log("%s:%d: ec=%d\n", SFILE, __LINE__, ec);
        plain.length = message->length + 16 + ec;
        plain.data = malloc(message->length + 16 + ec);
@@ -134,8 +146,9 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        /* TOK_ID */
        store_16_be(0x0504, outbuf);
        /* flags */
-       /* no acceptor subkey stuff yet */
-       outbuf[2] = acceptor_flag | (conf_req_flag ? 0x40 : 0);
+       outbuf[2] = (acceptor_flag
+                    | (conf_req_flag ? FLAG_WRAP_CONFIDENTIAL : 0)
+                    | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
        /* filler */
        outbuf[3] = 0xff;
        /* EC */
@@ -150,9 +163,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
 
        cipher.ciphertext.data = outbuf + 16;
        cipher.ciphertext.length = bufsize - 16;
-       cipher.enctype = ctx->enc->enctype;
-       err = krb5_c_encrypt(context, ctx->enc, key_usage, 0,
-                            &plain, &cipher);
+       cipher.enctype = key->enctype;
+       err = krb5_c_encrypt(context, key, key_usage, 0, &plain, &cipher);
        zap(plain.data, plain.length);
        free(plain.data);
        plain.data = 0;
@@ -161,8 +173,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        _log("%s:%d: just encrypted:\n"
             "\t(key=%d/%02x%02x..., usage=%d, plain.length=%d,\n"
             "\t ciphertext=%d/%02x%02x...)\n",
-            SFILE, __LINE__, ctx->enc->enctype,
-            ctx->enc->contents[0], ctx->enc->contents[1],
+            SFILE, __LINE__, key->enctype,
+            key->contents[0], key->contents[1],
             key_usage, plain.length,
             cipher.ciphertext.length,
             0xff & cipher.ciphertext.data[0],
@@ -171,11 +183,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        /* Now that we know we're returning a valid token....  */
        ctx->seq_send++;
 
+#ifdef CFX_EXERCISE
        rrc = rand() & 0xffff;
        if (rotate_left(outbuf+16, bufsize-16,
                        (bufsize-16) - (rrc % (bufsize - 16))))
            store_16_be(rrc, outbuf+6);
        /* If the rotate fails, don't worry about it.  */
+#endif
     } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
        krb5_data plain;
 
@@ -207,8 +221,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        /* TOK_ID */
        store_16_be(tok_id, outbuf);
        /* flags */
-       /* no acceptor subkey stuff yet */
-       outbuf[2] = acceptor_flag | (conf_req_flag ? 0x80 : 0);
+       outbuf[2] = (acceptor_flag
+                    | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0));
        /* filler */
        outbuf[3] = 0xff;
        if (toktype == KG_TOK_WRAP_MSG) {
@@ -240,7 +254,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        _log_block(SFILE, __LINE__, "checksum input",
                   plain.data, plain.length);
 
-       err = krb5_c_make_checksum(context, ctx->cksumtype, ctx->enc,
+       err = krb5_c_make_checksum(context, ctx->cksumtype, key,
                                   key_usage, &plain, &sum);
        zap(plain.data, plain.length);
        free(plain.data);
@@ -261,11 +275,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        ctx->seq_send++;
 
        if (toktype == KG_TOK_WRAP_MSG) {
+#ifdef CFX_EXERCISE
            rrc = rand() & 0xffff;
            /* If the rotate fails, don't worry about it.  */
            if (rotate_left(outbuf+16, bufsize-16,
                            (bufsize-16) - (rrc % (bufsize - 16))))
                store_16_be(rrc, outbuf+6);
+#endif
            /* Fix up EC field.  */
            store_16_be(ctx->cksum_size, outbuf+4);
        } else {
@@ -314,6 +330,7 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
     krb5_checksum sum;
     krb5_error_code err;
     krb5_boolean valid;
+    krb5_keyblock *key;
 
     assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
     assert(ctx->big_endian == 0);
@@ -356,6 +373,30 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
        return GSS_S_BAD_SIG;
     }
     LOG();
+
+    /* Two things to note here.
+
+       First, we can't really enforce the use of the acceptor's subkey,
+       if we're the acceptor; the initiator may have sent messages
+       before getting the subkey.  We could probably enforce it if
+       we're the initiator.
+
+       Second, if someone tweaks the code to not set the flag telling
+       the krb5 library to generate a new subkey in the AP-REP
+       message, the MIT library may include a subkey anyways --
+       namely, a copy of the AP-REQ subkey, if it was provided.  So
+       the initiator may think we wanted a subkey, and set the flag,
+       even though we weren't trying to set the subkey.  The "other"
+       key, the one not asserted by the acceptor, will have the same
+       value in that case, though, so we can just ignore the flag.  */
+    if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) {
+       _log("%s:%d: sender used acceptor subkey\n", SFILE, __LINE__);
+       key = ctx->acceptor_subkey;
+    } else {
+       _log("%s:%d: sender used its own key\n", SFILE, __LINE__);
+       key = ctx->enc;
+    }
+
     if (toktype == KG_TOK_WRAP_MSG) {
        if (load_16_be(ptr) != 0x0504)
            DEFECTIVE;
@@ -381,7 +422,7 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
 
               For all current cryptosystems, the ciphertext size will
               be larger than the plaintext size.  */
-           cipher.enctype = ctx->enc->enctype;
+           cipher.enctype = key->enctype;
            cipher.ciphertext.length = bodysize - 16;
            cipher.ciphertext.data = ptr + 16;
            plain.length = bodysize - 16;
@@ -390,13 +431,13 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
                goto no_mem;
            _log("%s:%d: about to decrypt:\n"
                 "\t(key=%d/%02x%02x..., usage=%d, ciphertext=%d/%02x%02x...)\n",
-                SFILE, __LINE__, ctx->enc->enctype,
-                ctx->enc->contents[0], ctx->enc->contents[1],
+                SFILE, __LINE__, key->enctype,
+                key->contents[0], key->contents[1],
                 key_usage,
                 cipher.ciphertext.length,
                 0xff & cipher.ciphertext.data[0],
                 0xff & cipher.ciphertext.data[1]);
-           err = krb5_c_decrypt(context, ctx->enc, key_usage, 0,
+           err = krb5_c_decrypt(context, key, key_usage, 0,
                                 &cipher, &plain);
            if (err) {
                free(plain.data);
@@ -453,7 +494,7 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
                       plain.data, plain.length);
            _log_block(SFILE, __LINE__, "checksum to test",
                       sum.contents, sum.length);
-           err = krb5_c_verify_checksum(context, ctx->enc, key_usage,
+           err = krb5_c_verify_checksum(context, key, key_usage,
                                         &plain, &sum, &valid);
            if (err)
                goto error;
@@ -507,7 +548,7 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
                       plain.data, plain.length);
            _log_block(SFILE, __LINE__, "checksum to test",
                       sum.contents, sum.length);
-       err = krb5_c_verify_checksum(context, ctx->enc, key_usage,
+       err = krb5_c_verify_checksum(context, key, key_usage,
                                     &plain, &sum, &valid);
        if (err) {
        error: