* kdc_util.h: Added new prototypes for return_padata() and check_padata()
authorTheodore Tso <tytso@mit.edu>
Tue, 14 Nov 1995 00:47:37 +0000 (00:47 +0000)
committerTheodore Tso <tytso@mit.edu>
Tue, 14 Nov 1995 00:47:37 +0000 (00:47 +0000)
* kdc_preauth.c (return_padata): New function which calls out to each preauth
 type to see if it is necessary to return preauth data or not.
(return_pw_salt): New function responsible for returning the
KRB5_PW_SALT preauth information.

* do_as_req.c (process_as_req):  Move creation of the PW_SALT
preauthentication step into kdc_preauth.c.  Call return_pdata()
which is responsible for all padata info which is returned by
the KDC in the KRB_AS_REP message.

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

src/kdc/ChangeLog
src/kdc/do_as_req.c
src/kdc/kdc_preauth.c
src/kdc/kdc_util.h

index bea2674c16a38d2a91a2c981a5d1f4dba84edd54..acc9b73bae271d55adf2a95271abd8225d12bf24 100644 (file)
@@ -1,3 +1,20 @@
+Mon Nov 13 19:40:50 1995  Theodore Y. Ts'o  <tytso@dcl>
+
+       * kdc_util.h: Added new prototypes for return_padata() and
+               check_padata().
+
+       * kdc_preauth.c (return_padata): New function which calls out to
+               each preauth type to see if it is necessary to return
+               preauth data or not.
+       (return_pw_salt): New function responsible for returning the
+               KRB5_PW_SALT preauth information.
+
+       * do_as_req.c (process_as_req):  Move creation of the PW_SALT
+               preauthentication step into kdc_preauth.c.  Call
+               return_pdata() which is responsible for all padata info
+               which is returned by the KDC in the KRB_AS_REP message.
+
+
 Thu Nov  9 00:05:55 1995  Theodore Y. Ts'o  <tytso@dcl>
 
        * kdc_preauth.c (get_etype_info): Added function to return the
index 3e7ebc99a27158a19bfbc5ae533ac7c0f18d50c9..9542c05d86a870ee0ea80a4686ffcae6eade411f 100644 (file)
@@ -63,13 +63,10 @@ krb5_data **response;                       /* filled in with a response packet */
     krb5_enc_tkt_part enc_tkt_reply;
     krb5_error_code errcode;
     int c_nprincs = 0, s_nprincs = 0;
-    int pa_id, pa_flags;
     krb5_boolean more;
     krb5_timestamp kdc_time, authtime;
     krb5_keyblock *session_key = 0;
     krb5_keyblock encrypting_key;
-    krb5_pa_data *padat_tmp[2], padat_local;
-    krb5_data salt_data;
     const char *status;
     krb5_encrypt_block eblock;
     krb5_key_data  *server_key, *client_key;
@@ -83,8 +80,8 @@ krb5_data **response;                 /* filled in with a response packet */
     char *cname = 0, *sname = 0, *fromstring = 0;
 
     ticket_reply.enc_part.ciphertext.data = 0;
-    salt_data.data = 0;
     e_data.data = 0;
+    encrypting_key.contents = 0;
 
 #ifdef KRB5_USE_INET
     if (from->address->addrtype == ADDRTYPE_INET)
@@ -326,6 +323,7 @@ krb5_data **response;                       /* filled in with a response packet */
     errcode = krb5_encrypt_tkt_part(kdc_context, &encrypting_key, &ticket_reply);
     memset((char *)encrypting_key.contents, 0, encrypting_key.length);
     krb5_xfree(encrypting_key.contents);
+    encrypting_key.contents = 0;
     if (errcode) {
        status = "ENCRYPTING_TICKET";
        goto errout;
@@ -353,66 +351,25 @@ krb5_data **response;                     /* filled in with a response packet */
        goto errout;
     }
 
+    /* convert client.key_data into a real key */
+    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, 
+                                              client_key, &encrypting_key,
+                                              NULL))) {
+       status = "DECRYPT_CLIENT_KEY";
+       goto errout;
+    }
+    encrypting_key.enctype = useenctype;
+
     /* Start assembling the response */
     reply.msg_type = KRB5_AS_REP;
-
     reply.padata = 0;
-
-    if (client_key->key_data_ver > 1) {
-        padat_tmp[0] = &padat_local;
-        padat_tmp[1] = 0;
-        padat_tmp[0]->pa_type = KRB5_PADATA_PW_SALT;
-
-       /* WARNING: sharing substructure here, but it's not a real problem,
-          since nothing below will "pull out the rug" */
-
-       switch (client_key->key_data_type[1]) {
-           krb5_data *data_foo;
-       case KRB5_KDB_SALTTYPE_NORMAL:
-           reply.padata = (krb5_pa_data **) NULL;
-           break;
-       case KRB5_KDB_SALTTYPE_V4:
-           /* send an empty (V4) salt */
-           padat_tmp[0]->contents = 0;
-           padat_tmp[0]->length = 0;
-           reply.padata = padat_tmp;
-           break;
-       case KRB5_KDB_SALTTYPE_NOREALM:
-           if ((errcode = krb5_principal2salt_norealm(kdc_context, 
-                                                     request->client,
-                                                      &salt_data))) {
-               status = "SALT_NOREALM";
-               goto errout;
-           }
-           padat_tmp[0]->contents = (krb5_octet *)salt_data.data;
-           padat_tmp[0]->length = salt_data.length;
-           reply.padata = padat_tmp;
-           break;
-       case KRB5_KDB_SALTTYPE_ONLYREALM:
-           data_foo = krb5_princ_realm(kdc_context, request->client);
-           padat_tmp[0]->contents = (krb5_octet *)data_foo->data;
-           padat_tmp[0]->length = data_foo->length;
-           reply.padata = padat_tmp;
-           break;
-       case KRB5_KDB_SALTTYPE_SPECIAL:
-           padat_tmp[0]->contents = client_key->key_data_contents[1];
-           padat_tmp[0]->length = client_key->key_data_length[1];
-           reply.padata = padat_tmp;
-           break;
-       }
-    }
-
     reply.client = request->client;
-
     reply.ticket = &ticket_reply;
-
     reply_encpart.session = session_key;
     if ((errcode = fetch_last_req_info(&client, &reply_encpart.last_req))) {
        status = "FETCH_LAST_REQ";
        goto errout;
     }
-
     reply_encpart.nonce = request->nonce;
     reply_encpart.key_exp = client.expiration;
     reply_encpart.flags = enc_tkt_reply.flags;
@@ -424,20 +381,19 @@ krb5_data **response;                     /* filled in with a response packet */
     reply_encpart.times.authtime = authtime = kdc_time;
 
     reply_encpart.caddrs = enc_tkt_reply.caddrs;
-
-    /* now encode/encrypt the response */
-
-    reply.enc_part.enctype = useenctype;
     reply.enc_part.kvno = client_key->key_data_kvno;
 
-    /* convert client.key_data into a real key */
-    if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock, 
-                                              client_key, &encrypting_key,
-                                              NULL))) {
-       status = "DECRYPT_CLIENT_KEY";
+    /* Fetch the padata info to be returned */
+    errcode = return_padata(kdc_context, &client, request, &reply, client_key,
+                           &encrypting_key);
+    if (errcode) {
+       status = "KDC_RETURN_PADATA";
        goto errout;
     }
-    encrypting_key.enctype = useenctype;
+
+    /* now encode/encrypt the response */
+
+    reply.enc_part.enctype = encrypting_key.enctype;
 
     errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP, &reply_encpart, 
                                  &eblock, &encrypting_key,  &reply, response);
@@ -481,6 +437,10 @@ errout:
            
        errcode = prepare_error_as(request, errcode, &e_data, response);
     }
+    if (encrypting_key.contents) {
+       memset((char *)encrypting_key.contents, 0, encrypting_key.length);
+       krb5_xfree(encrypting_key.contents);
+    }
     if (cname)
            free(cname);
     if (sname)
@@ -510,8 +470,6 @@ errout:
               ticket_reply.enc_part.ciphertext.length);
        free(ticket_reply.enc_part.ciphertext.data);
     }
-    if (salt_data.data)
-       krb5_xfree(salt_data.data);
     if (e_data.data)
        krb5_xfree(e_data.data);
     
index 056cd0681150dd1942bc57ac9bd7747050916afb..10cd2c52ddf04f6fd2d8e31be4b4c7eaba0be85f 100644 (file)
@@ -38,15 +38,25 @@ typedef krb5_error_code (edata_proc)
                    krb5_db_entry *client, krb5_db_entry *server,
                    krb5_pa_data *data));
 
+typedef krb5_error_code (return_proc)
+    KRB5_PROTOTYPE((krb5_context, krb5_pa_data * padata, 
+                   krb5_db_entry *client,
+                   krb5_kdc_req *request, krb5_kdc_rep *reply,
+                   krb5_key_data *client_key,
+                   krb5_keyblock *encrypting_key,
+                   krb5_pa_data **send_pa));
+
 typedef struct _krb5_preauth_systems {
     int                type;
     int                flags;
     edata_proc *get_edata;
-    verify_proc        *verify;
+    verify_proc        *verify_padata;
+    return_proc *return_padata;
 } krb5_preauth_systems;
 
 static verify_proc verify_enc_timestamp;
 static edata_proc get_etype_info;
+static return_proc return_pw_salt;
 
 /*
  * Preauth property flags
@@ -61,13 +71,22 @@ static krb5_preauth_systems preauth_systems[] = {
         0,
         0,
        verify_enc_timestamp,
+       0
     },
     {
        KRB5_PADATA_ETYPE_INFO,
        0,
        get_etype_info,
+       0,
        0
     },
+    {
+       KRB5_PADATA_PW_SALT,
+       0,
+       0, 
+       0,
+       return_pw_salt
+    },
     { -1,}
 };
 
@@ -88,45 +107,6 @@ find_pa_system(type, preauth)
     return 0;
 } 
 
-krb5_error_code
-krb5_decrypt_data(context, key, ivec, enc_data, data)
-    krb5_context       context;
-    krb5_keyblock *    key;
-    krb5_pointer       ivec;
-    krb5_enc_data *    enc_data;
-    krb5_data *                data;
-{
-    krb5_error_code    retval;
-    krb5_encrypt_block eblock;
-
-    krb5_use_enctype(context, &eblock, key->enctype);
-    data->length = enc_data->ciphertext.length;
-    if (!(data->data = malloc(data->length)))
-       return ENOMEM;
-
-    if ((retval = krb5_process_key(context, &eblock, key)) != 0)
-       goto cleanup;
-
-    if ((retval = krb5_decrypt(context,
-                              (krb5_pointer) enc_data->ciphertext.data,
-                              (krb5_pointer) data->data,
-                              enc_data->ciphertext.length, &eblock, ivec))) {
-       krb5_finish_key(context, &eblock);
-        goto cleanup;
-    }
-    (void) krb5_finish_key(context, &eblock);
-
-    return 0;
-
-cleanup:
-    if (data->data) {
-       free(data->data);
-       data->data = 0;
-    }
-    return retval;
-}
-
-    
 const char *missing_required_preauth(client, server, enc_tkt_reply)
     krb5_db_entry *client, *server;
     krb5_enc_tkt_part *enc_tkt_reply;
@@ -227,10 +207,10 @@ check_padata (context, client, request, enc_tkt_reply)
     for (padata = request->padata; *padata; padata++) {
        if (find_pa_system((*padata)->pa_type, &pa_sys))
            continue;
-       if (pa_sys->verify == 0)
+       if (pa_sys->verify_padata == 0)
            continue;
-       retval = pa_sys->verify(context, client, request,
-                               enc_tkt_reply, *padata);
+       retval = pa_sys->verify_padata(context, client, request,
+                                      enc_tkt_reply, *padata);
        if (retval) {
            if (pa_sys->flags & PA_REQUIRED)
                break;
@@ -244,6 +224,73 @@ check_padata (context, client, request, enc_tkt_reply)
     return retval;
 }
 
+/*
+ * return_padata creates any necessary preauthentication
+ * structures which should be returned by the KDC to the client
+ */
+krb5_error_code
+return_padata(context, client, request, reply,
+             client_key, encrypting_key)
+    krb5_context       context;
+    krb5_db_entry *    client;
+    krb5_kdc_req *     request;
+    krb5_kdc_rep *     reply;
+    krb5_key_data *    client_key;
+    krb5_keyblock *    encrypting_key;
+{
+    krb5_error_code            retval;
+    krb5_pa_data **            padata;
+    krb5_pa_data **            send_pa_list;
+    krb5_pa_data **            send_pa;
+    krb5_pa_data *             pa = 0;
+    krb5_preauth_systems *     ap;
+    int                        size;
+
+    for (ap = preauth_systems; ap->type != -1; ap++) {
+       if (ap->return_padata)
+           size++;
+    }
+
+    if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
+       return ENOMEM;
+
+    send_pa = send_pa_list;
+    *send_pa = 0;
+    
+    for (ap = preauth_systems; ap->type != -1; ap++) {
+       if (ap->return_padata == 0)
+           continue;
+       pa = 0;
+       if (request->padata) {
+           for (padata = request->padata; *padata; padata++) {
+               if ((*padata)->pa_type == ap->type) {
+                   pa = *padata;
+                   break;
+               }
+           }
+       }
+       if ((retval = ap->return_padata(context, pa, client, request, reply,
+                                       client_key, encrypting_key, send_pa)))
+           goto cleanup;
+
+       if (*send_pa)
+           send_pa++;
+       *send_pa = 0;
+    }
+    
+    retval = 0;
+
+    if (send_pa_list[0]) {
+       reply->padata = send_pa_list;
+       send_pa_list = 0;
+    }
+    
+cleanup:
+    if (send_pa_list)
+       krb5_free_pa_data(context, send_pa_list);
+    return (retval);
+}
+
 static krb5_error_code
 verify_enc_timestamp(context, client, request, enc_tkt_reply, pa)
     krb5_context       context;
@@ -281,7 +328,7 @@ verify_enc_timestamp(context, client, request, enc_tkt_reply, pa)
            goto cleanup;
        key.enctype = enc_data->enctype;
 
-       retval = krb5_decrypt_data(context, key, 0, enc_data, &enc_ts_data);
+       retval = krb5_decrypt_data(context, &key, 0, enc_data, &enc_ts_data);
        memset((char *)key.contents, 0, key.length);
        krb5_xfree(key.contents);
 
@@ -404,3 +451,77 @@ cleanup:
     return retval;
 }
 
+static krb5_error_code
+return_pw_salt(context, in_padata, client, request, reply, client_key,
+              encrypting_key, send_pa)
+    krb5_context       context;
+    krb5_pa_data *     in_padata;
+    krb5_db_entry *    client;
+    krb5_kdc_req *     request;
+    krb5_kdc_rep *     reply;
+    krb5_key_data *    client_key;
+    krb5_keyblock *    encrypting_key;
+    krb5_pa_data **    send_pa;
+{
+    krb5_error_code    retval;
+    krb5_pa_data *     padata;
+    krb5_data *                scratch;
+    krb5_data          salt_data;
+    
+    if (client_key->key_data_ver == 1 ||
+       client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)
+       return 0;
+
+    if ((padata = malloc(sizeof(krb5_pa_data))) == NULL)
+       return ENOMEM;
+    padata->magic = KV5M_PA_DATA;
+    padata->pa_type = KRB5_PADATA_PW_SALT;
+    
+    switch (client_key->key_data_type[1]) {
+    case KRB5_KDB_SALTTYPE_V4:
+       /* send an empty (V4) salt */
+       padata->contents = 0;
+       padata->length = 0;
+       break;
+    case KRB5_KDB_SALTTYPE_NOREALM:
+       if ((retval = krb5_principal2salt_norealm(kdc_context, 
+                                                  request->client,
+                                                  &salt_data)))
+           goto cleanup;
+       padata->contents = (krb5_octet *)salt_data.data;
+       padata->length = salt_data.length;
+       break;
+    case KRB5_KDB_SALTTYPE_ONLYREALM:
+       scratch = krb5_princ_realm(kdc_context, request->client);
+       if ((padata->contents = malloc(scratch->length)) == NULL) {
+           retval = ENOMEM;
+           goto cleanup;
+       }
+       memcpy(padata->contents, scratch->data, scratch->length);
+       padata->length = scratch->length;
+       break;
+    case KRB5_KDB_SALTTYPE_SPECIAL:
+       if ((padata->contents = malloc(client_key->key_data_length[1]))
+           == NULL) {
+           retval = ENOMEM;
+           goto cleanup;
+       }
+       memcpy(padata->contents, client_key->key_data_contents[1],
+              client_key->key_data_length[1]);
+       padata->length = client_key->key_data_length[1];
+       break;
+    default:
+       free(padata);
+       return 0;
+    }
+
+    *send_pa = padata;
+    return 0;
+    
+cleanup:
+    free(padata);
+    return retval;
+}
+
+    
+
index 7491ca90522447da726d20cd26baa8250e9f3e23..b869f6f8a5df798545c197328ae99f2adaf99788 100644 (file)
@@ -135,6 +135,14 @@ void get_preauth_hint_list PROTOTYPE((krb5_kdc_req * request,
                                      krb5_db_entry *client,
                                      krb5_db_entry *server,
                                      krb5_data *e_data));
+krb5_error_code check_padata
+    PROTOTYPE((krb5_context context, krb5_db_entry *client,
+              krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply));
+    
+krb5_error_code return_padata
+    PROTOTYPE((krb5_context context, krb5_db_entry *client,
+              krb5_kdc_req *request, krb5_kdc_rep *reply,
+              krb5_key_data *client_key, krb5_keyblock *encrypting_key));
     
 /* replay.c */
 krb5_boolean kdc_check_lookaside PROTOTYPE((krb5_data *, krb5_data **));