* Makefile.in: Removed rd_req_sim.c
authorChris Provenzano <proven@mit.edu>
Mon, 27 Mar 1995 14:49:55 +0000 (14:49 +0000)
committerChris Provenzano <proven@mit.edu>
Mon, 27 Mar 1995 14:49:55 +0000 (14:49 +0000)
* auth_con.c: Default cksumtype is now CKSUMTYPE_RSA_MD4_DES.

* auth_con.c: Added krb5_auth_con_setuseruserkey(),
krb5_auth_con_getkey(),
krb5_auth_con_getremotesubkey(),
krb5_auth_con_getauthenticator(),
krb5_auth_con_getremoteseqnumber(),
krb5_auth_con_initivector().

* auth_con.c: Fixed krb5_auth_con_getlocalsubkey() to check for
a valid local_subkey before calling krb5_copy_keyblock().

* auth_con.h: Fixed some comments.

* mk_req_ext.c (krb5_mk_req_extended()): Always pass in a seed
(the keyblock contents) to krb5_calculate_checksum()

* rd_rep.c (krb5_rd_rep()): Use appropriate key to decode reply.

* rd_safe.c (krb5_rd_safe()): Don't pass checksum to
krb5_rd_safe_basic(), it's unnecessary.

* compat_recv.c (krb5_compat_recvauth()):
* mk_rep.c (krb5_mk_rep()):
* rd_req.c (krb5_rd_req()):
* rd_req_dec.c (krb5_rd_req_decode()):
* recvauth.c (krb5_recvauth()):
Added a krb5_auth_context argument and eliminated many of
the other arguments because they are included in the
krb5_auth_context structure.

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

12 files changed:
src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/Makefile.in
src/lib/krb5/krb/auth_con.c
src/lib/krb5/krb/auth_con.h
src/lib/krb5/krb/compat_recv.c
src/lib/krb5/krb/mk_rep.c
src/lib/krb5/krb/mk_req_ext.c
src/lib/krb5/krb/rd_rep.c
src/lib/krb5/krb/rd_req.c
src/lib/krb5/krb/rd_req_dec.c
src/lib/krb5/krb/rd_safe.c
src/lib/krb5/krb/recvauth.c

index 80fef45effe21d28e79b4824c46aee0e647da62d..ae4ffe8430853758d293dbe1311a4c7f3b8dbf62 100644 (file)
@@ -1,8 +1,46 @@
+
+Mon Mar 27 08:34:49 1995 Chris Provenzano (proven@mit.edu)
+
+       * Makefile.in: Removed rd_req_sim.c
+
+       * auth_con.c: Default cksumtype is now CKSUMTYPE_RSA_MD4_DES.
+
+       * auth_con.c: Added krb5_auth_con_setuseruserkey(), 
+               krb5_auth_con_getkey(), 
+               krb5_auth_con_getremotesubkey(),
+               krb5_auth_con_getauthenticator(), 
+               krb5_auth_con_getremoteseqnumber(),
+               krb5_auth_con_initivector().
+
+       * auth_con.c: Fixed krb5_auth_con_getlocalsubkey() to check for
+               a valid local_subkey before calling krb5_copy_keyblock().
+
+       * auth_con.h: Fixed some comments.
+
+       * mk_req_ext.c (krb5_mk_req_extended()): Always pass in a seed
+               (the keyblock contents) to krb5_calculate_checksum()
+
+       * rd_rep.c (krb5_rd_rep()): Use appropriate key to decode reply.
+
+       * rd_safe.c (krb5_rd_safe()): Don't pass checksum to 
+               krb5_rd_safe_basic(), it's unnecessary.
+
+       * compat_recv.c (krb5_compat_recvauth()):
+       * mk_rep.c (krb5_mk_rep()):
+       * rd_req.c (krb5_rd_req()):
+       * rd_req_dec.c (krb5_rd_req_decode()):
+       * recvauth.c (krb5_recvauth()):
+               Added a krb5_auth_context argument and eliminated many of 
+               the other arguments because they are included in the
+               krb5_auth_context structure.
+
+
 Tue Mar 21 19:22:51 1995 Keith Vetter (keithv@fusion.com)
 
        * mk_safe.c: fixed signed/unsigned mismatch.
        * rd_safe.c: removed unused local variable currentime.
         * mk_req_e.c: fixed signed/unsigned mismatch.
+
 Sat Mar 18 18:58:02 1995  John Gilmore  (gnu at toad.com)
 
        * bld_pr_ext.c, bld_princ.c:  Replace STDARG_PROTOTYPES with
index 9407ee57e4c5590e996e0f323c07fc1f3b2d2f64..b615962242d141d09e5a8f5b7a12f2a778b36f09 100644 (file)
@@ -59,7 +59,6 @@ OBJS= addr_comp.$(OBJEXT)     \
        rd_priv.$(OBJEXT)       \
        rd_rep.$(OBJEXT)        \
        rd_req.$(OBJEXT)        \
-       rd_req_sim.$(OBJEXT)    \
        rd_req_dec.$(OBJEXT)    \
        rd_safe.$(OBJEXT)       \
        recvauth.$(OBJEXT)      \
@@ -125,7 +124,6 @@ SRCS=       $(srcdir)/addr_comp.c   \
        $(srcdir)/rd_priv.c     \
        $(srcdir)/rd_rep.c      \
        $(srcdir)/rd_req.c      \
-       $(srcdir)/rd_req_sim.c  \
        $(srcdir)/rd_req_dec.c  \
        $(srcdir)/rd_safe.c     \
        $(srcdir)/recvauth.c    \
index 571e38c3f1e233ca581fe726ab1dc96a61cfc1ca..ebf72a7904b9857fe251fb41d60d7d37066ea551 100644 (file)
@@ -14,7 +14,8 @@ krb5_auth_con_init(context, auth_context)
        (*auth_context)->auth_context_flags = 
          KRB5_AUTH_CONTEXT_DO_TIME |  KRB5_AUTH_CONN_INITIALIZED;
 
-       (*auth_context)->cksumtype = CKSUMTYPE_CRC32;
+       (*auth_context)->cksumtype = CKSUMTYPE_RSA_MD4_DES;
+       /* (*auth_context)->cksumtype = CKSUMTYPE_CRC32; */
        return 0;
     }
     return ENOMEM;
@@ -61,13 +62,58 @@ krb5_auth_con_setkey(context, auth_context, keyblock)
     return(krb5_copy_keyblock(context, keyblock, &(auth_context->keyblock)));
 }
 
+/*
+ * This function overloads the keyblock field. It is only useful prior to
+ * a krb5_rd_req_decode() call for user to user authentication where the
+ * server has the key and needs to use it to decrypt the incoming request.
+ * Once decrypted this key is no longer necessary and is then overwritten
+ * with the session key sent by the client.
+ */
+krb5_error_code INTERFACE
+krb5_auth_con_setuseruserkey(context, auth_context, keyblock)
+    krb5_context         context;
+    krb5_auth_context  * auth_context;
+    krb5_keyblock       * keyblock;            
+{
+    if (auth_context->keyblock)
+       krb5_free_keyblock(context, auth_context->keyblock);
+    return(krb5_copy_keyblock(context, keyblock, &(auth_context->keyblock)));
+}
+
+krb5_error_code INTERFACE
+krb5_auth_con_getkey(context, auth_context, keyblock)
+    krb5_context         context;
+    krb5_auth_context  * auth_context;
+    krb5_keyblock      ** keyblock;            
+{
+    if (auth_context->keyblock)
+       return krb5_copy_keyblock(context, auth_context->keyblock, keyblock);
+    *keyblock = NULL;
+    return 0;
+}
+
 krb5_error_code INTERFACE
 krb5_auth_con_getlocalsubkey(context, auth_context, keyblock)
     krb5_context         context;
     krb5_auth_context  * auth_context;
     krb5_keyblock      ** keyblock;            
 {
-    return(krb5_copy_keyblock(context, auth_context->local_subkey, keyblock));
+    if (auth_context->local_subkey)
+       return krb5_copy_keyblock(context,auth_context->local_subkey,keyblock);
+    *keyblock = NULL;
+    return 0;
+}
+
+krb5_error_code INTERFACE
+krb5_auth_con_getremotesubkey(context, auth_context, keyblock)
+    krb5_context         context;
+    krb5_auth_context  * auth_context;
+    krb5_keyblock      ** keyblock;            
+{
+    if (auth_context->remote_subkey)
+       return krb5_copy_keyblock(context,auth_context->remote_subkey,keyblock);
+    *keyblock = NULL;
+    return 0;
 }
 
 krb5_error_code INTERFACE
@@ -90,6 +136,44 @@ krb5_auth_con_getlocalseqnumber(context, auth_context, seqnumber)
     return 0;
 }
 
+krb5_error_code INTERFACE
+krb5_auth_con_getauthenticator(context, auth_context, authenticator)
+    krb5_context         context;
+    krb5_auth_context  * auth_context;
+    krb5_authenticator ** authenticator;               
+{
+    return (krb5_copy_authenticator(context, auth_context->authentp,
+                                   authenticator));
+}
+
+krb5_error_code INTERFACE
+krb5_auth_con_getremoteseqnumber(context, auth_context, seqnumber)
+    krb5_context         context;
+    krb5_auth_context  * auth_context;
+    krb5_int32         * seqnumber;            
+{
+    *seqnumber = auth_context->remote_seq_number;
+    return 0;
+}
+
+krb5_error_code INTERFACE
+krb5_auth_con_initivector(context, auth_context)
+    krb5_context         context;
+    krb5_auth_context  * auth_context;
+{
+    if (auth_context->keyblock) {
+       int size = krb5_keytype_array[auth_context->keyblock->keytype]->
+                     system->block_length;
+
+       if (auth_context->i_vector = (krb5_pointer)malloc(size)) {
+           memset(auth_context->i_vector, 0, size);
+           return 0;
+       }
+       return ENOMEM;
+    }
+    return EINVAL; /* XXX need an error for no keyblock */
+}
+
 krb5_error_code INTERFACE
 krb5_auth_con_setivector(context, auth_context, ivector)
     krb5_context         context;
index 0cf2ed7a262ba7262a3ba6c7c7a4e49bdf6ba6c8..2188f742d4d386074509be31903286d5f81ee898 100644 (file)
@@ -12,9 +12,9 @@ struct _krb5_auth_context {
     krb5_int32         auth_context_flags;
     krb5_int32         remote_seq_number;
     krb5_int32         local_seq_number;
-    krb5_authenticator *authentp;              /* mk_req, rd_re*/
+    krb5_authenticator *authentp;              /* mk_req, rd_req, mk_rep, ...*/
     krb5_cksumtype     cksumtype;              /* mk_safe, ... */
-    krb5_pointer       i_vector;               /* mk_priv only */
+    krb5_pointer       i_vector;               /* mk_priv, rd_priv only */
     krb5_rcache                rcache;
 };
 
index 8b245ff531f24c278096dd946e0dc80758169960..db35f7733f24e75b10831cc9ec0aa78b4c15ff57 100644 (file)
@@ -52,30 +52,25 @@ static int krb_v4_recvauth();
 #define KRB5_RECVAUTH_V5       5
 
 krb5_error_code
-krb5_compat_recvauth(context, 
-                /* IN */
-                    fdp, appl_version, server, sender_addr, fetch_from,
-                    keyproc, keyprocarg, rc_type, flags,
+krb5_compat_recvauth(context, auth_context,
+                    /* IN */
+                    fdp, appl_version, server, rc_type, flags, keytab,
                     v4_options, v4_service, v4_instance, v4_faddr, v4_laddr,
                     v4_filename, 
                     /* OUT */
-                    auth_sys, seq_number, client, ticket, authent,
-                    v4_kdata, v4_schedule, v4_version)
+                    ticket,
+                    auth_sys, v4_kdata, v4_schedule, v4_version)
     krb5_context context;
+    krb5_auth_context **auth_context;
        krb5_pointer    fdp;
        char    *appl_version;
        krb5_principal  server;
-       krb5_address    *sender_addr;
-       krb5_pointer    fetch_from;
-       krb5_int32      *seq_number;
        char            *rc_type;
        krb5_int32      flags;
-       krb5_rdreq_key_proc keyproc;
-       krb5_pointer keyprocarg;
-       krb5_principal  *client;
-       krb5_ticket     **ticket;
-       krb5_authenticator      **authent;
-       krb5_int32      *auth_sys;
+       krb5_keytab     keytab;
+       krb5_ticket  ** ticket;
+        krb5_int32      *auth_sys;
+
        /*
         * Version 4 arguments
         */
@@ -189,11 +184,9 @@ krb5_compat_recvauth(context,
 
        *auth_sys = KRB5_RECVAUTH_V5;
        
-       retval = krb5_recvauth(context, fdp, appl_version, server, sender_addr,
-                              fetch_from,
-                              keyproc, keyprocarg, rc_type,
-                              flags | KRB5_RECVAUTH_SKIP_VERSION,
-                              seq_number, client, ticket, authent);
+       retval = krb5_recvauth(context, auth_context, fdp, appl_version, server,
+                              rc_type, flags | KRB5_RECVAUTH_SKIP_VERSION, 
+                              keytab, ticket);
 
        return retval;
 }
index 27543cac2ea0df583387b70e37671219c600d681..b25e67c9a090bf1551d7148d9b63795951a646b4 100644 (file)
  */
 
 #include "k5-int.h"
+#include "auth_con.h"
 
 /*
  Formats a KRB_AP_REP message into outbuf.
 
- The reply in repl is encrypted under the key in kblock, and the resulting
- message encoded and left in outbuf.
-
  The outbuf buffer storage is allocated, and should be freed by the
  caller when finished.
 
 */
 
 krb5_error_code INTERFACE
-krb5_mk_rep(context, repl, kblock, outbuf)
-    krb5_context context;
-    const krb5_ap_rep_enc_part *repl;
-    const krb5_keyblock *kblock;
-    krb5_data *outbuf;
+krb5_mk_rep(context, auth_context, outbuf)
+    krb5_context         context;
+    krb5_auth_context  * auth_context;
+    krb5_data          * outbuf;
 {
-    krb5_error_code retval;
-    krb5_data *scratch;
-    krb5_ap_rep reply;
-    krb5_enctype etype;
-    krb5_encrypt_block eblock;
-    krb5_data *toutbuf;
+    krb5_error_code      retval;
+    krb5_keyblock      * keyblock;
+    krb5_keytype         keytype;
+    krb5_enctype         etype;
+    krb5_ap_rep_enc_part  repl;
+    krb5_encrypt_block           eblock;
+    krb5_ap_rep          reply;
+    krb5_data          * scratch;
+    krb5_data          * toutbuf;
+
+    if (auth_context->remote_subkey)
+       keyblock = auth_context->remote_subkey;
+    else
+       keyblock = auth_context->keyblock;
 
     /* verify a valid etype is available */
-    if (!valid_keytype(kblock->keytype))
+    if (!valid_keytype(keytype = keyblock->keytype))
        return KRB5_PROG_KEYTYPE_NOSUPP;
 
-    etype = krb5_keytype_array[kblock->keytype]->system->proto_enctype;
+    etype = krb5_keytype_array[keytype]->system->proto_enctype;
 
     if (!valid_etype(etype))
        return KRB5_PROG_ETYPE_NOSUPP;
 
+    /* Make the reply */
+    if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+       (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+       (auth_context->local_seq_number == 0)) {
+       if (retval = krb5_generate_seq_number(context, keyblock,
+                                              &auth_context->local_seq_number))
+            return(retval);
+    }
+
+    repl.ctime = auth_context->authentp->ctime;    
+    repl.cusec = auth_context->authentp->cusec;    
+    repl.subkey = auth_context->authentp->subkey;    
+    repl.seq_number = auth_context->local_seq_number;
+
     /* encode it before encrypting */
-    if (retval = encode_krb5_ap_rep_enc_part(repl, &scratch))
+    if (retval = encode_krb5_ap_rep_enc_part(&repl, &scratch))
        return retval;
 
-#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
-krb5_free_data(context, scratch); }
-
     /* put together an eblock for this encryption */
-
     krb5_use_cstype(context, &eblock, etype);
     reply.enc_part.etype = etype;
     reply.enc_part.kvno = 0;           /* XXX user set? */
@@ -88,50 +103,38 @@ krb5_free_data(context, scratch); }
     if (!(reply.enc_part.ciphertext.data =
          malloc(reply.enc_part.ciphertext.length))) {
        retval = ENOMEM;
-       goto clean_scratch;
+       goto cleanup_scratch;
     }
 
-#define cleanup_encpart() {\
-(void) memset(reply.enc_part.ciphertext.data, 0,\
-            reply.enc_part.ciphertext.length); \
-free(reply.enc_part.ciphertext.data); \
-reply.enc_part.ciphertext.length = 0; reply.enc_part.ciphertext.data = 0;}
-
     /* do any necessary key pre-processing */
-    if (retval = krb5_process_key(context, &eblock, kblock)) {
-       goto clean_encpart;
-    }
-
-#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);}
+    if (retval = krb5_process_key(context, &eblock, keyblock)) 
+       goto cleanup_encpart;
 
     /* call the encryption routine */
     if (retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
                              (krb5_pointer) reply.enc_part.ciphertext.data,
                              scratch->length, &eblock, 0)) {
-       goto clean_prockey;
+       krb5_finish_key(context, &eblock);
+       goto cleanup_encpart;
     }
 
-    /* encrypted part now assembled-- do some cleanup */
-    cleanup_scratch();
-
-    if (retval = krb5_finish_key(context, &eblock)) {
-       cleanup_encpart();
-       return retval;
-    }
+    if (retval = krb5_finish_key(context, &eblock)) 
+       goto cleanup_encpart;
 
     if (!(retval = encode_krb5_ap_rep(&reply, &toutbuf))) {
        *outbuf = *toutbuf;
        krb5_xfree(toutbuf);
     }
-    cleanup_encpart();
-    return retval;
 
- clean_prockey:
-    cleanup_prockey();
- clean_encpart:
-    cleanup_encpart();
- clean_scratch:
-    cleanup_scratch();
+cleanup_encpart:
+    memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
+    free(reply.enc_part.ciphertext.data); 
+    reply.enc_part.ciphertext.length = 0; 
+    reply.enc_part.ciphertext.data = 0;
+
+cleanup_scratch:
+    memset(scratch->data, 0, scratch->length); 
+    krb5_free_data(context, scratch);
 
     return retval;
 }
index 8aac3917a8d6c37c46a23ed7b4a4e3783b293fd5..1011574e4a95e49389a83ca540f7252cdd0f3780 100644 (file)
@@ -132,16 +132,18 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
 
 
     /* Generate checksum, XXX What should the seed be? */
-    if ((checksum.contents = (krb5_octet *)malloc(krb5_checksum_size(
-                                         context, CKSUMTYPE_CRC32))) == NULL) {
+    if ((checksum.contents = (krb5_octet *)malloc(krb5_checksum_size(context,
+                            (*auth_context)->cksumtype))) == NULL) {
        retval = ENOMEM;
        goto cleanup;
     }
 
     if (in_data == NULL) {
        if (retval = krb5_calculate_checksum(context, 
-                                            (*auth_context)->cksumtype, 
-                                            0, 0, 0, 0, &checksum))
+                                          (*auth_context)->cksumtype, 0, 0,
+                                          (*auth_context)->keyblock->contents,
+                                           (*auth_context)->keyblock->length,
+                                           &checksum))
            goto cleanup_cksum;
     } else 
         if ((*auth_context)->cksumtype == 0x8003) {
@@ -151,9 +153,11 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds,
            checksum.contents = (krb5_octet *) in_data->data;
         } else 
            if (retval = krb5_calculate_checksum(context, 
-                                                (*auth_context)->cksumtype, 
-                                                in_data->data, in_data->length,
-                                                0, 0, &checksum))
+                                           (*auth_context)->cksumtype, 
+                                           in_data->data, in_data->length,
+                                           (*auth_context)->keyblock->contents,
+                                           (*auth_context)->keyblock->length,
+                                           &checksum))
                goto cleanup_cksum;
 
     /* Generate authenticator */
index 1dd981611682479203c0dce3f10e390f7050f0b6..8ae69eb02d3931f1ceddde669b25d82520d0e03e 100644 (file)
@@ -45,10 +45,11 @@ krb5_rd_rep(context, auth_context, inbuf, repl)
     const krb5_data    * inbuf;
     krb5_ap_rep_enc_part **repl;
 {
-    krb5_error_code retval;
-    krb5_ap_rep *reply;
-    krb5_encrypt_block eblock;
-    krb5_data scratch;
+    krb5_error_code      retval;
+    krb5_ap_rep        * reply;
+    krb5_keyblock      * keyblock;
+    krb5_encrypt_block           eblock;
+    krb5_data            scratch;
 
     if (!krb5_is_ap_rep(inbuf))
        return KRB5KRB_AP_ERR_MSG_TYPE;
@@ -72,8 +73,13 @@ krb5_rd_rep(context, auth_context, inbuf, repl)
        return(ENOMEM);
     }
 
+    if (auth_context->local_subkey) 
+       keyblock = auth_context->local_subkey;
+    else
+       keyblock = auth_context->keyblock;
+
     /* do any necessary key pre-processing */
-    if (retval = krb5_process_key(context, &eblock, auth_context->keyblock)) {
+    if (retval = krb5_process_key(context, &eblock, keyblock)) {
        goto errout;
     }
 
index 6a6875ab18767b864688a4e7861f8705b6ab46f6..33f12cc711b66cc3af3041420d33902631c72d8a 100644 (file)
  */
 
 #include "k5-int.h"
+#include "auth_con.h"
 
 /*
  *  Parses a KRB_AP_REQ message, returning its contents.
  * 
  *  server specifies the expected server's name for the ticket.
  * 
- *  sender_addr specifies the address(es) expected to be present in the
- *  ticket.
- * 
- *  rcache specifies a replay detection cache used to store authenticators and
- *  server names
- * 
  *  keyproc specifies a procedure to generate a decryption key for the
  *  ticket.  If keyproc is non-NULL, keyprocarg is passed to it, and the result
  *  used as a decryption key. If keyproc is NULL, then fetchfrom is checked;
  *  decryption key.  If fetchfrom is NULL, then the default key store is
  *  consulted.
  * 
- *  authdat is set to point at allocated storage structures; the caller
- *  should free them when finished. 
- * 
  *  returns system errors, encryption errors, replay errors
  */
 
 krb5_error_code INTERFACE
-krb5_rd_req(context, inbuf, server, sender_addr, fetchfrom, keyproc, 
-           keyprocarg, rcache, authdat)
-    krb5_context context;
-    const krb5_data *inbuf;
-    krb5_const_principal server;
-    const krb5_address *sender_addr;
-    const char * fetchfrom;
-    krb5_rdreq_key_proc keyproc;
-    krb5_pointer keyprocarg;
-    krb5_rcache rcache;
-    krb5_tkt_authent **authdat;
+krb5_rd_req(context, auth_context, inbuf, server, keytab, 
+           ap_req_options, ticket)
+    krb5_context         context;
+    krb5_auth_context  ** auth_context;
+    const krb5_data    * inbuf;
+    krb5_const_principal  server;      /* XXX do we really need this */
+    krb5_keytab                  keytab;
+    krb5_flags         * ap_req_options;
+    krb5_ticket               ** ticket;
 {
-    krb5_error_code retval;
-    krb5_ap_req *request;
+    krb5_error_code      retval;
+    krb5_ap_req        * request;
+    krb5_auth_context  * new_auth_context;
+    krb5_rcache           new_rcache;
+    krb5_keytab           new_keytab = NULL;
 
     if (!krb5_is_ap_req(inbuf))
        return KRB5KRB_AP_ERR_MSG_TYPE;
@@ -75,12 +68,41 @@ krb5_rd_req(context, inbuf, server, sender_addr, fetchfrom, keyproc,
        default:
            return(retval);
        }
+    }
+
+    /* Get an auth context if necessary. */
+    new_auth_context = NULL;
+    if (*auth_context == NULL) {
+       if (retval = krb5_auth_con_init(context, &new_auth_context))
+           goto cleanup_request;
+        *auth_context = new_auth_context;
+    }
 
+    /* Get an rcache if necessary. */
+    if (((*auth_context)->rcache == NULL) && server) {
+       if (retval = krb5_get_server_rcache(context,
+            krb5_princ_component(context,server,0), &(*auth_context)->rcache))
+           goto cleanup_auth_context;
     }
 
-    retval = krb5_rd_req_decoded(context, request, server, sender_addr, 
-                                fetchfrom, keyproc, keyprocarg, rcache, 
-                                authdat);
+    /* Get a keytab if necessary. */
+    if (keytab == NULL) {
+       if (retval = krb5_kt_default(context, &new_keytab))
+           goto cleanup_auth_context;
+       keytab = new_keytab;
+    }
+
+    retval = krb5_rd_req_decoded(context, auth_context, request, server, 
+                                keytab, ap_req_options, ticket);
+
+    if (new_keytab == NULL)
+        (void) krb5_kt_close(context, new_keytab);
+
+cleanup_auth_context:
+    if (new_auth_context && retval)
+       krb5_auth_con_free(context, new_auth_context);
+
+cleanup_request:
     krb5_free_ap_req(context, request);
     return retval;
 }
index e8599795b5abac6f24686d121598c33539905843..85552960a03f49dc89c83a4d8911acbced53c7d6 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include "k5-int.h"
+#include "auth_con.h"
 
 /*
  * essentially the same as krb_rd_req, but uses a decoded AP_REQ as
@@ -39,9 +40,6 @@
  *  any server will be accepted if the key can be found, and the caller should
  *  verify that the principal is something it trusts.
  * 
- *  sender_addr specifies the address(es) expected to be present in the
- *  ticket.
- * 
  *  rcache specifies a replay detection cache used to store authenticators and
  *  server names
  * 
@@ -64,103 +62,80 @@ static krb5_error_code decrypt_authenticator
 extern krb5_deltat krb5_clockskew;
 #define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew)
 
-krb5_error_code INTERFACE
-krb5_rd_req_decoded(context, req, server, sender_addr, fetchfrom, keyproc,
-                   keyprocarg, rcache, authdat)
-    krb5_context context;
-    const krb5_ap_req *req;
-    krb5_const_principal server;
-    const krb5_address *sender_addr;
-    const char * fetchfrom;
-    krb5_rdreq_key_proc keyproc;
-    krb5_pointer keyprocarg;
-    krb5_rcache rcache;
-    krb5_tkt_authent **authdat;
-{
-    krb5_keytype keytype;
-    krb5_error_code retval = 0;
-    krb5_keyblock *tkt_key = NULL;
-    krb5_timestamp currenttime, starttime;
-    krb5_tkt_authent   *tktauthent = NULL;
+static krb5_error_code
+krb5_rd_req_decrypt_tkt_part(context, req, keytab)
+    krb5_context          context;
+    const krb5_ap_req  * req;
+    krb5_keytab           keytab;
 
-    if (server && !krb5_principal_compare(context, server, req->ticket->server))
-       return KRB5KRB_AP_WRONG_PRINC;
+{
+    krb5_error_code      retval;
+    krb5_keytype         keytype;
+    krb5_keytab_entry    ktent;
 
-    /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
-       do we need special processing here ?    */
-    
     /*
      * OK we know the encryption type req->ticket->enc_part.etype, 
      * and now we need to get the keytype
      */
     keytype = krb5_csarray[req->ticket->enc_part.etype]->system->proto_keytype;
 
-    /* fetch a server key */
-    if (keyproc) {
-       retval = (*keyproc)(context, keyprocarg, req->ticket->server,
-                           req->ticket->enc_part.kvno, keytype, &tkt_key);
-    } else {
-       krb5_keytab keytabid;
-       krb5_keytab_entry ktentry;
-
-       if (fetchfrom) {
-           /* use the named keytab */
-           retval = krb5_kt_resolve(context, fetchfrom, &keytabid);
-       } else {
-           /* use default keytab */
-           retval = krb5_kt_default(context, &keytabid);
-       }
-       if (!retval) {
-           retval = krb5_kt_get_entry(context, keytabid, req->ticket->server,
-                                      req->ticket->enc_part.kvno, keytype,
-                                      &ktentry);
-           (void) krb5_kt_close(context, keytabid);
-           if (!retval) {
-               retval = krb5_copy_keyblock(context, &ktentry.key, &tkt_key);
-               (void) krb5_kt_free_entry(context, &ktentry);
-           }
-       }
-    }
-    if (retval)
-       return retval;                  /* some error in getting the key */
+    if (retval = krb5_kt_get_entry(context, keytab, req->ticket->server,
+                                  req->ticket->enc_part.kvno, keytype, &ktent))
+       return retval;
 
-    /* decrypt the ticket */
-    if (retval = krb5_decrypt_tkt_part(context, tkt_key, req->ticket)) {
-       krb5_free_keyblock(context, tkt_key);
-       return(retval);
-    }
+    if (retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket)) 
+       return retval;
 
-    /*
-     * Now we allocate space for the krb5_tkt_authent structure.  If
-     * we ever have an error, we're responsible for freeing it.
-     */
-    if (!(tktauthent =
-         (krb5_tkt_authent *) malloc(sizeof(*tktauthent)))) {
-           retval = ENOMEM;
-           goto cleanup;
+    (void) krb5_kt_free_entry(context, &ktent);
+    return retval;
+}
+
+krb5_error_code INTERFACE
+krb5_rd_req_decoded(context, auth_context, req, server, keytab, 
+                   ap_req_options, ticket)
+    krb5_context         context;
+    krb5_auth_context  ** auth_context;
+    const krb5_ap_req  * req;
+    krb5_const_principal  server;
+    krb5_keytab           keytab;
+    krb5_flags          * ap_req_options;
+    krb5_ticket               ** ticket;
+{
+    krb5_error_code      retval = 0;
+    krb5_timestamp       currenttime, starttime;
+
+    if (server && !krb5_principal_compare(context, server, req->ticket->server))
+       return KRB5KRB_AP_WRONG_PRINC;
+
+    /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
+       do we need special processing here ?    */
+
+    /* decrypt the ticket */
+    if ((*auth_context)->keyblock) { /* User to User authentication */
+       if (retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock,
+                                          req->ticket)) 
+           return retval;
+       krb5_free_keyblock(context, (*auth_context)->keyblock);
+       (*auth_context)->keyblock = NULL;
+    } else {
+       if (retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab))
+           return retval;
     }
-    
-    memset((char *)tktauthent, 0, sizeof(*tktauthent));
 
-    if (retval = decrypt_authenticator(context, req, &tktauthent->authenticator))
+    if (retval = decrypt_authenticator(context, req, 
+                                      &((*auth_context)->authentp)))
        goto cleanup;
-    *authdat = NULL;           /* Set authdat to tktauthent when we finish */
 
-    if (!krb5_principal_compare(context, tktauthent->authenticator->client,
+    if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
                                req->ticket->enc_part2->client)) {
        retval = KRB5KRB_AP_ERR_BADMATCH;
        goto cleanup;
     }
-    if (sender_addr && !krb5_address_search(context, sender_addr, req->ticket->enc_part2->caddrs)) {
-       retval = KRB5KRB_AP_ERR_BADADDR;
-       goto cleanup;
-    }
 
-    
-    if (retval = krb5_timeofday(context, &currenttime))
-       goto cleanup;
-    if (!in_clock_skew(tktauthent->authenticator->ctime)) {
-       retval = KRB5KRB_AP_ERR_SKEW;
+    if ((*auth_context)->remote_addr && 
+      !krb5_address_search(context, (*auth_context)->remote_addr, 
+                          req->ticket->enc_part2->caddrs)) {
+       retval = KRB5KRB_AP_ERR_BADADDR;
        goto cleanup;
     }
 
@@ -170,33 +145,37 @@ krb5_rd_req_decoded(context, req, server, sender_addr, fetchfrom, keyproc,
 
     /* Single hop cross-realm tickets only */
 
-    { krb5_transited *trans = &(req->ticket->enc_part2->transited);
-
-      /* If the transited list is empty, then we have at most one hop */
+    { 
+       krb5_transited *trans = &(req->ticket->enc_part2->transited);
 
-      if (trans->tr_contents.data && trans->tr_contents.data[0]) {
-        retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
-      }
+       /* If the transited list is empty, then we have at most one hop */
+       if (trans->tr_contents.data && trans->tr_contents.data[0])
+            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
     }
 
 #elif defined(_NO_CROSS_REALM)
 
     /* No cross-realm tickets */
 
-    { char           *lrealm;
-      krb5_data      *realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
-      krb5_transited *trans = &(req->ticket->enc_part2->transited);
-
-      /* If the transited list is empty, then we have at most one hop      */
-      /* So we also have to check that the client's realm is the local one */
-
-      krb5_get_default_realm(context, &lrealm);
-      if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
+    { 
+       char            * lrealm;
+       krb5_data       * realm;
+       krb5_transited  * trans;
+  
+       realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
+       trans = &(req->ticket->enc_part2->transited);
+
+       /*
+        * If the transited list is empty, then we have at most one hop 
+        * So we also have to check that the client's realm is the local one 
+        */
+       krb5_get_default_realm(context, &lrealm);
+       if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
           strlen(lrealm) != realm->length ||
           memcmp(lrealm, realm->data, strlen(lrealm))) {
-        retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
-      }
-      free(lrealm);
+            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+       }
+       free(lrealm);
     }
 
 #else
@@ -204,21 +183,25 @@ krb5_rd_req_decoded(context, req, server, sender_addr, fetchfrom, keyproc,
     /* Hierarchical Cross-Realm */
   
     {
-      krb5_data      lrealm;
-      krb5_data      *realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
-      krb5_transited *trans = &(req->ticket->enc_part2->transited);
+       krb5_data        lrealm;
+       krb5_data      * realm;
+       krb5_transited * trans;
   
-      /* If the transited list is not empty, then check that all realms */
-      /* transited are within the hierarchy between the client's realm  */
-      /* and the local realm.                                           */
-  
-      if (trans->tr_contents.data && trans->tr_contents.data[0]) {
-        krb5_get_default_realm(context, &(lrealm.data));
-        lrealm.length = strlen(lrealm.data);
-        retval = krb5_check_transited_list(context, &(trans->tr_contents), realm,
-                                           &lrealm);
-        free(lrealm.data);
-      }
+       realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
+       trans = &(req->ticket->enc_part2->transited);
+
+       /*
+        * If the transited list is not empty, then check that all realms 
+        * transited are within the hierarchy between the client's realm  
+        * and the local realm.                                        
+        */
+       if (trans->tr_contents.data && trans->tr_contents.data[0]) {
+            lrealm.length = strlen(lrealm.data);
+            krb5_get_default_realm(context, &(lrealm.data));
+            retval = krb5_check_transited_list(context, &(trans->tr_contents), 
+                                              realm, &lrealm);
+            free(lrealm.data);
+       }
     }
 
 #endif
@@ -227,18 +210,19 @@ krb5_rd_req_decoded(context, req, server, sender_addr, fetchfrom, keyproc,
 
     /* only check rcache if sender has provided one---some services
        may not be able to use replay caches (such as datagram servers) */
-    if (rcache) {
-       krb5_donot_replay rep;
 
-       tktauthent->ticket = req->ticket;       /* Temporary; allocated below */
-       retval = krb5_auth_to_rep(context, tktauthent, &rep);
-       tktauthent->ticket = 0;                 /* Don't allow cleanup to free
-                                                  original ticket.  */
-       if (retval)
-           goto cleanup;
-       retval = krb5_rc_store(context, rcache, &rep);
-       krb5_xfree(rep.server);
-       krb5_xfree(rep.client);
+    if ((*auth_context)->rcache) {
+       krb5_donot_replay  rep;
+        krb5_tkt_authent   tktauthent;
+
+       tktauthent.ticket = req->ticket;        
+       tktauthent.authenticator = (*auth_context)->authentp;
+       if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
+           retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
+           krb5_xfree(rep.server);
+           krb5_xfree(rep.client);
+       }
+
        if (retval)
            goto cleanup;
     }
@@ -249,10 +233,16 @@ krb5_rd_req_decoded(context, req, server, sender_addr, fetchfrom, keyproc,
     else
        starttime = req->ticket->enc_part2->times.authtime;
 
+    if (retval = krb5_timeofday(context, &currenttime))
+       goto cleanup;
     if (starttime - currenttime > krb5_clockskew) {
        retval = KRB5KRB_AP_ERR_TKT_NYV;        /* ticket not yet valid */
        goto cleanup;
     }  
+    if (!in_clock_skew((*auth_context)->authentp->ctime)) {
+       retval = KRB5KRB_AP_ERR_SKEW;
+       goto cleanup;
+    }
     if (currenttime - req->ticket->enc_part2->times.endtime > krb5_clockskew) {
        retval = KRB5KRB_AP_ERR_TKT_EXPIRED;    /* ticket expired */
        goto cleanup;
@@ -261,25 +251,38 @@ krb5_rd_req_decoded(context, req, server, sender_addr, fetchfrom, keyproc,
        retval = KRB5KRB_AP_ERR_TKT_INVALID;
        goto cleanup;
     }
-    retval = krb5_copy_ticket(context, req->ticket, &tktauthent->ticket);
+
+    (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
+    (*auth_context)->remote_subkey = (*auth_context)->authentp->subkey;
+    if (retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session,
+                                   &((*auth_context)->keyblock)))
+       goto cleanup;
+
+    /*
+     * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used 
+     * then the default sequence number is the one's complement of the
+     * sequence number sent ot us.
+     */
+    if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && 
+      (*auth_context)->remote_seq_number) {
+       (*auth_context)->local_seq_number ^= 
+         (*auth_context)->remote_seq_number;
+    }
+
+    if (ticket)
+       if (retval = krb5_copy_ticket(context, req->ticket, ticket))
+           goto cleanup;
+    if (ap_req_options)
+       *ap_req_options = req->ap_options;
+    retval = 0;
     
 cleanup:
-    if (tktauthent) {
-        if (retval) {
-           krb5_free_tkt_authent(context, tktauthent);
-        } else {
-           tktauthent->ap_options = req->ap_options;
-           *authdat = tktauthent;
-       }
-    }
-    if (retval && req->ticket->enc_part2) {
+    if (retval) {
        /* only free if we're erroring out...otherwise some
           applications will need the output. */
         krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
        req->ticket->enc_part2 = NULL;
     }
-    if (tkt_key)
-       krb5_free_keyblock(context, tkt_key);
     return retval;
 }
 
@@ -318,9 +321,10 @@ decrypt_authenticator(context, request, authpp)
     }
 
     /* call the encryption routine */
-    if (retval = krb5_decrypt(context, (krb5_pointer) request->authenticator.ciphertext.data,
-                             (krb5_pointer) scratch.data,
-                             scratch.length, &eblock, 0)) {
+    if (retval = krb5_decrypt(context, 
+                          (krb5_pointer)request->authenticator.ciphertext.data,
+                          (krb5_pointer)scratch.data,
+                          scratch.length, &eblock, 0)) {
        (void) krb5_finish_key(context, &eblock);
        free(scratch.data);
        return retval;
index 7c0a94ec3a93c0282b1baf97af299f81da2a846b..aa5dd35382e3df36a28dc3b0463d21f37356020b 100644 (file)
@@ -164,7 +164,7 @@ cleanup:
 krb5_error_code INTERFACE
 krb5_rd_safe(context, auth_context, inbuf, outbuf, outdata)
     krb5_context       context;
-    krb5_auth_context *  auth_context;
+    krb5_auth_context * auth_context;
     const krb5_data   * inbuf;
     krb5_data        * outbuf;
     krb5_replay_data  * outdata;
@@ -184,7 +184,7 @@ krb5_rd_safe(context, auth_context, inbuf, outbuf, outdata)
 
     if (retval = krb5_rd_safe_basic(context, inbuf, auth_context->keyblock,
       auth_context->local_addr, auth_context->remote_addr,
-      auth_context->cksumtype, &replaydata, outbuf))
+      &replaydata, outbuf))
        return retval;
 
     if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
index 8b1e832e630d3310b9a407195faeb7d1e82bb039..02c9e42cf6befa4c4a45d3d38e8c387d521bff33 100644 (file)
@@ -26,6 +26,7 @@
 
 #define NEED_SOCKETS
 #include "k5-int.h"
+#include "auth_con.h"
 #include "com_err.h"
 #include <errno.h>
 #include <stdio.h>
@@ -36,37 +37,29 @@ extern krb5_flags   krb5_kdc_default_options;
 static char *sendauth_version = "KRB5_SENDAUTH_V1.0";
 
 krb5_error_code INTERFACE
-krb5_recvauth(context, 
+krb5_recvauth(context, auth_context,
              /* IN */
-             fd, appl_version, server, sender_addr, fetch_from,
-             keyproc, keyprocarg, rc_type, flags,
+             fd, appl_version, server, rc_type, flags, keytab,
              /* OUT */
-             seq_number, client, ticket, authent)
-       krb5_context context;
-       krb5_pointer    fd;
-       char    *appl_version;
-       krb5_principal  server;
-       krb5_address    *sender_addr;
-       krb5_pointer    fetch_from;
-       krb5_int32      *seq_number;
-       char            *rc_type;
-       krb5_int32      flags;
-       krb5_rdreq_key_proc keyproc;
-       krb5_pointer keyprocarg;
-       krb5_principal  *client;
-       krb5_ticket     **ticket;
-       krb5_authenticator      **authent;
+             ticket)
+    krb5_context         context;
+    krb5_auth_context  ** auth_context;
+    krb5_pointer         fd;
+    char               * appl_version;
+    krb5_principal       server;
+    char               * rc_type;
+    krb5_int32           flags;
+    krb5_keytab                  keytab;
+    krb5_ticket               ** ticket;
 {
-       krb5_error_code         retval, problem;
-       krb5_data               inbuf;
-       krb5_tkt_authent        *authdat;
-       krb5_data               outbuf;
-       krb5_rcache             rcache;
-       krb5_octet              response;
-       krb5_data               *server_name, null_server;
-       char                    *cachename;
-       extern krb5_deltat krb5_clockskew;
-       static char             *rc_base = "rc_";
+    krb5_flags           ap_option;
+    krb5_error_code      retval, problem;
+    krb5_data            inbuf;
+    krb5_data            outbuf;
+    krb5_rcache          rcache;
+    krb5_octet           response;
+    krb5_data            null_server;
+    extern krb5_deltat           krb5_clockskew;
        
        /*
         * Zero out problem variable.  If problem is set at the end of
@@ -133,71 +126,60 @@ krb5_recvauth(context,
         * Now we actually write the response.  If the response is non-zero,
         * exit with a return value of problem
         */
-       if ((krb5_net_write(context, *((int *) fd), (char *)&response, 1)) < 0) {
+       if ((krb5_net_write(context, *((int *)fd), (char *)&response, 1)) < 0) {
                return(problem); /* We'll return the top-level problem */
        }
        if (problem)
                return(problem);
-       rcache = NULL;
        /*
         * Setup the replay cache.
         */
-       if (!(rcache = (krb5_rcache) malloc(sizeof(*rcache)))) 
-               problem = ENOMEM;
-       if (!problem) 
-               problem = krb5_rc_resolve_type(context, &rcache,
-                                              rc_type ? rc_type : "dfl");
-       cachename = NULL;
        if (server) {
-           server_name = krb5_princ_component(context, server, 0);
+           problem = krb5_get_server_rcache(context, 
+                       krb5_princ_component(context, server, 0), &rcache);
        } else {
-           null_server.data = "default";
            null_server.length = 7;
-           server_name = &null_server;
-       }
-       
-       if (!problem && !(cachename = malloc(server_name->length+1+strlen(rc_base))))
-           problem = ENOMEM;
-       if (!problem) {
-           strcpy(cachename, rc_base ? rc_base : "rc_");
-           strncat(cachename, server_name->data, server_name->length);
-           cachename[server_name->length+strlen(rc_base)] = '\0';
-           problem = krb5_rc_resolve(context, rcache, cachename);
+           null_server.data = "default";
+           problem = krb5_get_server_rcache(context, &null_server, &rcache);
        }
-       if (!problem) {
-               if (krb5_rc_recover(context, rcache))
-                       /*
-                        * If the rc_recover didn't work, then try
-                        * initializing the replay cache.
-                        */
-                       problem = krb5_rc_initialize(context, rcache, krb5_clockskew);
-               if (problem) {
-                       krb5_rc_close(context, rcache);
-                       rcache = NULL;
-               }
+
+    if (!problem) {
+       if (krb5_rc_recover(context, rcache)) {
+           /*
+            * If the rc_recover() didn't work, then try
+            * initializing the replay cache.
+            */
+           if (krb5_rc_initialize(context, rcache, krb5_clockskew)) {
+               krb5_rc_close(context, rcache);
+               rcache = NULL;
+           }
        }
+    }
 
        /*
         * Now, let's read the AP_REQ message and decode it
         */
        if (retval = krb5_read_message(context, fd, &inbuf)) {
+               if (rcache)
                (void) krb5_rc_close(context, rcache);
-               if (cachename)
-                       free(cachename);
                return(retval);
        }
-       authdat = 0;                    /* so we can tell if we need to
-                                          free it later... */
+
+       if (*auth_context == NULL) {
+               if (retval = krb5_auth_con_init(context, auth_context))
+                       return(retval);
+       }
+
+       krb5_auth_con_setrcache(context, *auth_context, rcache);
+
        if (!problem)
-               problem = krb5_rd_req(context, &inbuf, server, sender_addr, fetch_from,
-                                     keyproc, keyprocarg, rcache, &authdat);
+               problem = krb5_rd_req(context, auth_context, &inbuf, server,
+                                     keytab, &ap_option, ticket);
        krb5_xfree(inbuf.data);
        if (rcache)
            retval = krb5_rc_close(context, rcache);
        if (!problem && retval)
                problem = retval;
-       if (cachename)
-               free(cachename);
        
        /*
         * If there was a problem, send back a krb5_error message,
@@ -231,86 +213,22 @@ krb5_recvauth(context,
        if (retval = krb5_write_message(context, fd, &outbuf)) {
                if (outbuf.data)
                        krb5_xfree(outbuf.data);
-               if (!problem)
-                       krb5_free_tkt_authent(context, authdat);
                return(retval);
        }
        if (problem) {
                /*
                 * We sent back an error, we need to return
                 */
-               if (authdat) krb5_free_tkt_authent(context, authdat);
                return(problem);
        }
-       /*
-        * Here lies the mutual authentication stuff...
-        *
-        * We're going to compose and send a AP_REP message.
-        */
-       if ((authdat->ap_options & AP_OPTS_MUTUAL_REQUIRED)) {
-               krb5_ap_rep_enc_part    repl;
 
-               /*
-                * Generate a random sequence number
-                */
-               if (seq_number &&
-                   (retval = krb5_generate_seq_number(context,
-                       authdat->ticket->enc_part2->session, seq_number))) {
-                   krb5_free_tkt_authent(context, authdat);
-                   return(retval);
-               }
-
-               repl.ctime = authdat->authenticator->ctime;
-               repl.cusec = authdat->authenticator->cusec;
-               repl.subkey = authdat->authenticator->subkey;
-               if (seq_number)
-                   repl.seq_number = *seq_number;
-               else
-                   repl.seq_number = 0;
-
-               if (retval = krb5_mk_rep(context, &repl,
-                                        authdat->ticket->enc_part2->session,
-                                        &outbuf)) {
-                       krb5_free_tkt_authent(context, authdat);
-                       return(retval);
-               }
-               if (retval = krb5_write_message(context, fd, &outbuf)) {
-                       krb5_xfree(outbuf.data);
-                       krb5_free_tkt_authent(context, authdat);
-                       return(retval);
-               }
-               krb5_xfree(outbuf.data);
+    /* Here lies the mutual authentication stuff... */
+    if ((ap_option & AP_OPTS_MUTUAL_REQUIRED)) {
+       if (retval = krb5_mk_rep(context, *auth_context, &outbuf)) {
+           return(retval);
        }
-       /*
-        * At this point, we've won.  We just need to copy whatever
-        * parts of the authdat structure which the user wants, clean
-        * up, and exit.
-        */
-       if (client)
-           if (retval =
-               krb5_copy_principal(context, authdat->ticket->enc_part2->client,
-                                   client)) {
-               krb5_free_tkt_authent(context, authdat);
-               return(retval);
-           }
-       /*
-        * The following efficiency hack assumes knowledge about the
-        * structure of krb5_tkt_authent.  If we later add additional
-        * allocated substructures to krb5_tkt_authent, they will have
-        * to be reflected here; otherwise, we will probably have a
-        * memory leak.
-        *
-        * If the user wants that part of the authdat structure,
-        * return it; otherwise free it.
-        */
-       if (ticket)
-               *ticket = authdat->ticket;
-       else
-               krb5_free_ticket(context, authdat->ticket);
-       if (authent)
-               *authent = authdat->authenticator;
-       else
-               krb5_free_authenticator(context, authdat->authenticator);
-       krb5_xfree(authdat);
-       return 0;
+       retval = krb5_write_message(context, fd, &outbuf);
+       krb5_xfree(outbuf.data);
+    }
+    return retval;
 }