]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
checkpoint; most tests work except gssftp "big encrypted get"; spews debug info to...
authorKen Raeburn <raeburn@mit.edu>
Tue, 2 Dec 2003 18:51:02 +0000 (18:51 +0000)
committerKen Raeburn <raeburn@mit.edu>
Tue, 2 Dec 2003 18:51:02 +0000 (18:51 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/raeburn-gssapi-cfx@15851 dc483132-0cff-0310-8789-dd5450dbe970

38 files changed:
src/include/k5-int.h
src/kadmin/testing/util/tcl_kadm5.c
src/kadmin/testing/util/tcl_ovsec_kadm.c
src/lib/gssapi/generic/gssapi.hin
src/lib/gssapi/generic/gssapiP_generic.h
src/lib/gssapi/generic/util_ordering.c
src/lib/gssapi/generic/util_token.c
src/lib/gssapi/krb5/ChangeLog
src/lib/gssapi/krb5/Makefile.in
src/lib/gssapi/krb5/accept_sec_context.c
src/lib/gssapi/krb5/acquire_cred.c
src/lib/gssapi/krb5/delete_sec_context.c
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/krb5/k5seal.c
src/lib/gssapi/krb5/k5sealv3.c
src/lib/gssapi/krb5/k5unseal.c
src/lib/gssapi/krb5/krb5_gss_glue.c
src/lib/gssapi/krb5/process_context_token.c
src/lib/gssapi/krb5/ser_sctx.c
src/lib/gssapi/krb5/unseal.c
src/lib/gssapi/krb5/verify.c
src/lib/gssapi/krb5/wrap_size_limit.c
src/lib/kadm5/clnt/client_init.c
src/lib/kadm5/clnt/client_rpc.c
src/lib/kdb/keytab.c
src/lib/rpc/auth_gssapi.c
src/lib/rpc/auth_gssapi_misc.c
src/lib/rpc/clnt_tcp.c
src/lib/rpc/rpc_callmsg.c
src/lib/rpc/svc.c
src/lib/rpc/svc_auth.c
src/lib/rpc/svc_auth_gssapi.c
src/lib/rpc/unit-test/ChangeLog
src/lib/rpc/unit-test/lib/helpers.exp
src/lib/rpc/xdr_rec.c
src/tests/dejagnu/config/default.exp
src/tests/dejagnu/krb-standalone/gssapi.exp

index 812066e5f4f311b886121baf4fff404e9f4adaf3..088e01316614e731a8801209166e5c378b4405c4 100644 (file)
@@ -688,6 +688,12 @@ krb5_error_code krb5int_pbkdf2_hmac_sha1 (const krb5_data *, unsigned long,
 
 /* Make this a function eventually?  */
 #define krb5int_zap_data(ptr, len) memset((volatile void *)ptr, 0, len)
+#if defined(__GNUC__) && defined(__GLIBC__)
+/* GNU libc generates multiple bogus initialization warnings if we
+   pass memset a volatile pointer.  The compiler should do well enough
+   with memset even without GNU libc's attempt at optimization.  */
+#undef memset
+#endif
 #define zap(p,l) krb5int_zap_data(p,l)
 
 /* A definition of init_state for DES based encryption systems.
index e1e36021390524200b86b6601a6ab2c50700b500..beeb8f321f326487f915512f0a2ab1d3b812e157 100644 (file)
@@ -287,7 +287,7 @@ static Tcl_DString *unparse_err(kadm5_ret_t code)
          code_string = "KADM5_AUTH_INSUFFICIENT"; break;
      case KADM5_BAD_DB: code_string = "KADM5_BAD_DB"; break;
      case KADM5_DUP: code_string = "KADM5_DUP"; break;
-     case KADM5_RPC_ERROR: code_string = "KADM5_RPC_ERROR"; break;
+     case /*KADM5_RPC_ERROR*/ (43787528L): code_string = "KADM5_RPC_ERROR"; break;
      case KADM5_NO_SRV: code_string = "KADM5_NO_SRV"; break;
      case KADM5_BAD_HIST_KEY:
          code_string = "KADM5_BAD_HIST_KEY"; break;
index e1eeceaf934f7b095f16653453a4b4aae6030176..5886a081130c8aee94f148422b4802f2b44a40f4 100644 (file)
@@ -268,7 +268,7 @@ static Tcl_DString *unparse_err(ovsec_kadm_ret_t code)
          code_string = "OVSEC_KADM_AUTH_INSUFFICIENT"; break;
      case OVSEC_KADM_BAD_DB: code_string = "OVSEC_KADM_BAD_DB"; break;
      case OVSEC_KADM_DUP: code_string = "OVSEC_KADM_DUP"; break;
-     case OVSEC_KADM_RPC_ERROR: code_string = "OVSEC_KADM_RPC_ERROR"; break;
+     case /*OVSEC_KADM_RPC_ERROR*/(43787528L): code_string = "OVSEC_KADM_RPC_ERROR"; break;
      case OVSEC_KADM_NO_SRV: code_string = "OVSEC_KADM_NO_SRV"; break;
      case OVSEC_KADM_BAD_HIST_KEY:
          code_string = "OVSEC_KADM_BAD_HIST_KEY"; break;
index 35519ed48a52ef78354670469469d097bf001bb9..8cd695248331ab20c84f6518f64b89995993e078 100644 (file)
@@ -802,4 +802,11 @@ OM_uint32 KRB5_CALLCONV gss_canonicalize_name
 /* XXXX This is a necessary evil until the spec is fixed */
 #define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
 
+extern void _log(const char *, ...);
+extern void _log_block(const char *, int, const char *, void *, size_t);
+#define _log_block2(LABEL,PTR,SIZE) _log_block(__FILE__,__LINE__,LABEL,PTR,SIZE)
+#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
+#undef GSS_S_DEFECTIVE_TOKEN
+#define GSS_S_DEFECTIVE_TOKEN (defective(SFILE,__LINE__),(((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET))
+
 #endif /* _GSSAPI_H_ */
index 602f01425cfd0ad7aa0f787f43273eba51fa3a09..24d51d0d59f6bdd9c3dc7a1d182ff9a6a6d6fe5c 100644 (file)
@@ -162,8 +162,9 @@ void g_make_token_header (gss_OID mech, unsigned int body_size,
                          unsigned char **buf, int tok_type);
 
 gss_int32 g_verify_token_header (gss_OID mech, unsigned int *body_size,
-                         unsigned char **buf, int tok_type, 
-                                unsigned int toksize_in);
+                                unsigned char **buf, int tok_type, 
+                                unsigned int toksize_in,
+                                int wrapper_required);
 
 OM_uint32 g_display_major_status (OM_uint32 *minor_status,
                                 OM_uint32 status_value,
index fe2eaafc2e43c872429bc105dae3d8c2bc347816..86d82c464082fb16a321f6e81db352e07e6524a9 100644 (file)
@@ -239,3 +239,59 @@ g_queue_internalize(void **vqueue, unsigned char **buf, size_t *lenremain)
     *vqueue = q;
     return 0;
 }
+
+/* debugging */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#if defined( __linux__)
+/*# define LOGPATH "/dev/pts/7"*/
+#define LOGPATH "/tmp/gsslog"
+#elif defined(__MACH__)
+# define LOGPATH "/dev/ttyp6" /* laptop */
+#endif
+void _log(const char *fmt, ...) {
+#if 1
+    static FILE *logf;
+    va_list x;
+    if (logf == 0) {
+       logf = fopen(LOGPATH, "a");
+       if (logf)
+           setvbuf(logf, 0, _IONBF, 0);
+    }
+    if (logf == 0)
+       return;
+    va_start(x, fmt);
+#if 0
+    fprintf(logf,"[%d]", getpid());
+#else
+    {
+       struct timeval tv;
+       struct tm tm;
+       time_t tvsec;
+       char buf[40];
+       char *p;
+
+       sprintf(buf,"[%d", getpid());
+       p = buf + strlen(buf);
+       gettimeofday(&tv, 0) == 0
+           && (tvsec = tv.tv_sec)
+           && strftime(p, buf + sizeof(buf) - p,
+                       ":%F-%T", localtime_r(&tvsec, &tm)) > 0
+           && (p += strlen(p))
+           && (buf + sizeof(buf) - p >= 10)
+           && sprintf(p, ".%06ld", (long) tv.tv_usec);
+       strcat(buf, "]");
+       fprintf(logf, "%s", buf);
+    }
+#endif
+    vfprintf(logf, fmt, x);
+    va_end(x);
+#endif
+}
+
+int defective(const char *f,int l) {
+    _log("%s:%d: reporting defective token\n", f, l);
+    return -1;
+}
index 30ae0698c2fcda499761cf89294688b768564cd2..104963ca257d56094f92bba48b3946c447c0c944 100644 (file)
@@ -168,22 +168,38 @@ void g_make_token_header(mech, body_size, buf, tok_type)
  * mechanism in the token does not match the mech argument.  buf and
  * *body_size are left unmodified on error.
  */
-gss_int32 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize_in)
+static gss_int32 g_bad_tok_header = G_BAD_TOK_HEADER;
+#undef G_BAD_TOK_HEADER
+#define G_BAD_TOK_HEADER (_log("%s:%d: returning G_BAD_TOK_HEADER", SFILE, __LINE__), g_bad_tok_header)
+gss_int32 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize_in,
+                               wrapper_required)
      gss_OID mech;
      unsigned int *body_size;
      unsigned char **buf_in;
      int tok_type;
      unsigned int toksize_in;
+     int wrapper_required;
 {
    unsigned char *buf = *buf_in;
    int seqsize;
    gss_OID_desc toid;
    int toksize = toksize_in;
 
+#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
+   _log("%s:%d: %s(tok_type=0x%x, toksize=%d, wrapper_required=%d)\n",
+       SFILE, __LINE__, __func__, tok_type, toksize, wrapper_required);
+   _log_block2("input token", buf, toksize);
+
+#define LOG() _log("%s:%d: here\n", SFILE, __LINE__)
    if ((toksize-=1) < 0)
       return(G_BAD_TOK_HEADER);
-   if (*buf++ != 0x60)
-      return(G_BAD_TOK_HEADER);
+   if (*buf++ != 0x60) {
+       if (wrapper_required)
+          return(G_BAD_TOK_HEADER);
+       buf--;
+       toksize++;
+       goto skip_wrapper;
+   }
 
    if ((seqsize = der_read_length(&buf, &toksize)) < 0)
       return(G_BAD_TOK_HEADER);
@@ -207,16 +223,22 @@ gss_int32 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize_in)
 
    if (! g_OID_equal(&toid, mech)) 
        return  G_WRONG_MECH;
+skip_wrapper:
    if (tok_type != -1) {
+       _log("%s:%d: toksize=%d\n", SFILE, __LINE__, toksize);
        if ((toksize-=2) < 0)
           return(G_BAD_TOK_HEADER);
 
+       _log("%s:%d: buf@%p: %02x %02x\n", SFILE, __LINE__,
+           buf, buf[0], buf[1]);
        if ((*buf++ != ((tok_type>>8)&0xff)) ||
-          (*buf++ != (tok_type&0xff))) 
+          (*buf++ != (tok_type&0xff))) {
+          _log("%s:%d: G_WRONG_TOKID\n", SFILE, __LINE__);
           return(G_WRONG_TOKID);
+       }
    }
-       *buf_in = buf;
-       *body_size = toksize;
+   *buf_in = buf;
+   *body_size = toksize;
 
-       return 0;
-       }
+   return 0;
+}
index 0fea901d3b6c873709bc8a7f057e758b3ada7d8c..cc120d3e22dbc14c84c7bc4736ae85f612d22945 100644 (file)
@@ -1,3 +1,10 @@
+2003-09-25  Ken Raeburn  <raeburn@mit.edu>
+
+       * gssapiP_krb5.h (struct _krb5_gss_ctx_id_rec): Deleted fields
+       ctypes and nctypes.
+       * delete_sec_context.c, init_sec_context.c, ser_sctx.c: Removed
+       references.
+
 2003-07-19  Ezra Peisach  <epeisach@mit.edu>
 
        * acquire_cred.c (krb5_gss_register_acceptor_identity): Allocate
index 9a18c50a8cf56b08fc0268c57317b81b4c1b0c41..759eedd9490f593193c735043301ebbbe0cf9a84 100644 (file)
@@ -42,6 +42,7 @@ SRCS = \
        $(srcdir)/inq_cred.c \
        $(srcdir)/inq_names.c \
        $(srcdir)/k5seal.c \
+       $(srcdir)/k5sealv3.c \
        $(srcdir)/k5unseal.c \
        $(srcdir)/krb5_gss_glue.c \
        $(srcdir)/process_context_token.c \
@@ -89,6 +90,7 @@ OBJS = \
        $(OUTPRE)inq_cred.$(OBJEXT) \
        $(OUTPRE)inq_names.$(OBJEXT) \
        $(OUTPRE)k5seal.$(OBJEXT) \
+       $(OUTPRE)k5sealv3.$(OBJEXT) \
        $(OUTPRE)k5unseal.$(OBJEXT) \
        $(OUTPRE)krb5_gss_glue.$(OBJEXT) \
        $(OUTPRE)process_context_token.$(OBJEXT) \
@@ -136,6 +138,7 @@ STLIBOBJS = \
        inq_cred.o \
        inq_names.o \
        k5seal.o \
+       k5sealv3.o \
        k5unseal.o \
        krb5_gss_glue.o \
        process_context_token.o \
index 3367c1da753b55fa83f2bacea2df5dd7df3e9b2f..55e9c2a9a3927b641d171f05c88dabf794bf005a 100644 (file)
@@ -309,16 +309,17 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
 
    ptr = (unsigned char *) input_token->value;
 
+   _log("%s:%d: here\n", SFILE, __LINE__);
    if (!(code = g_verify_token_header((gss_OID) gss_mech_krb5,
                                      &(ap_req.length),
                                      &ptr, KG_TOK_CTX_AP_REQ,
-                                     input_token->length))) {
+                                     input_token->length, 1))) {
        mech_used = gss_mech_krb5;
    } else if ((code == G_WRONG_MECH) &&
              !(code = g_verify_token_header((gss_OID) gss_mech_krb5_old,
                                             &(ap_req.length), 
                                             &ptr, KG_TOK_CTX_AP_REQ,
-                                            input_token->length))) {
+                                            input_token->length, 1))) {
        /*
        * Previous versions of this library used the old mech_id
        * and some broken behavior (wrong IV on checksum
@@ -331,6 +332,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
        major_status = GSS_S_DEFECTIVE_TOKEN;
        goto fail;
    }
+   _log("%s:%d: here\n", SFILE, __LINE__);
 
    sptr = (char *) ptr;
    TREAD_STR(sptr, ap_req.data, ap_req.length);
@@ -616,6 +618,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
        goto fail;
    }
 
+   ctx->proto = 0;
    switch(ctx->subkey->enctype) {
    case ENCTYPE_DES_CBC_MD5:
    case ENCTYPE_DES_CBC_CRC:
@@ -635,12 +638,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
           /*SUPPRESS 113*/
           ctx->enc->contents[i] ^= 0xf0;
 
-       if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
-          major_status = GSS_S_FAILURE;
-          goto fail;
-       }
-
-       break;
+       goto copy_subkey_to_seq;
 
    case ENCTYPE_DES3_CBC_SHA1:
        ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
@@ -649,36 +647,38 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
        ctx->sealalg = SEAL_ALG_DES3KD;
 
        /* fill in the encryption descriptors */
-
+   copy_subkey:
        if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
           major_status = GSS_S_FAILURE;
           goto fail;
        }
-
+   copy_subkey_to_seq:
        if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
           major_status = GSS_S_FAILURE;
           goto fail;
        }
-
        break;
-         case ENCTYPE_ARCFOUR_HMAC:
-           ctx->signalg = SGN_ALG_HMAC_MD5 ;
-           ctx->cksum_size = 8;
-           ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
-
-             code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
-             if (code)
-                 goto fail;
-             code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
-             if (code) {
-                 krb5_free_keyblock (context, ctx->enc);
-                 goto fail;
-             }
-             break;        
+
+   case ENCTYPE_ARCFOUR_HMAC:
+       ctx->signalg = SGN_ALG_HMAC_MD5 ;
+       ctx->cksum_size = 8;
+       ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
+       goto copy_subkey;
 
    default:
-       code = KRB5_BAD_ENCTYPE;
-       goto fail;
+       ctx->signalg = -1;
+       ctx->sealalg = -1;
+       ctx->proto = 1;
+       code = krb5int_c_mandatory_cksumtype(context, ctx->subkey->enctype,
+                                           &ctx->cksumtype);
+       if (code)
+          goto fail;
+       code = krb5_c_checksum_length(context, ctx->cksumtype,
+                                    &ctx->cksum_size);
+       if (code)
+          goto fail;
+       ctx->have_acceptor_subkey = 0;
+       goto copy_subkey;
    }
 
    ctx->endtime = ticket->enc_part2->times.endtime;
@@ -686,7 +686,11 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
 
    krb5_free_ticket(context, ticket); /* Done with ticket */
 
-   krb5_auth_con_getremoteseqnumber(context, auth_context, &ctx->seq_recv);
+   {
+       krb5_ui_4 seq_temp;
+       krb5_auth_con_getremoteseqnumber(context, auth_context, &seq_temp);
+       ctx->seq_recv = seq_temp;
+   }
 
    if ((code = krb5_timeofday(context, &now))) {
        major_status = GSS_S_FAILURE;
@@ -701,7 +705,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
 
    g_order_init(&(ctx->seqstate), ctx->seq_recv,
                (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
-               (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0);
+               (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
 
    /* at this point, the entire context structure is filled in, 
       so it can be released.  */
@@ -710,13 +714,15 @@ 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;
+
        if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
           major_status = GSS_S_FAILURE;
           goto fail;
        }
 
-       krb5_auth_con_getlocalseqnumber(context, auth_context,
-                                      &ctx->seq_send);
+       krb5_auth_con_getlocalseqnumber(context, auth_context, &seq_temp);
+       ctx->seq_send = seq_temp & 0xffffffffL;
 
        /* the reply token hasn't been sent yet, but that's ok. */
        ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
index 391575ddc97e476c9865e05b63d703597bffd864..c891c788d275f94669275cff67c0c8dc58cd6e8b 100644 (file)
@@ -136,9 +136,24 @@ acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
       return(GSS_S_CRED_UNAVAIL);
    }
 
+   _log("%s:%d: krb5_gss_keytab=%s ops=%p\n", SFILE, __LINE__,
+       krb5_gss_keytab ? krb5_gss_keytab : "(null)", kt->ops);
+
    if (desired_name != GSS_C_NO_NAME) {
       princ = (krb5_principal) desired_name;
       if ((code = krb5_kt_get_entry(context, kt, princ, 0, 0, &entry))) {
+        {
+            char *p, ktname[BUFSIZ];
+            krb5_error_code err;
+            if (krb5_unparse_name(context, princ, &p))
+                p = NULL;
+            if (err = krb5_kt_get_name(context, kt, ktname, sizeof(ktname)))
+                sprintf(ktname, "(error %d/%s)", err, error_message(err));
+            _log("%s:%d: error %d/%s; desired_name=%s\n", SFILE, __LINE__,
+                 code, error_message(code),
+                 p ? p : "(error)");
+            free(p);
+        }
         (void) krb5_kt_close(context, kt);
         if (code == KRB5_KT_NOTFOUND)
            *minor_status = KG_KEYTAB_NOMATCH;
index 28c23589062f6209454d89da0c619509ab3cd027..766a17bc5ac26e0b52742346b043d51f6f31c096 100644 (file)
@@ -101,9 +101,6 @@ krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
    if (ctx->mech_used)
        gss_release_oid(minor_status, &ctx->mech_used);
    
-   if (ctx->ctypes)
-       xfree(ctx->ctypes);
-
    /* Zero out context */
    memset(ctx, 0, sizeof(*ctx));
    xfree(ctx);
index 1215b1a9a6374ee83793b45afb33f02cc4e870ce..647f7cbf2b7fb73c5d40b6d121b4b80b6a710b5a 100644 (file)
@@ -116,10 +116,17 @@ enum seal_alg {
   SEAL_ALG_DES3KD          = 0x0002
 };
 
+/* for 3DES */
 #define KG_USAGE_SEAL 22
 #define KG_USAGE_SIGN 23
 #define KG_USAGE_SEQ  24
 
+/* for draft-ietf-krb-wg-gssapi-cfx-01 */
+#define KG_USAGE_ACCEPTOR_SEAL 22
+#define KG_USAGE_ACCEPTOR_SIGN 23
+#define KG_USAGE_INITIATOR_SEAL        24
+#define KG_USAGE_INITIATOR_SIGN        25
+
 enum qop {
   GSS_KRB5_INTEG_C_QOP_MD5       = 0x0001, /* *partial* MD5 = "MD2.5" */
   GSS_KRB5_INTEG_C_QOP_DES_MD5   = 0x0002,
@@ -151,16 +158,21 @@ typedef struct _krb5_gss_cred_id_rec {
    krb5_timestamp tgt_expire;
 } krb5_gss_cred_id_rec, *krb5_gss_cred_id_t; 
 
+#define GSS_CFX_SKIPS_ASN1_WRAPPER 0
+
 typedef struct _krb5_gss_ctx_id_rec {
-   int initiate;       /* nonzero if initiating, zero if accepting */
+   unsigned int initiate : 1;  /* nonzero if initiating, zero if accepting */
+   unsigned int established : 1;
+   unsigned int big_endian : 1;
+   unsigned int have_acceptor_subkey : 1;
+   unsigned int seed_init : 1; /* XXX tested but never actually set */
    OM_uint32 gss_flags;
-   int seed_init;
    unsigned char seed[16];
    krb5_principal here;
    krb5_principal there;
    krb5_keyblock *subkey;
    int signalg;
-   int cksum_size;
+   size_t cksum_size;
    int sealalg;
    krb5_keyblock *enc;
    krb5_keyblock *seq;
@@ -169,15 +181,17 @@ typedef struct _krb5_gss_ctx_id_rec {
    /* XXX these used to be signed.  the old spec is inspecific, and
       the new spec specifies unsigned.  I don't believe that the change
       affects the wire encoding. */
-   krb5_ui_4 seq_send;
-   krb5_ui_4 seq_recv;
+   gssint_uint64 seq_send;
+   gssint_uint64 seq_recv;
    void *seqstate;
-   int established;
-   int big_endian;
    krb5_auth_context auth_context;
    gss_OID_desc *mech_used;
-   int nctypes;
-   krb5_cksumtype *ctypes;
+    /* Protocol spec revision
+       0 => RFC 1964 with 3DES and RC4 enhancements
+       1 => draft-ietf-krb-wg-gssapi-cfx-01
+       No others defined so far.  */
+   int proto;
+   krb5_cksumtype cksumtype;
 } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
 
 extern void *kg_vdb;
@@ -587,4 +601,10 @@ gss_OID krb5_gss_convert_static_mech_oid
 (gss_OID oid
         );
        
+krb5_error_code gss_krb5int_make_seal_token_v3(krb5_context,
+                                              krb5_gss_ctx_id_rec *,
+                                              const gss_buffer_desc *,
+                                              gss_buffer_t,
+                                              int, int);
+
 #endif /* _GSSAPIP_KRB5_H_ */
index 98102ce8705aafa08ac88d87fcf81f4961f4b6e2..9fdc7b07dc1f40fb5624e3cc97f88febef66e76f 100644 (file)
@@ -340,9 +340,8 @@ get_requested_enctypes(
    int is_duplicate_enctype;
    int is_wanted_enctype;
    static const krb5_enctype wanted_enctypes[] = {
-#if 1
+     ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
      ENCTYPE_DES3_CBC_SHA1,
-#endif
      ENCTYPE_ARCFOUR_HMAC,
      ENCTYPE_DES_CBC_CRC,
      ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4,
@@ -418,6 +417,9 @@ setup_enc(
    krb5_error_code code;
    int i;
 
+   ctx->have_acceptor_subkey = 0;
+   ctx->proto = 0;
+   ctx->cksumtype = 0;
    switch(ctx->subkey->enctype) {
    case ENCTYPE_DES_CBC_MD5:
    case ENCTYPE_DES_CBC_MD4:
@@ -433,54 +435,53 @@ setup_enc(
         goto fail;
 
       for (i=0; i<ctx->enc->length; i++)
-        /*SUPPRESS 113*/
         ctx->enc->contents[i] ^= 0xf0;
 
-      if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq)))
-        goto fail;
-
-      break;
+      goto copy_subkey_to_seq;
 
    case ENCTYPE_DES3_CBC_SHA1:
+       /* MIT extension */
       ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
       ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
       ctx->cksum_size = 20;
       ctx->sealalg = SEAL_ALG_DES3KD;
 
+   copy_subkey:
       code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
       if (code)
         goto fail;
+   copy_subkey_to_seq:
       code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
       if (code) {
         krb5_free_keyblock (context, ctx->enc);
         goto fail;
       }
       break;
+
    case ENCTYPE_ARCFOUR_HMAC:
+       /* Microsoft extension */
       ctx->signalg = SGN_ALG_HMAC_MD5 ;
       ctx->cksum_size = 8;
       ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
 
-      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
-      if (code)
-        goto fail;
-      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
-      if (code) {
-        krb5_free_keyblock (context, ctx->enc);
-        goto fail;
-      }
-      break;       
-#if 0
-   case ENCTYPE_DES3_CBC_MD5:
-      enctype = ENCTYPE_DES3_CBC_RAW;
-      ctx->signalg = 3;
-      ctx->cksum_size = 16;
-      ctx->sealalg = 1;
-      break;
-#endif
+      goto copy_subkey;
+
    default:
-      *minor_status = KRB5_BAD_ENCTYPE;
-      return GSS_S_FAILURE;
+       /* Fill some fields we shouldn't be using on this path
+         with garbage.  */
+       ctx->signalg = -10;
+       ctx->sealalg = -10;
+
+       ctx->proto = 1;
+       code = krb5int_c_mandatory_cksumtype(context, ctx->subkey->enctype,
+                                           &ctx->cksumtype);
+       if (code)
+          goto fail;
+       code = krb5_c_checksum_length(context, ctx->cksumtype,
+                                    &ctx->cksum_size);
+       if (code)
+          goto fail;
+       goto copy_subkey;
    }
 fail:
    *minor_status = code;
@@ -557,8 +558,6 @@ new_connection(
    ctx->seed_init = 0;
    ctx->big_endian = 0;  /* all initiators do little-endian, as per spec */
    ctx->seqstate = 0;
-   ctx->nctypes = 0;
-   ctx->ctypes = 0;
 
    if ((code = krb5_timeofday(context, &now)))
       goto fail;
@@ -602,6 +601,7 @@ new_connection(
 
    {
       /* gsskrb5 v1 */
+      krb5_ui_4 seq_temp;
       if ((code = make_ap_req_v1(context, ctx,
                                 cred, k_cred, input_chan_bindings, 
                                 mech_type, &token))) {
@@ -613,8 +613,8 @@ new_connection(
         goto fail;
       }
 
-      krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
-                                     &ctx->seq_send);
+      krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &seq_temp);
+      ctx->seq_send = seq_temp;
       krb5_auth_con_getsendsubkey(context, ctx->auth_context,
                                  &ctx->subkey);
    }
@@ -664,7 +664,7 @@ new_connection(
       ctx->seq_recv = ctx->seq_send;
       g_order_init(&(ctx->seqstate), ctx->seq_recv,
                   (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 
-                  (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0);
+                  (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
       ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
       ctx->established = 1;
       return(GSS_S_COMPLETE);
@@ -680,8 +680,6 @@ fail:
           krb5_free_principal(context, ctx_free->there);
        if (ctx_free->subkey)
           krb5_free_keyblock(context, ctx_free->subkey);
-       if (ctx_free->ctypes)
-          krb5_free_cksumtypes(context, ctx_free->ctypes);
        xfree(ctx_free);
    } else
        (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
@@ -763,14 +761,15 @@ mutual_auth(
 
    ptr = (unsigned char *) input_token->value;
 
+   _log("%s:%d: here\n", SFILE, __LINE__);
    if (g_verify_token_header((gss_OID) ctx->mech_used,
                             &(ap_rep.length),
                             &ptr, KG_TOK_CTX_AP_REP,
-                            input_token->length)) {
+                            input_token->length, 1)) {
       if (g_verify_token_header((gss_OID) ctx->mech_used,
                                &(ap_rep.length),
                                &ptr, KG_TOK_CTX_ERROR,
-                               input_token->length) == 0) {
+                               input_token->length, 1) == 0) {
 
         /* Handle a KRB_ERROR message from the server */
 
@@ -791,6 +790,7 @@ mutual_auth(
         return(GSS_S_DEFECTIVE_TOKEN);
       }
    }
+   _log("%s:%d: here\n", SFILE, __LINE__);
 
    sptr = (char *) ptr;                      /* PC compiler bug */
    TREAD_STR(sptr, ap_rep.data, ap_rep.length);
@@ -813,7 +813,16 @@ mutual_auth(
    ctx->seq_recv = ap_rep_data->seq_number;
    g_order_init(&(ctx->seqstate), ctx->seq_recv,
                (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
-               (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0);
+               (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0, ctx->proto);
+
+   if (ctx->proto == 1 && ap_rep_data->subkey) {
+       /* Keep acceptor's subkey.  */
+       ctx->have_acceptor_subkey = 1;
+       code = krb5_copy_keyblock(context, ap_rep_data->subkey,
+                                &ctx->subkey);
+       if (code)
+          goto fail;
+   }
 
    /* free the ap_rep_data */
    krb5_free_ap_rep_enc_part(context, ap_rep_data);
index 3c8702a555ccd7f6b7c2dbb7aadfc2f14833aa82..7999a3e1580af757fb959169683c35e881e630cf 100644 (file)
@@ -54,7 +54,7 @@ static krb5_error_code
 make_seal_token_v1 (krb5_context context,
                    krb5_keyblock *enc,
                    krb5_keyblock *seq,
-                   krb5_ui_4 *seqnum,
+                   gssint_uint64 *seqnum,
                    int direction,
                    gss_buffer_t text,
                    gss_buffer_t token,
@@ -304,6 +304,7 @@ make_seal_token_v1 (krb5_context context,
     /* that's it.  return the token */
 
     (*seqnum)++;
+    *seqnum &= 0xffffffffL;
 
     token->length = tlen;
     token->value = (void *) t;
@@ -334,50 +335,16 @@ kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req,
     output_message_buffer->length = 0;
     output_message_buffer->value = NULL;
 
-    /* only default qop or matching established cryptosystem is allowed */
-    
-#if 0
-    switch (qop_req & GSS_KRB5_CONF_C_QOP_MASK) {
-    case GSS_C_QOP_DEFAULT:
-       break;
-    default:
-    unknown_qop:
-       *minor_status = (OM_uint32) G_UNKNOWN_QOP;
-       return GSS_S_FAILURE;
-    case GSS_KRB5_CONF_C_QOP_DES:
-       if (ctx->sealalg != SEAL_ALG_DES) {
-       bad_qop:
-           *minor_status = (OM_uint32) G_BAD_QOP;
-           return GSS_S_FAILURE;
-       }
-       break;
-    case GSS_KRB5_CONF_C_QOP_DES3:
-       if (ctx->sealalg != SEAL_ALG_DES3)
-           goto bad_qop;
-       break;
-    }
-    switch (qop_req & GSS_KRB5_INTEG_C_QOP_MASK) {
-    case GSS_C_QOP_DEFAULT:
-       break;
-    default:
-       goto unknown_qop;
-    case GSS_KRB5_INTEG_C_QOP_MD5:
-    case GSS_KRB5_INTEG_C_QOP_DES_MD5:
-    case GSS_KRB5_INTEG_C_QOP_DES_MAC:
-       if (ctx->sealalg != SEAL_ALG_DES)
-           goto bad_qop;
-       break;
-    case GSS_KRB5_INTEG_C_QOP_HMAC_SHA1:
-       if (ctx->sealalg != SEAL_ALG_DES3KD)
-           goto bad_qop;
-       break;
-    }
-#else
+    /* Only default qop or matching established cryptosystem is allowed.
+
+       There are NO EXTENSIONS to this set for AES and friends!  The
+       new spec says "just use 0".  The old spec plus extensions would
+       actually allow for certain non-zero values.  Fix this to handle
+       them later.  */
     if (qop_req != 0) {
        *minor_status = (OM_uint32) G_UNKNOWN_QOP;
        return GSS_S_FAILURE;
     }
-#endif
 
     /* validate the context handle */
     if (! kg_validate_ctx_id(context_handle)) {
@@ -397,12 +364,26 @@ kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req,
        return(GSS_S_FAILURE);
     }
 
-    code = make_seal_token_v1(context, ctx->enc, ctx->seq,
-                             &ctx->seq_send, ctx->initiate,
-                             input_message_buffer, output_message_buffer,
-                             ctx->signalg, ctx->cksum_size, ctx->sealalg,
-                             conf_req_flag, toktype, ctx->big_endian,
-                             ctx->mech_used);
+    switch (ctx->proto)
+    {
+    case 0:
+       code = make_seal_token_v1(context, ctx->enc, ctx->seq,
+                                 &ctx->seq_send, ctx->initiate,
+                                 input_message_buffer, output_message_buffer,
+                                 ctx->signalg, ctx->cksum_size, ctx->sealalg,
+                                 conf_req_flag, toktype, ctx->big_endian,
+                                 ctx->mech_used);
+       break;
+    case 1:
+       code = gss_krb5int_make_seal_token_v3(context, ctx,
+                                             input_message_buffer,
+                                             output_message_buffer,
+                                             conf_req_flag, toktype);
+       break;
+    default:
+       code = G_UNKNOWN_QOP;   /* XXX */
+       break;
+    }
 
     if (code) {
        *minor_status = code;
index b7fa2371d945f06f5def0c43cea159f5d7a0a89f..5b8e8ccaa974718bebf5aec757613dc1274460f0 100644 (file)
@@ -35,31 +35,71 @@ rotate_left (void *ptr, size_t bufsiz, size_t rc)
     return 1;
 }
 
+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
+
+void
+_log_block(const char *file, int line, const char *label,
+          void *vptr, size_t len)
+{
+    char b[8 * 4 + 4];
+    int i, j;
+    if (strrchr(file, '/'))
+       file = 1 + strrchr(file, '/');
+    _log("%s:%d: %s: %d at %p\n", file, line, label, len, vptr);
+    for (i = 0; i < (len + 7) / 8; i++) {
+       unsigned char *base = (i * 8) + (unsigned char *)vptr;
+       b[0] = 0;
+       for (j = 0; j < 8 && j < (len - i * 8); j++)
+           sprintf(b+strlen(b), " %02x", base[j]);
+       _log("\t\t%04x/@%p:%s\n", 8 * i, base, b);
+    }
+}
+
 krb5_error_code
 gss_krb5int_make_seal_token_v3 (krb5_context context,
                                krb5_gss_ctx_id_rec *ctx,
-                               gss_buffer_t message,
+                               const gss_buffer_desc * message,
                                gss_buffer_t token,
                                int conf_req_flag, int toktype)
 {
-    size_t bufsize = 16, cksumsize;
-    unsigned char *outbuf = 0, *tmpbuf = 0;
+    size_t bufsize = 16;
+    unsigned char *outbuf = 0;
     krb5_error_code err;
     int key_usage;
     unsigned char acceptor_flag;
-    gss_buffer_desc *message2 = message;
+    const gss_buffer_desc *message2 = message;
     size_t rrc, ec;
     unsigned short tok_id;
-
-    static const gss_buffer_desc empty_message = { 0, 0 };
+    krb5_checksum sum;
 
     assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
     assert(ctx->big_endian == 0);
 
     acceptor_flag = ctx->initiate ? 0 : 0x80;
     key_usage = (toktype == KG_TOK_WRAP_MSG
-                ? (ctx->initiate ? KG_USAGE_INITIATOR_SIGN : KG_USAGE_ACCEPTOR_SIGN)
-                : (ctx->initiate ? KG_USAGE_INITIATOR_SEAL : KG_USAGE_ACCEPTOR_SEAL));
+                ? (ctx->initiate
+                   ? KG_USAGE_INITIATOR_SIGN
+                   : KG_USAGE_ACCEPTOR_SIGN)
+                : (ctx->initiate
+                   ? KG_USAGE_INITIATOR_SEAL
+                   : KG_USAGE_ACCEPTOR_SEAL));
+
+#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
+
+    _log("%s:%d: wrap input token: %d @%p toktype=0x%x\n", SFILE, __LINE__,
+        message->length, message->value, toktype);
+
+    {
+       static int initialized = 0;
+       if (!initialized) {
+           srand(time(0));
+           initialized = 1;
+       }
+    }
 
     if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
        krb5_data plain;
@@ -73,7 +113,9 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        if (ec_max > 0xffff)
            ec_max = 0xffff;
        /* For testing only.  For performance, always set ec = 0.  */
+#define rand() ((rand)() & 0xf)
        ec = ec_max & rand();
+       _log("%s:%d: ec=%d\n", SFILE, __LINE__, ec);
        plain.length = message->length + 16 + ec;
        plain.data = malloc(message->length + 16 + ec);
        if (plain.data == NULL)
@@ -92,7 +134,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        store_16_be(0x0504, outbuf);
        /* flags */
        /* no acceptor subkey stuff yet */
-       outbuf[2] = acceptor_flag | (conf_req_flag ? 0x80 : 0);
+       outbuf[2] = acceptor_flag | (conf_req_flag ? 0x40 : 0);
        /* filler */
        outbuf[3] = 0xff;
        /* EC */
@@ -115,6 +157,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        plain.data = 0;
        if (err)
            goto error;
+       _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],
+            key_usage, plain.length,
+            cipher.ciphertext.length,
+            0xff & cipher.ciphertext.data[0],
+            0xff & cipher.ciphertext.data[1]);
 
        /* Now that we know we're returning a valid token....  */
        ctx->seq_send++;
@@ -126,7 +177,6 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        /* If the rotate fails, don't worry about it.  */
     } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
        krb5_data plain;
-       krb5_checksum sum;
 
        /* Here, message is the application-supplied data; message2 is
           what goes into the output token.  They may be the same, or
@@ -140,16 +190,11 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        if (plain.data == NULL)
            return ENOMEM;
 
-       err = krb5_c_checksum_length (context, ctx->cksumtype, &cksumsize);
-       if (err) {
-           free(plain.data);
-           plain.data = 0;
-           goto error;
-       }
-       if (cksumsize > 0xffff)
+       _log("%s:%d: cksumtype=%d\n", SFILE, __LINE__, ctx->cksumtype);
+       if (ctx->cksum_size > 0xffff)
            abort();
 
-       bufsize = 16 + message2->length + cksumsize;
+       bufsize = 16 + message2->length + ctx->cksum_size;
        outbuf = malloc(bufsize);
        if (outbuf == NULL) {
            free(plain.data);
@@ -179,33 +224,52 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
        }
        store_64_be(ctx->seq_send, outbuf+8);
 
-       /* For DEL_CTX, the message is empty, so it doesn't matter
-          which path we use.  The MIC path will probably change, for
-          security reasons.  */
-       if (toktype != KG_TOK_MIC_MSG) {
-           memcpy(plain.data, outbuf, 16);
-           memcpy(plain.data + 16, message->value, message->length);
-       } else {
-           memcpy(plain.data, message->value, message->length);
-           memcpy(plain.data+message->length, outbuf, 16);
-       }
-       sum.length = cksumsize;
-       sum.contents = outbuf + 16;
+       memcpy(plain.data, message->value, message->length);
+       memcpy(plain.data + message->length, outbuf, 16);
+
+       /* Fill in the output token -- data contents, if any, and
+          space for the checksum.  */
+       if (message2->length)
+           memcpy(outbuf + 16, message2->value, message2->length);
+
+       sum.contents = outbuf + 16 + message2->length;
+       sum.length = ctx->cksum_size;
+       _log("%s:%d: checksum @%p outbuf @%p offset %d\n", SFILE, __LINE__,
+            sum.contents, outbuf, sum.contents - outbuf);
+       _log_block(SFILE, __LINE__, "checksum input",
+                  plain.data, plain.length);
 
        err = krb5_c_make_checksum(context, ctx->cksumtype, ctx->enc,
                                   key_usage, &plain, &sum);
-
+       zap(plain.data, plain.length);
+       free(plain.data);
+       plain.data = 0;
+       if (err) {
+           zap(outbuf,bufsize);
+           free(outbuf);
+           goto error;
+       }
+       _log_block(SFILE, __LINE__, "checksum result",
+                  sum.contents, sum.length);
+       if (sum.length != ctx->cksum_size)
+           abort();
+       memcpy(outbuf + 16 + message2->length, sum.contents, ctx->cksum_size);
+       krb5_free_checksum_contents(context, &sum);
+       sum.contents = 0;
+       /* Now that we know we're actually generating the token...  */
        ctx->seq_send++;
 
-       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);
-
-       /* Fix up EC field.  */
-       if (toktype == KG_TOK_WRAP_MSG)
-           store_16_be(cksumsize, outbuf+4);
+       if (toktype == KG_TOK_WRAP_MSG) {
+           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);
+           /* Fix up EC field.  */
+           store_16_be(ctx->cksum_size, outbuf+4);
+       } else {
+           store_16_be(0xffff, outbuf+6);
+       }
     } else if (toktype == KG_TOK_MIC_MSG) {
        tok_id = 0x0404;
        message2 = &empty_message;
@@ -217,45 +281,265 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
     } else
        abort();
 
-#if 0
-    case KG_TOK_MIC_MSG:
-       store_16_be(0x0404, outbuf);
-    mic_del_common:
-       {
-           krb5_checksum sum;
-           krb5_data plain;
-
-           outbuf[2] = acceptor_flag;
-           memset(outbuf+3, 0xff, 5);
-           store_64_be(ctx->seq, outbuf + 8);
-           sum.length = cksumsize;
-           sum.contents = outbuf + 16;
-           plain.length = 16 + message2->length;
-           tmpbuf = malloc(plain.length);
-           if (tmpbuf == NULL) {
-               err = ENOMEM;
-               goto error;
-           }
-           plain.data = tmpbuf;
-           memcpy(plain.data, outbuf, 16);
-           memcpy(plain.data + 16, message2->value, message2->length);
-           err = krb5_c_make_checksum(context, ctx->cksumtype, ctx->enc,
-                                      sign_usage, &plain, &sum);
-           if (err)
-               goto error;
-       }
-       break;
-#endif
-
-    free(tmpbuf);
     token->value = outbuf;
     token->length = bufsize;
+    _log_block(SFILE, __LINE__, "output token", token->value, token->length);
     return 0;
 
 error:
-    free(tmpbuf);
     free(outbuf);
     token->value = NULL;
     token->length = 0;
     return err;
 }
+
+/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
+   conf_state is only valid if SEAL. */
+
+OM_uint32
+gss_krb5int_unseal_token_v3(krb5_context *contextptr,
+                           OM_uint32 *minor_status,
+                           krb5_gss_ctx_id_rec *ctx,
+                           unsigned char *ptr, int bodysize,
+                           gss_buffer_t message_buffer,
+                           int *conf_state, int *qop_state, int toktype)
+{
+    krb5_context context = *contextptr;
+    krb5_data plain;
+    gssint_uint64 seqnum;
+    size_t ec, rrc;
+    int key_usage;
+    unsigned char acceptor_flag;
+    krb5_checksum sum;
+    krb5_error_code err;
+    krb5_boolean valid;
+
+    assert(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0);
+    assert(ctx->big_endian == 0);
+    assert(ctx->proto == 1);
+
+    if (qop_state)
+       *qop_state = GSS_C_QOP_DEFAULT;
+
+    acceptor_flag = ctx->initiate ? FLAG_SENDER_IS_ACCEPTOR : 0;
+    key_usage = (toktype == KG_TOK_WRAP_MSG
+                ? (!ctx->initiate
+                   ? KG_USAGE_INITIATOR_SIGN
+                   : KG_USAGE_ACCEPTOR_SIGN)
+                : (!ctx->initiate
+                   ? KG_USAGE_INITIATOR_SEAL
+                   : KG_USAGE_ACCEPTOR_SEAL));
+
+#define LOG()          _log("%s:%d: here\n", SFILE, __LINE__)
+#define DEFECTIVE      do{LOG();goto defective;}while(0)
+
+    _log ("%s:%d: bodysize %d ptr @%p: %02x %02x\n", SFILE, __LINE__,
+         bodysize, ptr, ptr[0], ptr[1]);
+
+    /* Oops.  I wrote this code assuming ptr would be at the start of
+       the token header.  */
+    ptr -= 2;
+    bodysize += 2;
+
+    _log_block(SFILE, __LINE__, "input token", ptr, bodysize);
+
+    if (bodysize < 16) {
+       LOG();
+    defective:
+       *minor_status = 0;
+       return GSS_S_DEFECTIVE_TOKEN;
+    }
+    LOG();
+    if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) {
+       *minor_status = G_BAD_DIRECTION;
+       return GSS_S_BAD_SIG;
+    }
+    LOG();
+    if (toktype == KG_TOK_WRAP_MSG) {
+       if (load_16_be(ptr) != 0x0504)
+           DEFECTIVE;
+       if (ptr[2] & ~0xe0)
+           DEFECTIVE;
+       if (ptr[3] != 0xff)
+           DEFECTIVE;
+       ec = load_16_be(ptr+4);
+       rrc = load_16_be(ptr+6);
+       seqnum = load_64_be(ptr+8);
+       if (!rotate_left(ptr+16, bodysize-16, rrc)) {
+       no_mem:
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       if (ptr[2] & FLAG_WRAP_CONFIDENTIAL) {
+           /* confidentiality */
+           krb5_enc_data cipher;
+           unsigned char *althdr;
+
+    LOG();
+           if (conf_state)
+               *conf_state = 1;
+           /* Do we have no decrypt_size function?
+
+              For all current cryptosystems, the ciphertext size will
+              be larger than the plaintext size.  */
+           cipher.enctype = ctx->enc->enctype;
+           cipher.ciphertext.length = bodysize - 16;
+           cipher.ciphertext.data = ptr + 16;
+           plain.length = bodysize - 16;
+           plain.data = malloc(plain.length);
+           if (plain.data == NULL)
+               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],
+                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,
+                                &cipher, &plain);
+           if (err) {
+               free(plain.data);
+               _log("%s:%d: error %ld/%s\n", SFILE, __LINE__,
+                    (long) err, error_message(err));
+               goto error;
+           }
+           /* Don't use bodysize here!  Use the fact that
+              cipher.ciphertext.length has been adjusted to the
+              correct length.  */
+    LOG();
+           althdr = plain.data + plain.length - 16;
+           if (load_16_be(althdr) != 0x0504
+               || althdr[2] != ptr[2]
+               || althdr[3] != ptr[3]
+               || memcmp(althdr+8, ptr+8, 8))
+               DEFECTIVE;
+           message_buffer->value = plain.data;
+           _log("%s:%d: plaintext len=%d, ec=%d\n", SFILE, __LINE__,
+                plain.length, ec);
+           message_buffer->length = plain.length - ec - 16;
+           _log("%s:%d: decrypted token %d @%p\n", SFILE, __LINE__,
+                message_buffer->length, message_buffer->value);
+       } else {
+           /* no confidentiality */
+    LOG();
+           if (conf_state)
+               *conf_state = 0;
+           if (ec + 16 < ec)
+               /* overflow check */
+               DEFECTIVE;
+    LOG();
+           if (ec + 16 > bodysize)
+               DEFECTIVE;
+    LOG();
+           /* We have: header | msg | cksum.
+              We need cksum(msg | header).
+              Rotate the first two.  */
+           store_16_be(0, ptr+4);
+           store_16_be(0, ptr+6);
+           plain.length = bodysize-ec;
+           plain.data = ptr;
+           if (!rotate_left(ptr, bodysize-ec, 16))
+               goto no_mem;
+           sum.length = ec;
+           if (sum.length != ctx->cksum_size) {
+               *minor_status = 0;
+    LOG();
+               return GSS_S_BAD_SIG;
+           }
+           sum.contents = ptr+bodysize-ec;
+           sum.checksum_type = ctx->cksumtype;
+           _log_block(SFILE, __LINE__, "checksum data input",
+                      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,
+                                        &plain, &sum, &valid);
+           if (err)
+               goto error;
+           _log("%s:%d: valid=%d\n", SFILE, __LINE__, valid);
+           if (!valid) {
+    LOG();
+               *minor_status = 0;
+               return GSS_S_BAD_SIG;
+           }
+           message_buffer->length = plain.length - 16;
+           message_buffer->value = malloc(message_buffer->length);
+           if (message_buffer->value == NULL)
+               goto no_mem;
+           memcpy(message_buffer->value, plain.data, message_buffer->length);
+       }
+    LOG();
+       err = g_order_check(&ctx->seqstate, seqnum);
+       *minor_status = 0;
+       _log("%s:%d: g_order_check => %d/%s, unseal %s\n", SFILE, __LINE__,
+            err, err ? error_message(err) : "No error",
+            err ? "failed" : "passed");
+       return err;
+    } else if (toktype == KG_TOK_MIC_MSG) {
+       /* wrap token, no confidentiality */
+    LOG();
+       if (load_16_be(ptr) != 0x0404)
+           DEFECTIVE;
+    LOG();
+    verify_mic_1:
+    LOG();
+       if (ptr[2] & ~0xe0)
+           DEFECTIVE;
+    LOG();
+       if (ptr[3] != 0xff)
+           DEFECTIVE;
+       _log("%s:%d: at ptr+4 %p: %02x %02x %02x %02x\n", SFILE, __LINE__,
+            ptr+4, ptr[4], ptr[5], ptr[6], ptr[7]);
+       if (load_32_be(ptr+4) != 0xffffffffL)
+           DEFECTIVE;
+    LOG();
+       seqnum = load_64_be(ptr+8);
+       plain.length = message_buffer->length + 16;
+       plain.data = malloc(plain.length);
+       if (plain.data == NULL)
+           goto no_mem;
+       if (message_buffer->length)
+           memcpy(plain.data, message_buffer->value, message_buffer->length);
+       memcpy(plain.data + message_buffer->length, ptr, 16);
+       sum.length = bodysize - 16;
+       sum.contents = ptr + 16;
+       sum.checksum_type = ctx->cksumtype;
+       _log("%s:%d: sum.length = %d\n", SFILE, __LINE__, sum.length);
+           _log_block(SFILE, __LINE__, "checksum data input",
+                      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,
+                                    &plain, &sum, &valid);
+       if (err) {
+       error:
+           free(plain.data);
+    LOG();
+           *minor_status = err;
+           return GSS_S_BAD_SIG; /* XXX */
+       }
+    LOG();
+       if (!valid) {
+           free(plain.data);
+           *minor_status = 0;
+    LOG();
+           return GSS_S_BAD_SIG;
+       }
+    LOG();
+       err = g_order_check(&ctx->seqstate, seqnum);
+       *minor_status = 0;
+       return err;
+    } else if (toktype == KG_TOK_DEL_CTX) {
+    LOG();
+       if (load_16_be(ptr) != 0x0405)
+           DEFECTIVE;
+    LOG();
+       message_buffer = &empty_message;
+       goto verify_mic_1;
+    } else {
+    LOG();
+       DEFECTIVE;
+    }
+}
index e678311f9a47815ec082cc0c8ba37f80b246d02f..16334ea6da124c3864462f6db72b48d794153403 100644 (file)
@@ -490,6 +490,10 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
     unsigned char *ptr;
     unsigned int bodysize;
     int err;
+    int toktype2;
+
+    _log_block2("token to unseal",
+               input_token_buffer->value, input_token_buffer->length);
 
     /* validate the context handle */
     if (! kg_validate_ctx_id(context_handle)) {
@@ -510,14 +514,40 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
 
     ptr = (unsigned char *) input_token_buffer->value;
 
-    if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
-                                     &bodysize, &ptr, toktype,
-                                     input_token_buffer->length))) {
-       return(kg_unseal_v1(context, minor_status, ctx, ptr, bodysize,
-                           message_buffer, conf_state, qop_state,
-                           toktype));
+    if (ctx->proto)
+       switch (toktype) {
+       case KG_TOK_SIGN_MSG:
+           toktype2 = 0x0404;
+           break;
+       case KG_TOK_SEAL_MSG:
+           toktype2 = 0x0504;
+           break;
+       case KG_TOK_DEL_CTX:
+           toktype2 = 0x0405;
+           break;
+       default:
+           toktype2 = toktype;
+           break;
+       }
+    else
+       toktype2 = toktype;
+    err = g_verify_token_header((gss_OID) ctx->mech_used,
+                               &bodysize, &ptr, toktype2,
+                               input_token_buffer->length,
+                               !ctx->proto);
+    if (err) {
+       *minor_status = err;
+       _log("%s:%d: g_verify_token_header returns %d/%s\n", SFILE, __LINE__,
+            err, error_message(err));
+       return GSS_S_DEFECTIVE_TOKEN;
     }
 
-    *minor_status = err;
-    return(GSS_S_DEFECTIVE_TOKEN);
+    if (ctx->proto == 0)
+       return kg_unseal_v1(context, minor_status, ctx, ptr, bodysize,
+                           message_buffer, conf_state, qop_state,
+                           toktype);
+    else
+       return gss_krb5int_unseal_token_v3(context, minor_status, ctx,
+                                          ptr, bodysize, message_buffer,
+                                          conf_state, qop_state, toktype);
 }
index 540652ad8dfd8c8112a2e38e5dab8114eded9c4f..c1d49ed35d539c0b0bf9399c725b88ebce972869 100644 (file)
@@ -482,6 +482,12 @@ gss_unseal(minor_status, context_handle, input_message_buffer,
      int *conf_state;
      int *qop_state;
 {
+   _log("%s:%d: input length %d\n", SFILE, __LINE__,
+       input_message_buffer->length);
+   if (input_message_buffer->length == 0) {
+       if (fork() == 0)
+          abort();
+   }
    return(krb5_gss_unseal(minor_status, context_handle,
                          input_message_buffer, output_message_buffer,
                          conf_state, qop_state));
index 4639108d512239421d14005b9922af3eb1aa2dfe..b76ae50b64039dd899cb47e944c895d6822c39ee 100644 (file)
@@ -55,10 +55,12 @@ krb5_gss_process_context_token(minor_status, context_handle,
 
    /* "unseal" the token */
 
+   _log("%s:%d: here\n", SFILE, __LINE__);
    if (GSS_ERROR(majerr = kg_unseal(context, minor_status, ctx, token_buffer,
                                    GSS_C_NO_BUFFER, NULL, NULL,
                                    KG_TOK_DEL_CTX)))
       return(majerr);
+   _log("%s:%d: here\n", SFILE, __LINE__);
 
    /* that's it.  delete the context */
 
index 8ab9401c3ec6dbd82d760e14e6f086e687a85c2b..f6314928e56e6ab8fce60568e5317067954c8649 100644 (file)
@@ -237,7 +237,6 @@ kg_ctx_size(kcontext, arg, sizep)
     if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
        required = 16*sizeof(krb5_int32);
        required += sizeof(ctx->seed);
-       required += ctx->nctypes*sizeof(krb5_int32);
 
        kret = 0;
        if (!kret && ctx->here)
@@ -337,16 +336,14 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
                                       &bp, &remain);
            (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_flags,
                                       &bp, &remain);
-           (void) krb5_ser_pack_int32((krb5_int32) ctx->seq_send,
+           (void) krb5_ser_pack_int64((krb5_int64) ctx->seq_send,
                                       &bp, &remain);
-           (void) krb5_ser_pack_int32((krb5_int32) ctx->seq_recv,
+           (void) krb5_ser_pack_int64((krb5_int64) ctx->seq_recv,
                                       &bp, &remain);
            (void) krb5_ser_pack_int32((krb5_int32) ctx->established,
                                       &bp, &remain);
            (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian,
                                       &bp, &remain);
-           (void) krb5_ser_pack_int32((krb5_int32) ctx->nctypes,
-                                      &bp, &remain);
 
            /* Now dynamic data */
            kret = 0;
@@ -395,13 +392,6 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
                                               (krb5_pointer) ctx->auth_context,
                                               &bp, &remain);
 
-           for (i=0; i<ctx->nctypes; i++) {
-               if (!kret) {
-                   kret = krb5_ser_pack_int32((krb5_int32) ctx->ctypes[i],
-                                              &bp, &remain);
-               }
-           }
-           
            if (!kret) {
                (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
                *buffer = bp;
@@ -464,14 +454,12 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
            ctx->endtime = (krb5_timestamp) ibuf;
            (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
            ctx->krb_flags = (krb5_flags) ibuf;
-           (void) krb5_ser_unpack_int32(&ctx->seq_send, &bp, &remain);
-           (void) krb5_ser_unpack_int32(&ctx->seq_recv, &bp, &remain);
+           (void) krb5_ser_unpack_int64(&ctx->seq_send, &bp, &remain);
+           (void) krb5_ser_unpack_int64(&ctx->seq_recv, &bp, &remain);
            (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
            ctx->established = (int) ibuf;
            (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
            ctx->big_endian = (int) ibuf;
-           (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
-           ctx->nctypes = (int) ibuf;
 
            if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp,
                                           &remain))) {
@@ -531,22 +519,6 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
                                               KV5M_AUTH_CONTEXT,
                                       (krb5_pointer *) &ctx->auth_context,
                                               &bp, &remain);
-               
-           if (!kret) {
-               if (ctx->nctypes) {
-                   if ((ctx->ctypes = (krb5_cksumtype *)
-                        malloc(ctx->nctypes*sizeof(krb5_cksumtype))) == NULL){
-                       kret = ENOMEM;
-                   }
-
-                   for (i=0; i<ctx->nctypes; i++) {
-                       if (!kret) {
-                           kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
-                           ctx->ctypes[i] = (krb5_cksumtype) ibuf;
-                       }
-                   }
-               }
-           }
 
            /* Get trailer */
            if (!kret &&
index 546521e1bf4a816766efe7ac64ac75d8862f4fbe..21df41ddbae7c948a03f1171173778edf32c9616 100644 (file)
@@ -42,6 +42,8 @@ krb5_gss_unseal(minor_status, context_handle,
    if (GSS_ERROR(kg_get_context(minor_status, &context)))
       return(GSS_S_FAILURE);
 
+   _log_block2("krb5_gss_unseal token", input_message_buffer->value,
+              input_message_buffer->length);
    return(kg_unseal(context, minor_status, context_handle,
                    input_message_buffer, output_message_buffer,
                    conf_state, qop_state, KG_TOK_SEAL_MSG));
@@ -66,9 +68,11 @@ krb5_gss_unwrap(minor_status, context_handle,
     if (GSS_ERROR(kg_get_context(minor_status, &context)))
        return(GSS_S_FAILURE);
 
+   _log("%s:%d: here\n", SFILE, __LINE__);
     rstat = kg_unseal(context, minor_status, context_handle,
                      input_message_buffer, output_message_buffer,
                      conf_state, &qstate, KG_TOK_WRAP_MSG);
+   _log("%s:%d: here\n", SFILE, __LINE__);
     if (!rstat && qop_state)
        *qop_state = (gss_qop_t) qstate;
     return(rstat);
index 0e73056404420b8bed7c29c4e059f3cef264eba4..aad630f9c6849df31c4e8cfd29a4dffc406bef55 100644 (file)
@@ -42,6 +42,7 @@ krb5_gss_verify(minor_status, context_handle,
        return(GSS_S_FAILURE);
 
 
+   _log("%s:%d: here\n", SFILE, __LINE__);
      return(kg_unseal(context, minor_status, context_handle,
                      token_buffer, message_buffer,
                      NULL, qop_state, KG_TOK_SIGN_MSG));
@@ -60,15 +61,17 @@ krb5_gss_verify_mic(minor_status, context_handle,
 {
     krb5_context       context;
     OM_uint32          rstat;
-    int                        qstate;
+    OM_uint32          qstate;
 
     if (GSS_ERROR(kg_get_context(minor_status, &context)))
        return(GSS_S_FAILURE);
 
 
+   _log("%s:%d: here\n", SFILE, __LINE__);
     rstat = kg_unseal(context, minor_status, context_handle,
                      token_buffer, message_buffer,
                      NULL, &qstate, KG_TOK_MIC_MSG);
+   _log("%s:%d: here\n", SFILE, __LINE__);
     if (!rstat && qop_state)
        *qop_state = (gss_qop_t) qstate;
     return(rstat);
index 43ccc6415bf05c3d835b753355ac952070ae8e1b..c21166848ecad0a69084a63603c8f0b5e31ccdcd 100644 (file)
@@ -110,6 +110,27 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
        return(GSS_S_NO_CONTEXT);
     }
 
+#if 1
+    if (ctx->proto == 1) {
+       /* No pseudo-ASN.1 wrapper overhead, so no sequence length and
+          OID.  */
+       OM_uint32 sz = req_output_size;
+       /* Token header: 16 octets.  */
+       if (conf_req_flag) {
+           while (sz > 0 && krb5_encrypt_size(sz, ctx->enc->enctype) + 16 > req_output_size)
+               sz--;
+       } else {
+           if (sz < 16 + ctx->cksum_size)
+               sz = 0;
+           else
+               sz -= (16 + ctx->cksum_size);
+       }
+       *max_input_size = sz;
+       *minor_status = 0;
+       return GSS_S_COMPLETE;
+    }
+#endif
+
     /* Calculate the token size and subtract that from the output size */
     overhead = 7 + ctx->mech_used->length;
     data_size = req_output_size;
index 247af875c0ce04fbc3b2866f2eb600e5f880d8e7..477a685112e84dea5d2e971366e2a660ebf513d7 100644 (file)
@@ -129,13 +129,7 @@ static int preauth_search_list[] = {
      -1
 };
 
-static krb5_enctype enctypes[] = {
-    ENCTYPE_DES3_CBC_SHA1,
-    ENCTYPE_ARCFOUR_HMAC,
-    ENCTYPE_DES_CBC_MD5,
-    ENCTYPE_DES_CBC_CRC,
-    0,
-};
+static const krb5_enctype *enctypes = 0;
 
 static kadm5_ret_t _kadm5_init_any(char *client_name,
                                   enum init_type init_type,
index 4e3b68a7f4f9fb78de08c7c919cfe6c1316e5b91..a15615fa1ee57340b1804ae120c2e5cd099e9c48 100644 (file)
@@ -297,10 +297,13 @@ init_1(argp, clnt)
    CLIENT *clnt;
 {
      static generic_ret res;
+     int x;
 
      memset((char *)&res, 0, sizeof(res));
-     if (clnt_call(clnt, INIT, xdr_u_int32, argp,
-                  xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+     x = clnt_call(clnt, INIT, xdr_u_int32, argp,
+                  xdr_generic_ret, &res, TIMEOUT);
+     if (x != RPC_SUCCESS) {
+        _log("%s:%d: init_1: clnt_call returned %d\n", SFILE, __LINE__, x);
          return (NULL);
      }
      return (&res);
index 5db382cc25c686ab522a15718cdc9d74f9b502b9..4d5894d088cf7282b2f62848079bcc8241965107 100644 (file)
@@ -37,11 +37,21 @@ krb5_error_code krb5_ktkdb_close (krb5_context, krb5_keytab);
 krb5_error_code krb5_ktkdb_get_entry (krb5_context, krb5_keytab, krb5_const_principal,
                   krb5_kvno, krb5_enctype, krb5_keytab_entry *);
 
+static krb5_error_code
+krb5_ktkdb_get_name(krb5_context context, krb5_keytab keytab,
+                   char *name, unsigned int namelen)
+{
+    if (namelen < sizeof("KDB:"))
+       return KRB5_KT_NAME_TOOLONG;
+    strcpy(name, "KDB:");
+    return 0;
+}
+
 krb5_kt_ops krb5_kt_kdb_ops = {
     0,
     "KDB",     /* Prefix -- this string should not appear anywhere else! */
     krb5_ktkdb_resolve,                /* resolve */
-    NULL,                      /* get_name */
+    krb5_ktkdb_get_name,       /* get_name */
     krb5_ktkdb_close,          /* close */
     krb5_ktkdb_get_entry,      /* get */
     NULL,                      /* start_seq_get */
index a18939ae697d34a0cc009ae05d5c72c9b2e57fb3..6545d32826e5f1f462868a2334d9efbe4add0abb 100644 (file)
@@ -581,11 +581,13 @@ static bool_t auth_gssapi_marshall(auth, xdrs)
          
          PRINTF(("gssapi_marshall: sending seq_num %d\n", seq_num));
          
+         _log("%s:%d: in %s\n", SFILE, __LINE__, __func__);
          if (auth_gssapi_seal_seq(AUTH_PRIVATE(auth)->context, seq_num,
                                   &out_buf) == FALSE) {
               PRINTF(("gssapi_marhshall: seal failed\n"));
          }
-         
+         _log("%s:%d: in %s\n", SFILE, __LINE__, __func__);
+
          auth->ah_verf.oa_base = out_buf.value;
          auth->ah_verf.oa_length = out_buf.length;
          
index ab9b0bcbca8a5e0083cbeaf35ab7fc97618d821a..28896b3eeddbb1c48e9f9c91b240105787e12285 100644 (file)
@@ -97,8 +97,12 @@ bool_t auth_gssapi_seal_seq(context, seq_num, out_buf)
      
      in_buf.length = sizeof(rpc_u_int32);
      in_buf.value = (char *) &nl_seq_num;
+     _log("%s:%d: %s about to call gss_seal\n", SFILE, __LINE__,
+         __func__);
      gssstat = gss_seal(&minor_stat, context, 0, GSS_C_QOP_DEFAULT,
                        &in_buf, NULL, out_buf);
+     _log("%s:%d: %s result %d/%d in_buf %d out_buf %d\n", __FILE__, __LINE__,
+         __func__, gssstat, minor_stat, in_buf.length, out_buf->length);
      if (gssstat != GSS_S_COMPLETE) {
          PRINTF(("gssapi_seal_seq: failed\n"));
          AUTH_GSSAPI_DISPLAY_STATUS(("sealing sequence number",
@@ -119,6 +123,9 @@ bool_t auth_gssapi_unseal_seq(context, in_buf, seq_num)
      
      gssstat = gss_unseal(&minor_stat, context, in_buf, &out_buf,
                          NULL, NULL);
+     _log("%s:%d: %s input len %d result %d/%d len %d\n",
+         __FILE__, __LINE__, __func__, in_buf->length,
+         gssstat, minor_stat, out_buf.length);
      if (gssstat != GSS_S_COMPLETE) {
          PRINTF(("gssapi_unseal_seq: failed\n"));
          AUTH_GSSAPI_DISPLAY_STATUS(("unsealing sequence number",
index 9906bca0e9a2f1aa479f8217aef51fdfe8af8094..d422079a0983b73d96c13675cb09fc0fbcfc02e0 100644 (file)
@@ -440,6 +440,7 @@ readtcp(ctptr, buf, len)
                return (0);
 
 #endif /* def FD_SETSIZE */
+#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
        while (TRUE) {
                readfds = mask;
                tout = ct->ct_wait;
@@ -447,6 +448,8 @@ readtcp(ctptr, buf, len)
                               &tout)) {
                case 0:
                        ct->ct_error.re_status = RPC_TIMEDOUT;
+                       _log("%s:%d: %s select says 0\n", SFILE, __LINE__, __func__);
+           if (fork() == 0) abort();
                        return (-1);
 
                case -1:
@@ -454,6 +457,8 @@ readtcp(ctptr, buf, len)
                                continue;
                        ct->ct_error.re_status = RPC_CANTRECV;
                        ct->ct_error.re_errno = errno;
+                       _log("%s:%d: %s select says error %d/%s\n", SFILE, __LINE__, __func__,
+                            errno, error_message(errno));
                        return (-1);
                }
                break;
@@ -461,6 +466,7 @@ readtcp(ctptr, buf, len)
        switch (len = read(ct->ct_sock, buf, (size_t) len)) {
 
        case 0:
+           _log("%s:%d: %s %d bytes\n", SFILE, __LINE__, __func__, len);
                /* premature eof */
                ct->ct_error.re_errno = ECONNRESET;
                ct->ct_error.re_status = RPC_CANTRECV;
@@ -468,9 +474,12 @@ readtcp(ctptr, buf, len)
                break;
 
        case -1:
+           _log("%s:%d: %s %d bytes\n", SFILE, __LINE__, __func__, len);
                ct->ct_error.re_errno = errno;
                ct->ct_error.re_status = RPC_CANTRECV;
                break;
+       default:
+           _log("%s:%d: %s %d bytes\n", SFILE, __LINE__, __func__, len);
        }
        return (len);
 }
@@ -486,10 +495,12 @@ writetcp(ctptr, buf, len)
 
        for (cnt = len; cnt > 0; cnt -= i, buf += i) {
                if ((i = write(ct->ct_sock, buf, (size_t) cnt)) == -1) {
+           _log("%s:%d: %s %d bytes\n", SFILE, __LINE__, __func__, len);
                        ct->ct_error.re_errno = errno;
                        ct->ct_error.re_status = RPC_CANTSEND;
                        return (-1);
                }
+           _log("%s:%d: %s %d bytes\n", SFILE, __LINE__, __func__, len);
        }
        return (len);
 }
index 831f2fd2da8a9058bbc885342b2d9ba217527546..f9072be8b1b5af6d67c76cec3218dc5cafc68df6 100644 (file)
@@ -87,6 +87,8 @@ xdr_callmsg(xdrs, cmsg)
                                buf += RNDUP(oa->oa_length) / sizeof (rpc_int32);
                        }
                        oa = &cmsg->rm_call.cb_verf;
+                       _log("%s:%d: packing: oa->oa_flavor=%d oa_length=%d\n",
+                            __FILE__, __LINE__, oa->oa_flavor, oa->oa_length);
                        IXDR_PUT_ENUM(buf, oa->oa_flavor);
                        IXDR_PUT_LONG(buf, oa->oa_length);
                        if (oa->oa_length) {
@@ -153,6 +155,8 @@ xdr_callmsg(xdrs, cmsg)
                                oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
                                oa->oa_length = IXDR_GET_LONG(buf);
                        }
+                       _log("%s:%d: unpacked: oa->oa_flavor=%d oa_length=%d\n",
+                            __FILE__, __LINE__, oa->oa_flavor, oa->oa_length);
                        if (oa->oa_length) {
                                if (oa->oa_length > MAX_AUTH_BYTES) {
                                        return (FALSE);
index 9026815415bff9f1bf5f0750730a6082ce9985ca..ad3cd5bebfc34beea6fcee33d82220db5ea059ac 100644 (file)
@@ -457,6 +457,9 @@ svc_getreqset(readfds)
                                no_dispatch = FALSE;
 
                                /* first authenticate the message */
+                               _log("%s:%d: msg.cb_verf.oa_length=%d, oa_flavor=%d\n",
+                                    __FILE__, __LINE__, msg.rm_call.cb_verf.oa_length,
+                                    msg.rm_call.cb_verf.oa_flavor);
                                why=_authenticate(&r, &msg, &no_dispatch);
                                if (why != AUTH_OK) {
                                     svcerr_auth(xprt, why);
index 2e28b5c059137b05499b0d15555ad865fca0d46f..e52e4722b09a794159a9193cf0fd6b4949f854f6 100644 (file)
@@ -93,6 +93,8 @@ _authenticate(rqst, msg, no_dispatch)
        rqst->rq_xprt->xp_verf.oa_length = 0;
        cred_flavor = rqst->rq_cred.oa_flavor;
        *no_dispatch = FALSE;
+       _log("%s:%d: dispatching authentication flavor %d\n",
+            __FILE__, __LINE__, cred_flavor);
        for (i = 0; i < svcauthnum; i++) {
             if (cred_flavor == svcauthsw[i].flavor &&
                 svcauthsw[i].authenticator != NULL) {
index 8458bf4733d5d37e17568a489158a23e704886c2..41a3311f6238ff729527ebb89dbfdc6731485b3d 100644 (file)
@@ -137,6 +137,7 @@ enum auth_stat _gssrpc_svcauth_gssapi(rqst, msg, no_dispatch)
      rpc_u_int32 seq_num;
 
      PRINTF(("svcauth_gssapi: starting\n"));
+     _log("%s:%d: svcauth_gssapi starting\n", __FILE__, __LINE__);
      
      /* clean up expired entries */
      clean_client();
@@ -182,6 +183,7 @@ enum auth_stat _gssrpc_svcauth_gssapi(rqst, msg, no_dispatch)
 #ifdef DEBUG_GSSAPI
      if (svc_debug_gssapi) {
          if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_EXIT) {
+      _log("%s:%d: %s AUTH_GSSAPI_EXIT\n", SFILE, __LINE__, __func__);
               PRINTF(("svcauth_gssapi: GSSAPI_EXIT, cleaning up\n"));
               svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
               gssrpc_xdr_free(xdr_authgssapi_creds, &creds);
@@ -442,6 +444,7 @@ enum auth_stat _gssrpc_svcauth_gssapi(rqst, msg, no_dispatch)
               PRINTF(("svcauth_gssapi: context established, isn %d\n", 
                       client_data->seq_num));
 
+              _log("%s:%d: in %s\n", SFILE, __LINE__, __func__);
               if (auth_gssapi_seal_seq(client_data->context,
                                        client_data->seq_num,
                                        &call_res.signed_isn) ==
@@ -451,6 +454,7 @@ enum auth_stat _gssrpc_svcauth_gssapi(rqst, msg, no_dispatch)
                    gss_release_buffer(&minor_stat, &output_token);
                    goto error;
               }
+              _log("%s:%d: in %s\n", SFILE, __LINE__, __func__);
          }
 
          PRINTF(("svcauth_gssapi: sending reply\n"));
@@ -508,12 +512,14 @@ enum auth_stat _gssrpc_svcauth_gssapi(rqst, msg, no_dispatch)
          
          /* prepare response verifier */
          seq_num = client_data->seq_num + 1;
+         _log("%s:%d: in %s\n", SFILE, __LINE__, __func__);
          if (auth_gssapi_seal_seq(client_data->context, seq_num,
                                   &out_buf) == FALSE) {
               ret = AUTH_FAILED;
               LOG_MISCERR("internal error sealing sequence number");
               goto error;
          }
+         _log("%s:%d: in %s\n", SFILE, __LINE__, __func__);
          
          client_data->seq_num++;
          
index e565321f2751309e1ab020e873405732738697b6..1d6c648b762f371c8ce6fc795643cea4f1ba42c0 100644 (file)
@@ -1,3 +1,9 @@
+2003-12-02  Ken Raeburn  <raeburn@mit.edu>
+
+       * lib/helpers.exp (expect_kadm_ok, eof_client): Accept and ignore
+       debugging messages starting "marshall_new_creds" or "gssapi_", and
+       blank lines.
+
 2003-01-07  Ken Raeburn  <raeburn@mit.edu>
 
        * Makefile.ov: Deleted.
index 54e0ef4301f8b0a128ff9fce3274e38a32f16461..c1d691e67fee8436943ee063f54e8e9d843cbc21 100644 (file)
@@ -51,6 +51,9 @@ proc expect_kadm_ok {} {
     expect {
        -i $kadmin_tcl_spawn_id
        -re "^OK OVSEC_KADM_OK \[^\n\]*\n" {}
+       -re "^marshall_new_creds: \[^\n\]*\n" { exp_continue }
+       -re "^gssapi_\[^\n\]*\n" { exp_continue }
+       -re "^\r?\n" { exp_continue }
        default { perror "didn't get ok back" }
     }
 }
@@ -190,6 +193,9 @@ proc eof_client {testname ccname id status} {
 
        expect {
                -i $id
+               -re "^marshall_new_creds\[^\n\]*\n" { exp_continue }
+               -re "^gssapi_\[^\n\]*\n" { exp_continue }
+               -re "^\r?\n" { exp_continue }
                eof { verbose $expect_out(buffer) 1 }
                timeout { 
                        fail "$testname: timeout waiting for client $ccname to exit"
index 28faaf24c6b74bb233ffe7fd480a8a4e5faa641c..251d7718fa5ec818b8cf61dc5dcfa0d7cec1a2fa 100644 (file)
@@ -538,6 +538,8 @@ get_input_bytes(rstrm, addr, len)
 {
        register size_t current;
 
+#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
+       _log("%s:%d: %s wants %d bytes\n", SFILE, __LINE__, __func__, len);
        while (len > 0) {
                current = (size_t)((long)rstrm->in_boundry - 
                                (long)rstrm->in_finger);
index 5f4b5924d8d09580614b9ae96d8add0fa5977042..2325df1ef4c55f47bbc7c3a65b2eca890c7c097c 100644 (file)
@@ -96,6 +96,17 @@ set passes {
        {master_key_type=aes256-cts-hmac-sha1-96}
        {dummy=[verbose -log "AES + DES enctypes"]}
     }
+    {
+       aesonly
+       des3_krbtgt=0
+       {supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+       {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
+       {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
+       {permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
+       {permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
+       {master_key_type=aes256-cts-hmac-sha1-96}
+       {dummy=[verbose -log "AES enctypes"]}
+    }
     {
        aes-des3
        des3_krbtgt=0
@@ -1451,6 +1462,10 @@ proc start_kerberos_daemons { standalone } {
            wait -i $tailf_spawn_id
            return 0
        }
+       "No principal in keytab matches desired name" {
+           dump_db
+           exp_continue
+       }
        "starting" { }
        timeout {
            if {$standalone} {
@@ -1591,6 +1606,28 @@ proc add_kerberos_key { kkey standalone } {
     }
 }
 
+# dump_db
+proc dump_db { } {
+    global KADMIN_LOCAL
+    global REALMNAME
+
+    spawn $KADMIN_LOCAL -r $REALMNAME
+    expect_after {
+       eof {
+           perror "failed to get debugging dump of database (eof)"
+       }
+       timeout {
+           perror "failed to get debugging dump of database (timeout)"
+       }
+    }
+    expect "kadmin.local: "
+    send "getprincs\r"
+    expect "kadmin.local: "
+    send "quit\r"
+    expect eof
+    catch expect_after
+}
+
 # add_random_key
 # Add a key with a random password to the Kerberos database.
 # start_kerberos_daemons must be called before this procedure.  If the
@@ -2508,7 +2545,7 @@ proc krb_exit { } {
 # helpful sometimes for debugging the test suite
 proc spawn_xterm { } {
     global env
-    foreach i {KDB5_UTIL KRB5KDC KADMIND KADMIN KADMIN_LOCAL KINIT KTUTIL KLIST RLOGIN RLOGIND FTP FTPD KPASSWD REALMNAME} {
+    foreach i {KDB5_UTIL KRB5KDC KADMIND KADMIN KADMIN_LOCAL KINIT KTUTIL KLIST RLOGIN RLOGIND FTP FTPD KPASSWD REALMNAME GSSCLIENT REALMNAME} {
        global $i
        if [info exists $i] { set env($i) [set $i] }
     }
index fa717282e58e9f3ed8470e22477a1ff68819b820..6dcea8d85a640146bf7593b257573df5551dfa3a 100644 (file)
@@ -285,6 +285,11 @@ proc doit { } {
     set gss_server_spawn_id $spawn_id
     sleep 2
 
+    if 0 {
+       send_user "about to run run_client gssclient0 $tmppwd/gss_tk_0 gssclient0\n"
+       set env(CMD) "env KRB5CCNAME=$tmppwd/gss_tk_0 $GSSCLIENT -port 5556 $hostname gssservice@$hostname message-from-gssclient0"
+       spawn_xterm
+    }
     run_client gssclient0 $tmppwd/gss_tk_0 gssclient0
     run_client gssclient1 $tmppwd/gss_tk_1 gssclient1
     run_client gssclient2 $tmppwd/gss_tk_2 gssclient2