--- /dev/null
+/*
+ * $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);
+}
+
--- /dev/null
+/*
+ * $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__ */
--- /dev/null
+/*
+ * $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
+
--- /dev/null
+/*
+ ***********************************************************************
+ ** 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;
+
--- /dev/null
+/*
+ * $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(¤ttime);
+ 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