* encrypt_tk.c (cleanup_scratch): Changed interface to no longer require
authorTheodore Tso <tytso@mit.edu>
Wed, 8 Nov 1995 07:52:57 +0000 (07:52 +0000)
committerTheodore Tso <tytso@mit.edu>
Wed, 8 Nov 1995 07:52:57 +0000 (07:52 +0000)
an eblock; we can use our own and figure out the enctype
from the passed-in key.

* get_in_tkt.c (krb5_get_in_tkt): Added calls to krb5_obtain_padata().

* preauth.c: Completely restructured file to support preauthentication.

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

src/lib/krb5/krb/ChangeLog
src/lib/krb5/krb/encrypt_tk.c
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/preauth.c

index abf4ad153e8b773cf17b20c670eeee849bacdb6e..cf9852d687df2b2746ad079e908a44494b1f3116 100644 (file)
@@ -1,3 +1,16 @@
+Wed Nov  8 02:50:59 1995  Theodore Y. Ts'o  <tytso@dcl>
+
+       * encrypt_tk.c (cleanup_scratch): Changed interface to no longer
+               require an eblock; we can use our own and figure out the
+               enctype from the passed-in key.
+
+       * get_in_tkt.c (krb5_get_in_tkt): Added calls to
+               krb5_obtain_padata(). 
+
+       * preauth.c: Completely restructured file to support
+               preauthentication. 
+               
+
 Fri Oct 27 22:15:33 1995  Theodore Y. Ts'o  <tytso@dcl>
 
        * get_in_tkt.c (krb5_get_in_tkt): Extensive reworking of the
index 88b23209ae109ba67842ff3f540117b4e81f50a9..6203b783666c5e87e78fcbc1b10fa2c8afac4323 100644 (file)
 */
 
 krb5_error_code
-krb5_encrypt_tkt_part(context, eblock, srv_key, dec_ticket)
+krb5_encrypt_tkt_part(context, srv_key, dec_ticket)
     krb5_context context;
-    krb5_encrypt_block *eblock;
     const krb5_keyblock *srv_key;
     register krb5_ticket *dec_ticket;
 {
+    krb5_encrypt_block eblock;
     krb5_data *scratch;
     krb5_error_code retval;
     register krb5_enc_tkt_part *dec_tkt_part = dec_ticket->enc_part2;
@@ -57,8 +57,10 @@ krb5_encrypt_tkt_part(context, eblock, srv_key, dec_ticket)
 #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \
 krb5_free_data(context, scratch); }
 
+    krb5_use_enctype(kdc_context, &eblock, srv_key->enctype);
+
     dec_ticket->enc_part.ciphertext.length =
-       krb5_encrypt_size(scratch->length, eblock->crypto_entry);
+       krb5_encrypt_size(scratch->length, eblock.crypto_entry);
     /* add padding area, and zero it */
     if (!(scratch->data = realloc(scratch->data,
                                  dec_ticket->enc_part.ciphertext.length))) {
@@ -82,25 +84,25 @@ dec_ticket->enc_part.ciphertext.length = 0; \
 dec_ticket->enc_part.ciphertext.data = 0;}
 
     /* do any necessary key pre-processing */
-    if ((retval = krb5_process_key(context, eblock, srv_key))) {
+    if ((retval = krb5_process_key(context, &eblock, srv_key))) {
        goto clean_encpart;
     }
 
-#define cleanup_prockey() {(void) krb5_finish_key(context, eblock);}
+#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);}
 
     /* call the encryption routine */
     if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
                               (krb5_pointer) dec_ticket->enc_part.ciphertext.data,
-                              scratch->length, eblock, 0))) {
+                              scratch->length, &eblock, 0))) {
        goto clean_prockey;
     }
 
-    dec_ticket->enc_part.enctype = krb5_eblock_enctype(context, eblock);
+    dec_ticket->enc_part.enctype = srv_key->enctype;
 
     /* ticket is now assembled-- do some cleanup */
     cleanup_scratch();
 
-    if ((retval = krb5_finish_key(context, eblock))) {
+    if ((retval = krb5_finish_key(context, &eblock))) {
        cleanup_encpart();
        return retval;
     }
index 9e5e20a568138d110eef54d670169dd9ba853d13..3a71d89fcf78ad78b2e03836e43cb4b58cec8929 100644 (file)
@@ -98,7 +98,7 @@ send_as_request(context, request, time_now, ret_err_reply, ret_as_reply)
      * XXX we know they are the same size... and we should do
      * something better than just the current time
      */
-    request->nonce = (krb5_int32) time_now;
+    request->nonce = (krb5_int32) *time_now;
 
     /* encode & send to KDC */
     if ((retval = encode_krb5_as_req(request, &packet)) != 0)
@@ -452,13 +452,14 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed,
            retval = KRB5_GET_IN_TKT_LOOP;
            goto cleanup;
        }
-#if 0
-       if ((retval = krb5_obtain_padata(context, preauth_to_use, key_proc,
+
+       if ((retval = krb5_obtain_padata(context, preauth_to_use, 0, key_proc,
                                         keyseed, creds, &request)) != 0)
            goto cleanup;
-       krb5_free_pa_data(context, preauth_to_use);
+       if (preauth_to_use)
+           krb5_free_pa_data(context, preauth_to_use);
        preauth_to_use = 0;
-#endif
+       
        err_reply = 0;
        as_reply = 0;
        if ((retval = send_as_request(context, &request, &time_now, &err_reply,
@@ -483,13 +484,11 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed,
            retval = KRB5KRB_AP_ERR_MSG_TYPE;
            goto cleanup;
        }
-#if 0
        if ((retval = krb5_process_padata(context, &request, as_reply,
                                          key_proc, keyseed, creds,
                                          &do_more)) != 0)
            goto cleanup;
-       
-#endif
+
        if (!do_more)
            break;
     }
@@ -510,6 +509,8 @@ cleanup:
        free(request.ktype);
     if (!addrs && request.addresses)
        krb5_free_addresses(context, request.addresses);
+    if (request.padata)
+       krb5_free_pa_data(context, request.padata);
     if (padata)
        krb5_free_pa_data(context, padata);
     if (preauth_to_use)
index e41399a467a8fe514bd833268a02d5be5004e1a0..ae961a6ceb1f46f5227c19fc296fbe04b1f5195b 100644 (file)
  * this software for any purpose.  It is provided "as is" without express
  * or implied warranty.
  *
- * Sandia National Laboratories also makes no representations about the 
- * suitability of the modifications, or additions to this software for 
- * any purpose.  It is provided "as is" without express or implied warranty.
- *
- * Note: The internal interfaces to this routine are subject to change
- * and/or cleanup.  You should only expect the interfaces to
- * krb5_obtain_padata and krb5_verify_padata to have some chance of
- * staying stable.  [tytso:19920903.1544EDT]
  */
 
 /*
  * This file contains routines for establishing, verifying, and any other
  * necessary functions, for utilizing the pre-authentication field of the 
  * kerberos kdc request, with various hardware/software verification devices.
- *
- * Note: At some point these functions may very well be split apart
- * into different files.... [tytso:19920903.1618EDT]
  */
 
+
 #include "k5-int.h"
 #include <stdio.h>
 #include <time.h>
 #include <process.h>
 #endif
 
+static krb5_preauth_obtain_proc obtain_enc_ts_padata;
+
 static krb5_preauth_ops preauth_systems[] = {
     {
-       0,
-        KRB5_PADATA_ENC_UNIX_TIME,
-        KRB5_PREAUTH_FLAGS_ENCRYPT,
-        get_unixtime_padata,
-        verify_unixtime_padata,
-    },
-    {
-       0,
-       KRB5_PADATA_ENC_SANDIA_SECURID,
-       KRB5_PREAUTH_FLAGS_ENCRYPT | KRB5_PREAUTH_FLAGS_HARDWARE,
-       get_securid_padata,
-       verify_securid_padata,
+       KV5M_PREAUTH_OPS,
+       KRB5_PADATA_ENC_TIMESTAMP,
+        0,
+        obtain_enc_ts_padata,
+        0,
     },
     { -1,}
 };
 
-static krb5_error_code find_preauthenticator
+static krb5_error_code find_pa_system
     PROTOTYPE((int type, krb5_preauth_ops **Preauth_proc));
 
-/*
- *   krb5_obtain_padata  is a glue routine which when passed in
- *   a preauthentication type, client principal, and src_addr, returns
- *   preauthentication data contained in data to be passed onto the KDC.
- *   
- *   If problems occur then a non zero value is returned...
- *
- *   Note: This is a first crack at what any preauthentication will need...
- */
+/* some typedef's for the function args to make things look a bit cleaner */
+
+typedef krb5_error_code (*git_key_proc) PROTOTYPE((krb5_context,
+                                                  const krb5_enctype,
+                                                  krb5_data *,
+                                                  krb5_const_pointer,
+                                                  krb5_keyblock **));
+
 krb5_error_code
-krb5_obtain_padata(context, type, client, src_addr, encrypt_key, ret_data)
-    krb5_context context;
-    int type;                          /*IN:  Preauth type */
-    krb5_principal client;             /*IN:  requestor */
-    krb5_address **src_addr;            /*IN:  array of ptrs to addresses */
-    krb5_keyblock *encrypt_key;                /*IN:  encryption key */
-    krb5_pa_data **ret_data;                   /*OUT: Returned padata */
+krb5_encrypt_data(context, key, ivec, data, enc_data)
+    krb5_context       context;
+    krb5_keyblock *    key;
+    krb5_pointer       ivec;
+    krb5_data *                data;
+    krb5_enc_data *    enc_data;
 {
     krb5_error_code    retval;
-    krb5_preauth_ops   *p_system;
     krb5_encrypt_block eblock;
-    krb5_data          scratch;
-    krb5_pa_data       *data;
 
-    if (!ret_data)
-       return EINVAL;
-    *ret_data = 0;
-    
-    if (type == KRB5_PADATA_NONE ) 
-       return(0);
+    krb5_use_enctype(context, &eblock, key->enctype);
 
-    data = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
-    if (!data)
+    enc_data->magic = KV5M_ENC_DATA;
+    enc_data->kvno = 0;
+    enc_data->enctype = key->enctype;
+    enc_data->ciphertext.length = krb5_encrypt_size(data->length,
+                                                   eblock.crypto_entry);
+    enc_data->ciphertext.data = malloc(enc_data->ciphertext.length);
+    if (enc_data->ciphertext.data == 0)
        return ENOMEM;
-    
-    data->length = 0;
-    data->contents = 0;
-    data->pa_type = type;
 
-    /* Find appropriate preauthenticator */
-    retval = find_preauthenticator(type, &p_system);
-    if (retval)
-       goto error_out;
+    if ((retval = krb5_process_key(context, &eblock, key)) != 0)
+       goto cleanup;
 
-    retval = (*p_system->obtain)(context, client, src_addr, data );
-    if (retval)
-       goto error_out;
-
-    /* Check to see if we need to encrypt padata */
-    if (p_system->flags & KRB5_PREAUTH_FLAGS_ENCRYPT) {
-       /* If we dont have a encryption key we are out of luck */
-       if (!encrypt_key) {
-           retval = KRB5_PREAUTH_NO_KEY;
-           goto error_out;
-       }
-        krb5_use_enctype(context, &eblock, encrypt_key->enctype);
-
-       /* do any necessay key pre-processing */
-       retval = krb5_process_key(context, &eblock, encrypt_key);
-       if (retval)
-           goto error_out;
-       
-       /*
-        * Set up scratch data and length for encryption 
-        * Must allocate more space for checksum and confounder
-        * We also leave space for an uncrypted size field.
-        */
-       scratch.length = krb5_encrypt_size(data->length,
-                                          eblock.crypto_entry) + 4;
-       
-       if(!(scratch.data = malloc(scratch.length))){
-           (void) krb5_finish_key(context, &eblock);
-           retval = ENOMEM;
-           goto error_out;
-       }
-       
-       scratch.data[0] = data->length >> 24;
-       scratch.data[1] = data->length >> 16;
-       scratch.data[2] = data->length >> 8;
-       scratch.data[3] = data->length;
-
-       /* Encrypt preauth data in encryption key */
-       if ((retval = krb5_encrypt(context, (krb5_pointer) data->contents,
-                                  (char *) scratch.data + 4,
-                                  data->length, &eblock, 0))) {
-           (void) krb5_finish_key(context, &eblock);
-           free(scratch.data);
-           goto error_out;
-       }
-       (void) krb5_finish_key(context, &eblock);
-           
-       free(data->contents);
-       data->length = scratch.length;
-       data->contents = (unsigned char *) scratch.data;
+    if ((retval = krb5_encrypt(context, (krb5_pointer) data->data,
+                              (krb5_pointer) enc_data->ciphertext.data,
+                              data->length, &eblock, ivec))) {
+       krb5_finish_key(context, &eblock);
+        goto cleanup;
     }
+    (void) krb5_finish_key(context, &eblock);
 
-    *ret_data = data;
     return 0;
-    
-error_out:
-    free(data);
+
+cleanup:
+    free(enc_data->ciphertext.data);
     return retval;
 }
 
-/*
- *   krb5_verify_padata  is a glue routine which when passed in
- *   the client, src_addr and padata verifies it with the appropriate 
- *   verify function.
- *  
- *   If problems occur then a non zero value is returned...
- *   else returns zero if padata verifies, and returns a "unique" id.
- *
- *   Note: This is a first crack at what any preauthentication will need...
- */
-
-krb5_error_code
-krb5_verify_padata(context, data,client,src_addr, decrypt_key, req_id, flags)
-    krb5_context context;
-    krb5_pa_data *data;                 /*IN: padata */
-    krb5_principal client;              /*IN: requestor */
-    krb5_address **src_addr;            /*IN: array of ptrs to addresses */
-    krb5_keyblock *decrypt_key;                /*IN: decryption key */
-    int * req_id;                      /*OUT: identifier */
-    int * flags;                       /*OUT: flags  */
+    
+krb5_error_code krb5_obtain_padata(context, preauth_to_use, etype_info,
+                                  key_proc, key_seed, creds, request)
+    krb5_context               context;
+    krb5_pa_data **            preauth_to_use;
+    krb5_etype_info            etype_info;
+    git_key_proc               key_proc;
+    krb5_const_pointer         key_seed;
+    krb5_creds *               creds;
+    krb5_kdc_req *             request;
 {
-    krb5_preauth_ops   *p_system;
-    krb5_encrypt_block         eblock;
-    krb5_data          scratch;
-    int                free_scratch = 0;
-    krb5_checksum      cksum;
-    krb5_error_code    retval;
+    krb5_error_code            retval;
+    krb5_pa_data **            pa;
+    krb5_pa_data **            send_pa_list;
+    krb5_pa_data **            send_pa;
+    krb5_preauth_ops           *ops;
+    krb5_keyblock *            def_enc_key = 0;
+    krb5_enctype               enctype;
+    krb5_data                  salt;
+    int                                size;
+    int                                f_salt = 0;
+
+    if (preauth_to_use == NULL)
+       return 0;
+
+    for (pa = preauth_to_use, size=0; *pa; pa++, size++);
+
+    if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
+       return ENOMEM;
 
-    if (!data)
-       return(EINVAL);
+    send_pa = send_pa_list;
+    *send_pa = 0;
 
-    /* Find appropriate preauthenticator */
-    retval = find_preauthenticator((int) data->pa_type, &p_system);
-    if (retval)
-       return retval;
-
-    /* Check to see if we need to decrypt padata */
-    if (p_system->flags & KRB5_PREAUTH_FLAGS_ENCRYPT) {
-
-       /* If we dont have a decryption key we are out of luck */
-       if (!decrypt_key)
-           return(EINVAL);
-
-        krb5_use_enctype(context, &eblock, decrypt_key->enctype);
-
-        scratch.length = data->length;
-        if (!(scratch.data = (char *)malloc(scratch.length))) {
-           return(ENOMEM);
-        }
-
-       /* do any necessay key pre-processing */
-       retval = krb5_process_key(context, &eblock,decrypt_key);
-       if (retval) {
-           free(scratch.data);
-           return(retval);
-        }
-
-       /* Decrypt data */
-       retval = krb5_decrypt(context, (char *) data->contents + 4,
-                             (krb5_pointer) scratch.data,
-                             scratch.length - 4, &eblock, 0);
-       if (retval) {
-           (void) krb5_finish_key(context, &eblock);
-           free(scratch.data);
-           return(retval);
-       }
-
-       scratch.length  = (((int) ((unsigned char *)data->contents)[0] << 24)
-                          + ((int) ((unsigned char *)data->contents)[1] << 16)
-                          + ((int) ((unsigned char *)data->contents)[2] << 8)
-                          + (int) ((unsigned char *)data->contents)[3]);
-       free_scratch++;
+    if (etype_info) {
+       enctype = etype_info[0]->etype;
+       salt.data = etype_info[0]->salt;
+       salt.length = etype_info[0]->length;
     } else {
-       scratch.data = (char *) data->contents;
-       scratch.length = data->length;
+       enctype = request->ktype[0];
+       if ((retval = krb5_principal2salt(context, request->client, &salt)))
+           return(retval);
+       f_salt = 1;
     }
-
-    retval = (*p_system->verify)(context, client, src_addr, &scratch);
-    if (free_scratch)
-       free(scratch.data);
-    if (retval)
-       return retval;
-    if (flags)
-       *flags = p_system->flags;
-
-    /* Generate a request id by crc32ing the (encrypted) preauth data. */
-    /* Note: The idea behind req_id is that it is dependant upon
-             the information in data. This could then be used for
-             replay detection. */
-    /* MUST malloc cksum.contents */
-    cksum.contents = (krb5_octet *)calloc(1,
-                               krb5_checksum_size(context, CKSUMTYPE_CRC32));
-    if (!cksum.contents) return(1);
-
-    if (krb5_calculate_checksum(context, CKSUMTYPE_CRC32,
-                       data->contents,
-                       data->length,
-                        0, /* seed is ignored */
-                        0, /* seed length is ignored */
-                        &cksum )) {
-        *req_id = 0;
-    } else {
-        /* Checksum length should be 32 bits, so truncation should never
-           take place */
-        if ( cksum.length > sizeof(*req_id)) cksum.length = sizeof(*req_id);
-
-        /* Offset req_id for 64 bit systems */
-        memcpy((char *)req_id + (sizeof(*req_id) - cksum.length),
-                cksum.contents,cksum.length);
-    } 
-    free(cksum.contents);
-    return(0);
-}
-
-static krb5_error_code
-find_preauthenticator(type, preauth)
-    int                        type;
-    krb5_preauth_ops   **preauth;
-{
-    krb5_preauth_ops *ap = preauth_systems;
     
-    while ((ap->type != -1) && (ap->type != type))
-       ap++;
-    if (ap->type == -1)
-       return(KRB5_PREAUTH_BAD_TYPE);
-    *preauth = ap;
-    return 0;
-} 
-
-/*
- * Format is:   8 bytes of random confounder,
- *              1 byte version number (currently 0),
- *              4 bytes: number of seconds since Jan 1, 1970, in MSB order.
- */
-int seeded = 0 ; /* Used by srand below */
+    if ((retval = (*key_proc)(context, enctype, &salt, key_seed,
+                             &def_enc_key)))
+       goto cleanup;
+    
 
-krb5_error_code
-get_unixtime_padata(context, client, src_addr, pa_data)
-    krb5_context context;
-    krb5_principal client;
-    krb5_address **src_addr;
-    krb5_pa_data *pa_data;
-{
-    unsigned char *tmp;
-    krb5_error_code     retval;
-    krb5_timestamp kdc_time;
-    int         i;
+    for (pa = preauth_to_use; *pa; pa++) {
+       if (find_pa_system((*pa)->pa_type, &ops))
+           continue;
 
-    pa_data->length = 13;
-    tmp = pa_data->contents = (unsigned char *) malloc(pa_data->length);
-    if (!tmp) 
-        return(ENOMEM);
+       if (ops->obtain == 0)
+           continue;
+       
+       retval = ((ops)->obtain)(context, *pa, etype_info, def_enc_key,
+                                key_proc, key_seed, creds,
+                                request, send_pa);
+       if (retval)
+           goto cleanup;
 
-    retval = krb5_timeofday(context, &kdc_time);
-    if (retval)
-        return retval;
-    if ( !seeded) {
-       seeded = (int) kdc_time + getpid();
-       srand(seeded);
+       if (*send_pa)
+           send_pa++;
+       *send_pa = 0;
     }
 
-    for (i=0; i < 8; i++)
-        *tmp++ = rand() & 255;
+    retval = 0;
 
-    *tmp++ = (unsigned char) 0;
-    *tmp++ = (unsigned char) ((kdc_time >> 24) & 255);
-    *tmp++ = (unsigned char) ((kdc_time >> 16) & 255);
-    *tmp++ = (unsigned char) ((kdc_time >> 8) & 255);
-    *tmp++ = (unsigned char) (kdc_time & 255);
+    if (send_pa_list[0]) {
+       request->padata = send_pa_list;
+       send_pa_list = 0;
+    }
 
-    return(0);
+cleanup:
+    if (f_salt)
+       krb5_xfree(salt.data);
+    if (send_pa_list)
+       krb5_free_pa_data(context, send_pa_list);
+    if (def_enc_key)
+       krb5_free_keyblock(context, def_enc_key);
+    return retval;
+    
 }
 
 krb5_error_code
-verify_unixtime_padata(context, client, src_addr, data)
-    krb5_context context;
-    krb5_principal client;
-    krb5_address **src_addr;
-    krb5_data *data;
+krb5_process_padata(context, request, as_reply, key_proc, keyseed,
+                   creds, do_more)
+    krb5_context       context;
+    krb5_kdc_req *     request;
+    krb5_kdc_rep *     as_reply;
+    git_key_proc       key_proc;
+    krb5_const_pointer keyseed;
+    krb5_creds *       creds;
+    krb5_int32 *       do_more;
+{
+    *do_more = 0;
+    return 0;
+}
+
+static krb5_error_code
+obtain_enc_ts_padata(context, in_padata, etype_info, def_enc_key,
+                    key_proc, key_seed, creds, request, out_padata)
+    krb5_context               context;
+    krb5_pa_data *             in_padata;
+    krb5_etype_info            etype_info;
+    krb5_keyblock *            def_enc_key;
+    git_key_proc               key_proc;
+    krb5_const_pointer         key_seed;
+    krb5_creds *               creds;
+    krb5_kdc_req *             request;
+    krb5_pa_data **            out_padata;
 {
-    unsigned char       *tmp;
-    krb5_error_code     retval;
-    krb5_timestamp      currenttime, patime;
-    extern krb5_deltat  krb5_clockskew;
-#define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew)
-
-    tmp = (unsigned char *) data->data;
-    if (tmp[8] != 0)
-        return KRB5_PREAUTH_FAILED;
-    patime = (int) tmp[9] << 24;
-    patime += (int) tmp[10] << 16;
-    patime += (int) tmp[11] << 8;
-    patime += tmp[12];
-
-    retval = krb5_timeofday(context, &currenttime);
+    krb5_pa_enc_ts             pa_enc;
+    krb5_error_code            retval;
+    krb5_data *                        scratch;
+    krb5_enc_data              enc_data;
+    krb5_pa_data *             pa;
+    
+
+    enc_data.ciphertext.data = 0;
+
+    retval = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec);
     if (retval)
-        return retval;
+       return retval;
 
-    if (!in_clock_skew(patime))
-        return KRB5_PREAUTH_FAILED;
+    if ((retval = encode_krb5_pa_enc_ts(&pa_enc, &scratch)) != 0)
+       return retval;
 
-    return 0;
-}
+    if ((retval = krb5_encrypt_data(context, def_enc_key, 0, scratch,
+                                   &enc_data)))
+       goto cleanup;
 
-#ifdef KRBCONF_SECUREID
-#include "sdcli.h"
-#include "sdconf.c"
+    krb5_free_data(context, scratch);
+    scratch = 0;
+    
+    if ((retval = encode_krb5_enc_data(&enc_data, &scratch)) != 0)
+       goto cleanup;
 
-krb5_error_code
-verify_securid_padata(client, src_addr, data)
-    krb5_principal client;
-    krb5_address **src_addr;
-    krb5_data *data;
-{
-   extern perform_hw;
-
-   if (perform_hw) {
-        krb5_error_code        retval;
-        char username[255];
-        struct SD_CLIENT sd;
-
-       memset((char *)&sd,0, sizeof (sd));
-       memset((char *) username, 0, sizeof(username));
-        memcpy((char *) username, krb5_princ_component(context, client,0)->data,
-                                 krb5_princ_component(context, client,0)->length);
-        /* If Instance then Append */
-       if (krb5_princ_size(context, client) > 1 ) {
-           if (strncmp(krb5_princ_realm(context, client)->data,
-                       krb5_princ_component(context, client,1)->data,
-                       krb5_princ_component(context, client,1)->length) ||
-                       krb5_princ_realm(context, client)->length != 
-                       krb5_princ_component(context, client,1)->length) {
-               strncat(username,"/",1);
-               strncat(username,krb5_princ_component(context, client,1)->data,
-                                krb5_princ_component(context, client,1)->length);
-           }
-       }
-        if (retval = sd_check(data->data,username,&sd) != ACM_OK) {
-               syslog(LOG_INFO, 
-                   "%s - Invalid Securid Authentication Data sd_check Code %d",
-                       username, retval);
-               return(KRB5_PREAUTH_FAILED);
-       }
-       return(0);
-    } else {
-        char *username = 0;
-
-       krb5_unparse_name(context, client,&username);
-       syslog(LOG_INFO, 
-           "%s Provided Securid but this KDC does not support Securid",
-               username);
-       free(username);
-       return(KRB5_PREAUTH_FAILED);
+    if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) {
+       retval = ENOMEM;
+       goto cleanup;
     }
-}
-#else
-krb5_error_code
-verify_securid_padata(context, client, src_addr, data)
-    krb5_context context;
-    krb5_principal client;
-    krb5_address **src_addr;
-    krb5_data *data;
-{
- char *username = 0;
-       krb5_unparse_name(context, client,&username);
-       syslog(LOG_INFO, 
-           "%s Provided Securid but this KDC does not support Securid",
-               username);
-       free(username);
-       return(KRB5_PREAUTH_FAILED);
-}
 
-#endif
+    pa->magic = KV5M_PA_DATA;
+    pa->pa_type = KRB5_PADATA_ENC_TIMESTAMP;
+    pa->length = scratch->length;
+    pa->contents = scratch->data;
 
+    *out_padata = pa;
 
-/*
-static char *krb5_SecureId_prompt = "\nEnter Your SecurId Access Code Prepended with Your PIN\n (or a \'#\'if Your PIN is entered on the card keypad)\n or Type return <CR> if You Do NOT Use a SecurId Card: ";
- */
-static char *krb5_SecureId_prompt = "\nEnter Your SecurId Access Code Prepended with Your PIN\n (or a \'#\'if Your PIN is entered on the card keypad): ";
+    krb5_xfree(scratch);
+    scratch = 0;
 
-krb5_error_code
-get_securid_padata(context, client,src_addr,pa_data)
-    krb5_context context;
-    krb5_principal client;
-    krb5_address **src_addr;
-    krb5_pa_data *pa_data;
+    retval = 0;
+    
+cleanup:
+    if (scratch)
+       krb5_free_data(context, scratch);
+    if (enc_data.ciphertext.data)
+       krb5_xfree(enc_data.ciphertext.data);
+    return retval;
+}
+
+static krb5_error_code
+find_pa_system(type, preauth)
+    int                        type;
+    krb5_preauth_ops   **preauth;
 {
+    krb5_preauth_ops *ap = preauth_systems;
+    
+    while ((ap->type != -1) && (ap->type != type))
+       ap++;
+    if (ap->type == -1)
+       return(KRB5_PREAUTH_BAD_TYPE);
+    *preauth = ap;
+    return 0;
+} 
 
- char temp[MAX_PREAUTH_SIZE];   
- int tempsize;
- int retval = 0;
-
-    tempsize = sizeof(temp) - 1;
-    if (krb5_read_password(context, krb5_SecureId_prompt, 0, temp, &tempsize))
-        return(KRB5_PARSE_ILLCHAR);
-    temp[tempsize] = '\0';
-
-    if (temp[0] == '\0') 
-       return(KRB5_PARSE_ILLCHAR);
-    pa_data->length = strlen(temp) + 1;
-    pa_data->contents = (krb5_octet *) calloc(1,pa_data->length);
-    if (pa_data->contents) {
-        memcpy(pa_data->contents,temp,pa_data->length);
-       retval = 0;
-    }
-    else retval = ENOMEM;
-    memset(temp,0,pa_data->length);
-    return(retval);
-}