*** empty log message ***
authorTheodore Tso <tytso@mit.edu>
Wed, 30 Sep 1992 13:24:49 +0000 (13:24 +0000)
committerTheodore Tso <tytso@mit.edu>
Wed, 30 Sep 1992 13:24:49 +0000 (13:24 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2449 dc483132-0cff-0310-8789-dd5450dbe970

src/admin/edit/util.c [new file with mode: 0644]
src/include/krb5/adm_defs.h [new file with mode: 0644]
src/include/krb5/preauth.h [new file with mode: 0644]
src/include/krb5/rsa-md5.h [new file with mode: 0644]
src/lib/krb5/krb/preauth.c [new file with mode: 0644]

diff --git a/src/admin/edit/util.c b/src/admin/edit/util.c
new file mode 100644 (file)
index 0000000..4822623
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1992 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America is assumed
+ *   to require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ * Utilities for kdb5_edit.
+ * 
+ * Some routines derived from code contributed by the Sandia National
+ * Laboratories.  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.
+ * 
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcsid_util_c[] =
+"$Id$";
+#endif /* !lint & !SABER */
+
+#include <krb5/krb5.h>
+#include <krb5/kdb.h>
+#include <krb5/los-proto.h>
+#include <krb5/ext-proto.h>
+
+#include "./kdb5_edit.h"
+
+#if defined(sysvimp) || ( defined(mips) && defined(SYSTYPE_BSD43)) || (defined(vax) && !defined(ultrix))
+char *
+strstr(s1, s2)
+char *s1;
+char *s2;
+{
+   int s2len;
+   int i;
+   char *temp_ptr;
+
+   temp_ptr = s1;
+   for ( i = 0; i < strlen(s1); i++) {
+        if (memcmp(temp_ptr, s2, strlen(s2)) == 0) return(temp_ptr);
+        temp_ptr += 1;
+   }
+   return ((char *) 0);
+}
+#endif /* sysvimp */
+
+void
+parse_token(token_in, must_be_first_char, num_tokens, tokens_out)
+char *token_in;
+int  *must_be_first_char;
+int  *num_tokens;
+char *tokens_out;
+{
+    int i, j;
+    int token_count = 0;
+
+    i = 0;
+    j = 0;
+
+       /* Eliminate Up Front Asterisks */
+    *must_be_first_char = 1;
+    for (i = 0; token_in[i] == '*'; i++) {
+       *must_be_first_char = 0;
+    }
+
+    if (i == strlen(token_in)) {
+       *num_tokens = 0;
+       return;
+    }
+
+       /* Fill first token_out */
+    token_count++;
+    while ((token_in[i] != '*') && (token_in[i] != '\0')) {
+       tokens_out[j] = token_in[i];
+        j++;
+       i++;
+    }
+
+    if (i == strlen(token_in)) {
+       tokens_out[j] = '\0';
+       *num_tokens = token_count;
+       return;
+    }
+
+       /* Then All Subsequent Tokens */
+    while (i < strlen(token_in)) {
+       if (token_in[i] == '*') {
+          token_count++;
+          tokens_out[j] = '\t';
+       } else {
+          tokens_out[j] = token_in[i];
+       }
+       i++;
+       j++;
+    }
+    tokens_out[j] = '\0';
+
+    if (tokens_out[j - 1] == '\t') {
+       token_count--;
+       tokens_out[j - 1] = '\0';
+    }
+
+    *num_tokens = token_count;
+    return;
+}
+
+int
+check_for_match(search_field, must_be_first_character, chk_entry, 
+               num_tokens, type)
+int must_be_first_character;
+char *search_field;
+krb5_db_entry *chk_entry;
+int num_tokens;
+int type;
+{
+    char token1[256];
+    char *found1;
+    char token2[256];
+    char *found2;
+    char token3[256];
+    char *found3;
+    char *local_entry;
+
+    local_entry = chk_entry->principal->data[type].data;
+
+    token1[0] = token2[0] = token3[0] = '\0';
+
+    (void) sscanf(search_field, "%s\t%s\t%s", token1, token2, token3);
+
+    found1 = strstr(local_entry, token1);
+
+    if (must_be_first_character && (found1 != local_entry)) return(0);
+
+    if (found1 && (num_tokens == 1)) return(1);
+
+    if (found1 && (num_tokens > 1)) {
+       found2 = strstr(local_entry, token2);
+       if (found2 && (found2 > found1) && (num_tokens == 2)) return(1);
+    }
+
+    if ((found2 > found1) && (num_tokens == 3)) {
+       found3 = strstr(local_entry, token3);
+               if (found3 && (found3 > found2) && (found2 > found1)) return(1);
+    }
+    return(0);
+}
+
diff --git a/src/include/krb5/adm_defs.h b/src/include/krb5/adm_defs.h
new file mode 100644 (file)
index 0000000..ae69831
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * $Source$
+ * $Author$
+ * $Id$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * Export of this software from the United States of America is assumed
+ *   to require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ *
+ * <<< Description >>>
+ */
+
+
+#ifndef __ADM_DEFINES__
+#define __ADM_DEFINES__
+
+#define ADM5_VERSTR            "ADM5VER1"
+#define ADM5_VERSIZE           strlen(ADM5_VERSTR)
+/* This used to be kerberos_master */
+#define ADM5_PORTNAME          "kerberos_adm"
+#define DEFAULT_ACL_NAME       "/krb5/.admin_acl_file"
+#define ADM5_CPW_VERSION       "V5CPWS01"
+#define ADM5_ADM_VERSION       "V5ADMS01"
+#define CPWNAME                        "kadmin"
+/* Instance used to be kerberos
+#define CPWINSTANCE            "kerberos"
+   Now, instance is realm */
+#define ADMINSTANCE            "admin"
+
+#define ADM_CPW_VERSION         "V5CPWS01"
+#define ADM_MAX_PW_ITERATIONS  5
+#define ADM_MAX_PW_CHOICES     5
+
+#ifdef MACH_PASS
+#define ADM_MAX_PW_LENGTH       8
+#define ADM_MAX_PHRASE_LENGTH  101
+#else
+#define ADM_MAX_PW_LENGTH       255
+#endif
+
+#define CPW_SNAME               ADM5_PORTNAME
+
+#define MAXCPWBUFSIZE 4096
+
+#ifdef unicos61
+#define SIZEOF_INADDR  SIZEOF_in_addr
+#else
+#define SIZEOF_INADDR sizeof(struct in_addr)
+#endif
+
+/* Server */
+#define KADMIND                0x01
+
+/* Applications */
+#define KPASSWD                0x01
+#define KSRVUTIL       0x02
+#define KADMIN         0x03
+
+/* Operations */
+#define ADDOPER                0x01    /* Add Principal */
+#define CHGOPER                0x02    /* Change Password */
+#define ADROPER         0x03    /* Add principal with random password */
+#define CHROPER         0x04    /* Change to random password */
+#define DELOPER                0x05    /* Delete Principal */
+#define MODOPER                0x06    /* Modify Principal attributes */
+#define INQOPER                0x07    /* Display Principal info */
+#define AD4OPER         0x08    /* Add Principal using v4 string-to-key */
+#define CH4OPER         0x09    /* Change password using v4 string-to-key */
+#define COMPLETE       0x0f
+
+/* Extra Message Types */
+#define SENDDATA1      0x00
+#define SENDDATA2      0x01
+#define SENDDATA3      0x02
+
+/* Unknowns */
+#define KUNKNOWNAPPL   0xff
+#define KUNKNOWNOPER   0xff
+#define KUNKNOWNERR    0xff
+
+typedef struct {
+    char appl_code;
+    char oper_code;
+    char retn_code;
+    char *message;
+} kadmin_requests;
+
+static char *oper_type[] = {
+       "complete",                                     /* 0 */
+       "addition",                                     /* 1 */
+       "deletion",                                     /* 2 */
+       "change",                                       /* 3 */
+       "modification",                                 /* 4 */
+       "inquiry"                                       /* 5 */
+};
+
+#define SKYCHANGED     0x00
+#define NSKYRCVD       0x01
+
+static char *ksrvutil_message[] = {
+       "Service Key Changed",                          /* 0 */
+       "New Key and Version Received"                  /* 1 */
+};
+
+#define KADMGOOD       0x00
+#define KADMSAG                0x01
+
+static char *kadmind_general_response[] = {
+       "Success",                                      /* 0 */
+       "Service Access Granted"                        /* 1 */
+};
+
+
+#define KPASSGOOD      0x00
+#define KPASSBAD       0x01
+
+static char *kadmind_kpasswd_response[] = {
+       "Password Changed",                             /* 0 */
+       "Password NOT Changed!"                         /* 1 */
+};
+
+#define KSRVGOOD       0x00
+#define KSRVBAD                0x01
+#define KSRVCATASTROPHE        0x02
+
+static char *kadmind_ksrvutil_response[] = {
+       "Service Password Change Complete",             /* 0 */
+       "One or More Service Password Change(s) Failed!",       /* 1 */
+       "Database Update Failure - Possible Catastrophe!!"      /* 2 */
+};
+
+#define KADMGOOD       0x00
+#define KADMBAD                0x01
+
+static char *kadmind_kadmin_response[] = {
+       "Administrative Service Completed",             /* 0 */
+       "Principal Unknown!",                           /* 1 */
+       "Principal Already Exists!",                    /* 2 */
+       "Allocation Failure!",                          /* 3 */
+       "Password Failure!",                            /* 4 */
+       "Protocol Failure!",                            /* 5 */
+       "Security Failure!",                            /* 6 */
+       "Admin Client Not in ACL List!",                        /* 7 */
+       "Database Update Failure - Possible Catastrophe!!"      /* 8 */
+};
+
+#define KMODVNO                0x00
+#define KMODATTR       0x01
+
+#ifdef SANDIA
+#define KMODFCNT       0x02
+#endif
+
+#define ATTRPOST       0x00
+#define ATTRNOPOST     0x01
+#define ATTRFOR                0x02
+#define ATTRNOFOR      0x03
+#define ATTRTGT                0x04
+#define ATTRNOTGT      0x05
+#define ATTRREN                0x06
+#define ATTRNOREN      0x07
+#define ATTRPROXY      0x08
+#define ATTRNOPROXY    0x09
+#define ATTRDSKEY      0x0a
+#define ATTRNODSKEY    0x0b
+#define ATTRLOCK       0x0c
+#define ATTRUNLOCK     0x0d
+
+#ifdef SANDIA
+#define ATTRPRE                0x0e
+#define ATTRNOPRE      0x0f
+#define ATTRPWOK       0x10
+#define ATTRPWCHG      0x11
+#define ATTRSID                0x12
+#define ATTRNOSID      0x13
+#endif
+
+#define ATTRNOSVR       0x14
+#define ATTRSVR         0x15
+
+#define BADATTR                0x3f
+
+#endif /* __ADM_DEFINES__ */
diff --git a/src/include/krb5/preauth.h b/src/include/krb5/preauth.h
new file mode 100644 (file)
index 0000000..e36ece6
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * $Author$
+ * (Originally written by Glen Machin at Sandia Labs.)
+ *
+ * Copyright 1992 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America is assumed
+ *   to require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * 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.
+ * 
+ */
+
+#define MAX_PREAUTH_SIZE 20    /* Maximum size of PreAuthenticator.data */
+
+/*
+ * Note: these typedefs are subject to change.... [tytso:19920903.1609EDT]
+ */
+typedef krb5_error_code (krb5_preauth_obtain_proc)
+    PROTOTYPE((krb5_principal client, krb5_address **src_addr,
+              krb5_pa_data *pa_data));
+
+typedef krb5_error_code (krb5_preauth_verify_proc)
+    PROTOTYPE((krb5_principal client, krb5_address **src_addr,
+              krb5_data *data));
+
+typedef struct _krb5_preauth_ops {
+        int     type;
+       int     flags;
+       krb5_preauth_obtain_proc        *obtain;
+       krb5_preauth_verify_proc        *verify;
+} krb5_preauth_ops;
+
+/*
+ * Preauthentication property flags
+ */
+#define KRB5_PREAUTH_FLAGS_ENCRYPT     0x00000001
+#define KRB5_PREAUTH_FLAGS_HARDWARE    0x00000002
+
+krb5_error_code find_preauthenticator
+    PROTOTYPE((int type, krb5_preauth_ops **Preauth_proc));
+
+#if 0
+krb5_error_code get_random_padata
+    PROTOTYPE((krb5_principal client, krb5_address **src_addr,
+              krb5_pa_data *data));
+
+krb5_error_code verify_random_padata
+    PROTOTYPE((krb5_principal client, krb5_address **src_addr,
+              krb5_data *data));
+#endif
+
+krb5_error_code get_timestamp_padata
+    PROTOTYPE((krb5_principal client, krb5_address **src_addr,
+              krb5_pa_data *data));
+
+krb5_error_code verify_timestamp_padata
+    PROTOTYPE((krb5_principal client, krb5_address **src_addr,
+              krb5_data *data));
+
+#ifdef KRBCONF_SECUREID
+krb5_preauth_obtain_proc get_securid_padata;
+krb5_preauth_verify_proc verify_securid_padata;
+#endif
+
diff --git a/src/include/krb5/rsa-md5.h b/src/include/krb5/rsa-md5.h
new file mode 100644 (file)
index 0000000..7278183
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5                    **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version               **
+ ** Revised (for MD5): RLR 4/27/91                                    **
+ **   -- G modified to have y&~z instead of y&z                       **
+ **   -- FF, GG, HH modified to add in last register done             **
+ **   -- Access pattern: round 2 works mod 5, round 3 works mod 3     **
+ **   -- distinct additive constant for each step                     **
+ **   -- round 4 added, working mod 7                                 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** RSA Data Security, Inc. makes no representations concerning       **
+ ** either the merchantability of this software or the suitability    **
+ ** of this software for any particular purpose.  It is provided "as  **
+ ** is" without express or implied warranty of any kind.              **
+ **                                                                   **
+ ** These notices must be retained in any copies of any part of this  **
+ ** documentation and/or software.                                    **
+ ***********************************************************************
+ */
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+  krb5_ui_4 i[2];                      /* number of _bits_ handled mod 2^64 */
+  krb5_ui_4 buf[4];                    /* scratch buffer */
+  unsigned char in[64];                        /* input buffer */
+  unsigned char digest[16];            /* actual digest after MD5Final call */
+} MD5_CTX;
+
+#if defined(__STDC__) || defined(KRB5_PROVIDE_PROTOTYPES)
+extern void MD5Init(MD5_CTX *);
+extern void MD5Update (MD5_CTX *, unsigned char *, unsigned int);
+extern void MD5Final (MD5_CTX *);
+#else
+extern void MD5Init();
+extern void MD5Update ();
+extern void MD5Final ();
+#endif
+
+#define        RSA_MD5_CKSUM_LENGTH            16
+#define        RSA_MD5_DES_CKSUM_LENGTH        16
+
+extern krb5_checksum_entry
+    rsa_md5_cksumtable_entry,
+    rsa_md5_des_cksumtable_entry;
+
diff --git a/src/lib/krb5/krb/preauth.c b/src/lib/krb5/krb/preauth.c
new file mode 100644 (file)
index 0000000..fba6a9d
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * $Author$
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America is assumed
+ *   to require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * 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 <stdio.h>
+#include <time.h>
+#include <krb5/krb5.h>
+#include <krb5/ext-proto.h>
+#include <krb5/preauth.h>
+#include <krb5/mit-des.h>
+
+#include <syslog.h>
+
+static krb5_preauth_ops preauth_systems[] = {
+#if 0
+    {
+       KRB5_PADATA_ENC_RANDOM,
+       KRB5_PREAUTH_FLAGS_ENCRYPT,
+       get_random_padata,
+       verify_random_padata,
+    },
+#endif
+    {
+       KRB5_PADATA_ENC_TIMESTAMP,
+       KRB5_PREAUTH_FLAGS_ENCRYPT,
+       get_timestamp_padata,
+       verify_timestamp_padata,
+    },
+#ifdef KRBCONF_SECUREID
+    {
+       KRB5_PADATA_ENC_SECURID,
+       KRB5_PREAUTH_FLAGS_ENCRYPT | KRB5_PREAUTH_FLAGS_HARDWARE,
+       get_securid_padata,
+       verify_securid_padata,
+    },
+#endif
+    { -1,}
+};
+                               
+/*
+ *   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...
+ */
+krb5_error_code 
+krb5_obtain_padata(type, client, src_addr, encrypt_key, ret_data)
+    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_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);
+
+    data = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
+    if (!data)
+       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;
+
+    retval = (*p_system->obtain)( 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_keytype(&eblock, encrypt_key->keytype);
+
+       /* do any necessay key pre-processing */
+       retval = krb5_process_key(&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(&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((krb5_pointer) data->contents,
+                                 (char *) scratch.data + 4,
+                                 data->length, &eblock, 0)) {
+           (void) krb5_finish_key(&eblock);
+           free(scratch.data);
+           goto error_out;
+       }
+       (void) krb5_finish_key(&eblock);
+           
+       free(data->contents);
+       data->length = scratch.length;
+       data->contents = (unsigned char *) scratch.data;
+    }
+
+    *ret_data = data;
+    return 0;
+    
+error_out:
+    free(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(data,client,src_addr, decrypt_key, req_id, flags)
+    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_preauth_ops   *p_system;
+    krb5_encrypt_block         eblock;
+    krb5_data          scratch;
+    int                free_scratch = 0;
+    krb5_checksum      cksum;
+    krb5_error_code    retval;
+
+    if (!data)
+       return(EINVAL);
+
+    /* 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_keytype(&eblock, decrypt_key->keytype);
+
+        scratch.length = data->length;
+        if (!(scratch.data = (char *)malloc(scratch.length))) {
+           return(ENOMEM);
+        }
+
+       /* do any necessay key pre-processing */
+       retval = krb5_process_key(&eblock,decrypt_key);
+       if (retval) {
+           free(scratch.data);
+           return(retval);
+        }
+
+       /* Decrypt data */
+       retval = krb5_decrypt((char *) data->contents + 4,
+                             (krb5_pointer) scratch.data,
+                             scratch.length - 4, &eblock, 0);
+       if (retval) {
+           (void) krb5_finish_key(&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++;
+    } else {
+       scratch.data = (char *) data->contents;
+       scratch.length = data->length;
+    }
+
+    retval = (*p_system->verify)(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(CKSUMTYPE_CRC32));
+    if (!cksum.contents) return(1);
+
+    if (krb5_calculate_checksum(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.
+ */
+krb5_error_code
+get_timestamp_padata(client, src_addr, pa_data)
+    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;
+
+    pa_data->length = 13;
+    tmp = pa_data->contents = (unsigned char *) malloc(pa_data->length);
+    if (!tmp) 
+       return(ENOMEM);
+
+    retval = krb5_timeofday(&kdc_time);
+    if (retval)
+       return retval;
+    srand(kdc_time);           /* XXX NOT GOOD ENOUGH!!!! */
+
+    for (i=0; i < 8; i++)
+       *tmp++ = rand() & 255;
+
+    *tmp++ = 0;
+    *tmp++ = (kdc_time >> 24) & 255;
+    *tmp++ = (kdc_time >> 16) & 255;
+    *tmp++ = (kdc_time >> 8) & 255;
+    *tmp++ = kdc_time & 255;
+
+    return(0);
+}
+
+krb5_error_code
+verify_timestamp_padata(client, src_addr, data)
+    krb5_principal client;
+    krb5_address **src_addr;
+    krb5_data *data;
+{
+    unsigned char      *tmp;
+    krb5_error_code    retval;
+    krb5_timestamp     currenttime, patime;
+    extern krb5_deltat krb5_clockskew;
+#define in_clock_skew(date) (abs((date)-currenttime) < krb5_clockskew)
+
+    tmp = (unsigned char *) data->data;
+    if (tmp[8] != 0)
+       return KRB5_PREAUTH_FAILED;
+    patime = tmp[9] << 24;
+    patime += tmp[10] << 16;
+    patime += tmp[11] << 8;
+    patime += tmp[12];
+
+    retval = krb5_timeofday(&currenttime);
+    if (retval)
+       return retval;
+
+    if (!in_clock_skew(patime))
+       return KRB5_PREAUTH_FAILED;
+
+    return 0;
+}
+
+#if 0
+krb5_error_code
+get_random_padata(client, src_addr, pa_data)
+    krb5_principal client;
+    krb5_address **src_addr;
+    krb5_pa_data *pa_data;
+{
+    char temp[MAX_PREAUTH_SIZE];
+
+    srand(time(0));
+    sprintf(temp, "%1u", rand() & 0x7fffffff);
+    pa_data->length = strlen(temp) + 1;
+    pa_data->contents = (unsigned char *) malloc(pa_data->length);
+    if (!pa_data->contents) 
+       return(ENOMEM);
+    memcpy(pa_data->contents, temp, pa_data->length);
+    return(0);
+}
+
+krb5_error_code
+verify_random_padata(client, src_addr, data)
+    krb5_principal client;
+    krb5_address **src_addr;
+    krb5_data *data;
+{
+    if (atof(data->data) > 2147483637.0)
+       return KRB5_PREAUTH_FAILED;
+    
+    return 0;
+}
+#endif
+
+#ifdef SECUREID
+#include "sdcli.h"
+#include "sdconf.c"
+
+int verify_securid_padata(preauth_data)
+PreAuthenticator *preauth_data;
+{
+   char username[255];
+   struct SD_CLIENT sd;
+
+       memset((char *)&sd,0, sizeof (sd));
+       memset((char *) username, 0, sizeof(username));
+        memcpy((char *) username, (char *) preauth_data->client[1]->data,
+                                          preauth_data->client[1]->length);
+        /* If Instance then Append */
+        if (preauth_data->client[2] != '\0') {
+            memcpy((char *) username + preauth_data->client[1]->length, 
+                                               (char *) "/", 1);
+            memcpy((char *) username + preauth_data->client[1]->length + 1,
+                          (char *)  preauth_data->client[2]->data,
+                           preauth_data->client[2]->length);
+        }
+        if (sd_check( preauth_data->data,username,&sd) != ACM_OK) return(1);
+       return(0);
+}
+
+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: ";
+
+int get_securid_padata(preauth_data)
+PreAuthenticator *preauth_data;
+{
+
+ char temp[MAX_PREAUTH_SIZE];   
+ int tempsize;
+ int retval = 0;
+
+    tempsize = sizeof(temp) - 1;
+    if (krb5_read_password(krb5_SecureId_prompt, 0, temp, &tempsize))
+       return(1);
+    temp[tempsize] = '\0';
+
+    if (temp[0] == '\0') return(1);
+    preauth_data->datalen = strlen(temp) + 1;
+    preauth_data->data = (char *) calloc(1,preauth_data->datalen);
+    if (preauth_data->data) {
+        memcpy(preauth_data->data,temp,preauth_data->datalen);
+       retval = 0;
+    }
+    else retval = 1;
+    memset(temp,0,preauth_data->datalen);
+    return(retval);
+}
+#endif