Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1160 lines
31 KiB

#define UNICODE
#define INC_OLE2
#include <windows.h>
#include <activeds.h>
#include <ntsecapi.h>
#include <stdio.h> // printf
#include <stdlib.h> // strtoul
#include <assert.h>
#define SECURITY_WIN32
#include <security.h> // General definition of a Security Support Provider
#include <shlwapi.h>
typedef int krb5_int32;
typedef short krb5_int16;
typedef unsigned int krb5_kvno;
typedef unsigned char krb5_octet;
typedef unsigned int krb5_enctype;
typedef krb5_int32 krb5_deltat;
typedef krb5_int32 krb5_flags;
typedef krb5_int32 krb5_timestamp;
typedef krb5_int32 krb5_error_code;
typedef char FAR * krb5_principal;
typedef void FAR * krb5_pointer;
/*
* Note --- these structures cannot be modified without changing the
* database version number in libkdb.a, but should be expandable by
* adding new tl_data types.
*/
typedef struct _krb5_tl_data {
struct _krb5_tl_data* tl_data_next; /* NOT saved */
krb5_int16 tl_data_type;
krb5_int16 tl_data_length;
krb5_octet * tl_data_contents;
} krb5_tl_data;
/*
* If this ever changes up the version number and make the arrays be as
* big as necessary.
*
* Currently the first type is the enctype and the second is the salt type.
*/
typedef struct _krb5_key_data {
krb5_int16 key_data_ver; /* Version */
krb5_int16 key_data_kvno; /* Key Version */
krb5_int16 key_data_type[2]; /* Array of types */
krb5_int16 key_data_length[2]; /* Array of lengths */
krb5_octet * key_data_contents[2]; /* Array of pointers */
} krb5_key_data;
#define KRB5_KDB_V1_KEY_DATA_ARRAY 2 /* # of array elements */
typedef struct _krb5_db_entry_new {
krb5_int16 len;
krb5_flags attributes;
krb5_deltat max_life;
krb5_deltat max_renewable_life;
krb5_timestamp expiration; /* When the client expires */
krb5_timestamp pw_expiration; /* When its passwd expires */
krb5_timestamp last_success; /* Last successful passwd */
krb5_timestamp last_failed; /* Last failed passwd attempt */
krb5_kvno fail_auth_count; /* # of failed passwd attempt */
krb5_int16 n_tl_data;
krb5_int16 n_key_data;
krb5_int16 e_length; /* Length of extra data */
krb5_octet * e_data; /* Extra data to be saved */
krb5_principal princ; /* Length, data */
krb5_tl_data * tl_data; /* Linked list */
krb5_key_data * key_data; /* Array */
} krb5_db_entry;
typedef struct _krb5_keyblock {
krb5_enctype enctype;
int length;
krb5_octet FAR *contents;
} krb5_keyblock;
krb5_keyblock mkey;
/* Strings */
static const char k5_dump_header[] = "kdb5_util load_dump version 4\n";
/* Message strings */
static const char regex_err[] = "%s: regular expression error - %s\n";
static const char regex_merr[] = "%s: regular expression match error - %s\n";
static const char pname_unp_err[] = "%s: cannot unparse principal name (%s)\n";
static const char mname_unp_err[] = "%s: cannot unparse modifier name (%s)\n";
static const char nokeys_err[] = "%s: cannot find any standard key for %s\n";
static const char sdump_tl_inc_err[] = "%s: tagged data list inconsistency for %s (counted %d, stored %d)\n";
static const char stand_fmt_name[] = "Kerberos version 5";
static const char old_fmt_name[] = "Kerberos version 5 old format";
static const char b6_fmt_name[] = "Kerberos version 5 beta 6 format";
static const char ofopen_error[] = "%s: cannot open %s for writing (%s)\n";
static const char oflock_error[] = "%s: cannot lock %s (%s)\n";
static const char dumprec_err[] = "%s: error performing %s dump (%s)\n";
static const char dumphdr_err[] = "%s: error dumping %s header (%s)\n";
static const char trash_end_fmt[] = "%s(%d): ignoring trash at end of line: ";
static const char read_name_string[] = "name string";
static const char read_key_type[] = "key type";
static const char read_key_data[] = "key data";
static const char read_pr_data1[] = "first set of principal attributes";
static const char read_mod_name[] = "modifier name";
static const char read_pr_data2[] = "second set of principal attributes";
static const char read_salt_data[] = "salt data";
static const char read_akey_type[] = "alternate key type";
static const char read_akey_data[] = "alternate key data";
static const char read_asalt_type[] = "alternate salt type";
static const char read_asalt_data[] = "alternate salt data";
static const char read_exp_data[] = "expansion data";
static const char store_err_fmt[] = "%s(%d): cannot store %s(%s)\n";
static const char add_princ_fmt[] = "%s\n";
static const char parse_err_fmt[] = "%s(%d): cannot parse %s (%s)\n";
static const char read_err_fmt[] = "%s(%d): cannot read %s\n";
static const char no_mem_fmt[] = "%s(%d): no memory for buffers\n";
static const char rhead_err_fmt[] = "%s(%d): cannot match size tokens\n";
static const char err_line_fmt[] = "%s: error processing line %d of %s\n";
static const char head_bad_fmt[] = "%s: dump header bad in %s\n";
static const char read_bytecnt[] = "record byte count";
static const char read_encdata[] = "encoded data";
static const char n_name_unp_fmt[] = "%s(%s): cannot unparse name\n";
static const char n_dec_cont_fmt[] = "%s(%s): cannot decode contents\n";
static const char read_nint_data[] = "principal static attributes";
static const char read_tcontents[] = "tagged data contents";
static const char read_ttypelen[] = "tagged data type and length";
static const char read_kcontents[] = "key data contents";
static const char read_ktypelen[] = "key data type and length";
static const char read_econtents[] = "extra data contents";
static const char k5beta_fmt_name[] = "Kerberos version 5 old format";
static const char standard_fmt_name[] = "Kerberos version 5 format";
static const char no_name_mem_fmt[] = "%s: cannot get memory for temporary name\n";
static const char ctx_err_fmt[] = "%s: cannot initialize Kerberos context\n";
static const char stdin_name[] = "standard input";
static const char restfail_fmt[] = "%s: %s restore failed\n";
static const char close_err_fmt[] = "%s: cannot close database (%s)\n";
static const char dbinit_err_fmt[] = "%s: cannot initialize database (%s)\n";
static const char dblock_err_fmt[] = "%s: cannot initialize database lock (%s)\n";
static const char dbname_err_fmt[] = "%s: cannot set database name to %s (%s)\n";
static const char dbdelerr_fmt[] = "%s: cannot delete bad database %s (%s)\n";
static const char dbunlockerr_fmt[] = "%s: cannot unlock database %s (%s)\n";
static const char dbrenerr_fmt[] = "%s: cannot rename database %s to %s (%s)\n";
static const char dbcreaterr_fmt[] = "%s: cannot create database %s (%s)\n";
static const char dfile_err_fmt[] = "%s: cannot open %s (%s)\n";
static const char oldoption[] = "-old";
static const char b6option[] = "-b6";
static const char verboseoption[] = "-verbose";
static const char updateoption[] = "-update";
static const char ovoption[] = "-ov";
static const char dump_tmptrail[] = "~";
#define ENCTYPE_NULL 0x0000
#define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */
#define ENCTYPE_DES_CBC_MD4 0x0002 /* DES cbc mode with RSA-MD4 */
#define ENCTYPE_DES_CBC_MD5 0x0003 /* DES cbc mode with RSA-MD5 */
#define ENCTYPE_DES_CBC_RAW 0x0004 /* DES cbc mode raw */
#define ENCTYPE_DES3_CBC_SHA 0x0005 /* DES-3 cbc mode with NIST-SHA */
#define ENCTYPE_DES3_CBC_RAW 0x0006 /* DES-3 cbc mode raw */
#define ENCTYPE_RC4_MD4 -128
#define ENCTYPE_RC4_PLAIN2 -129
#define ENCTYPE_RC4_LM -130
#define ENCTYPE_RC4_SHA -131
#define ENCTYPE_DES_PLAIN -132
#define ENCTYPE_RC4_HMAC_OLD -133
#define ENCTYPE_RC4_PLAIN_OLD -134
#define ENCTYPE_RC4_HMAC_OLD_EXP -135
#define ENCTYPE_RC4_PLAIN_OLD_EXP -136
#define ENCTYPE_DES_CBC_MD5_EXP -137
#define ENCTYPE_DES_PLAIN_EXP -138
#define ENCTYPE_RC4_PLAIN -140
#define ENCTYPE_RC4_PLAIN_EXP -141
#define ENCTYPE_UNKNOWN 0x01ff
/* Salt types */
#define KRB5_KDB_SALTTYPE_NORMAL 0
#define KRB5_KDB_SALTTYPE_V4 1
#define KRB5_KDB_SALTTYPE_NOREALM 2
#define KRB5_KDB_SALTTYPE_ONLYREALM 3
#define KRB5_KDB_SALTTYPE_SPECIAL 4
#define KRB5_KDB_SALTTYPE_AFS3 5
/* Attributes */
#define KRB5_KDB_DISALLOW_POSTDATED 0x00000001
#define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002
#define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004
#define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008
#define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010
#define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020
#define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040
#define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080
#define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100
#define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200
#define KRB5_KDB_DISALLOW_SVR 0x00001000
#define KRB5_KDB_PWCHANGE_SERVICE 0x00002000
#define KRB5_KDB_SUPPORT_DESMD5 0x00004000
#define KRB5_KDB_NEW_PRINC 0x00008000
//
// SALT flags for encryption, from rfc1510 update 3des enctype
//
#define KERB_ENC_TIMESTAMP_SALT 1
#define KERB_TICKET_SALT 2
#define KERB_AS_REP_SALT 3
#define KERB_TGS_REQ_SESSKEY_SALT 4
#define KERB_TGS_REQ_SUBKEY_SALT 5
#define KERB_TGS_REQ_AP_REQ_AUTH_CKSUM_SALT 6
#define KERB_TGS_REQ_AP_REQ_AUTH_SALT 7
#define KERB_TGS_REP_SALT 8
#define KERB_TGS_REP_SUBKEY_SALT 9
#define KERB_AP_REQ_AUTH_CKSUM_SALT 10
#define KERB_AP_REQ_AUTH_SALT 11
#define KERB_AP_REP_SALT 12
#define KERB_PRIV_SALT 13
#define KERB_CRED_SALT 14
#define KERB_SAFE_SALT 15
#define KERB_NON_KERB_SALT 16
#define KERB_NON_KERB_CKSUM_SALT 17
#define KERB_KERB_ERROR_SALT 18
#define KERB_KDC_ISSUED_CKSUM_SALT 19
#define KERB_MANDATORY_TKT_EXT_CKSUM_SALT 20
#define KERB_AUTH_DATA_TKT_EXT_CKSUM_SALT 21
LPSTR
get_error_text(DWORD dwError)
{
PCHAR pBuf = NULL;
DWORD cMsgLen = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER | 40,
NULL,
dwError,
MAKELANGID(0, SUBLANG_ENGLISH_US),
(LPSTR) &pBuf,
128,
NULL);
if (!cMsgLen) {
pBuf = (LPSTR)malloc(30);
sprintf(pBuf, "(%d)", dwError);
}
return(pBuf);
}
void
print_salt_string(
int stype,
int len,
char *str
)
{
int i;
switch (stype) {
case KRB5_KDB_SALTTYPE_NORMAL:
printf("Normal\n");
break;
case KRB5_KDB_SALTTYPE_V4:
printf("V4\n");
break;
case KRB5_KDB_SALTTYPE_NOREALM:
printf("No Realm : \"%*s\"\n", len, str);
break;
case KRB5_KDB_SALTTYPE_ONLYREALM:
printf("Only Realm : \"%*s\"\n", len, str);
break;
case KRB5_KDB_SALTTYPE_AFS3:
printf("AFS3 : \"%*s\"\n", len, str);
break;
case KRB5_KDB_SALTTYPE_SPECIAL:
printf("Special [%d]:", len);
goto dump;
default:
printf("salttype %d [%d]:", stype, len);
dump:;
for (i=0; i < len; i++)
printf(" %02x", str[i]);
printf("\n");
break;
}
}
char *
etype_string(
int enctype
)
{
static char buf[32];
switch (enctype) {
case ENCTYPE_DES_CBC_CRC:
return "DES-CBC-CRC";
break;
case ENCTYPE_DES_CBC_MD4:
return "DES-CBC-MD4";
break;
case ENCTYPE_DES_CBC_MD5:
return "DES-CBC-MD5";
break;
case ENCTYPE_DES3_CBC_SHA:
return "DES3-CBC-SHA";
break;
case ENCTYPE_RC4_MD4:
return "RC4-MD4";
break;
case ENCTYPE_RC4_PLAIN2:
return "RC4-PLAIN2";
break;
case ENCTYPE_RC4_LM:
return "RC4-LM";
break;
case ENCTYPE_RC4_SHA:
return "RC4-SHA";
break;
case ENCTYPE_DES_PLAIN:
return "DES-PLAIN";
break;
case ENCTYPE_RC4_HMAC_OLD:
return "RC4-HMAC-OLD";
break;
case ENCTYPE_RC4_PLAIN_OLD:
return "RC4-PLAIN-OLD";
break;
case ENCTYPE_RC4_HMAC_OLD_EXP:
return "RC4-HMAC-OLD-EXP";
break;
case ENCTYPE_RC4_PLAIN_OLD_EXP:
return "RC4-PLAIN-OLD-EXP";
break;
case ENCTYPE_DES_CBC_MD5_EXP:
return "DES-CBC-MD5-40bit";
break;
case ENCTYPE_DES_PLAIN_EXP:
return "DES-PLAIN-40bit";
break;
case ENCTYPE_RC4_PLAIN:
return "RC4-PLAIN";
break;
case ENCTYPE_RC4_PLAIN_EXP:
return "RC4-PLAIN-EXP";
break;
default:
sprintf(buf, "etype %d", enctype);
return buf;
break;
}
}
void
print_tl_data(
int n_data,
krb5_tl_data *tl_data
)
{
krb5_tl_data *tlp;
int i;
if (n_data) {
printf("\ttl_data:\n");
for (tlp = tl_data; tlp; tlp = tlp->tl_data_next) {
printf("\t\ttype=%d len=%d ",
tlp->tl_data_type, tlp->tl_data_length);
for (i = 0; i < tlp->tl_data_length; i++)
printf(" %02x", tlp->tl_data_contents[i]);
printf("\n");
}
}
}
int
decrypt_key(
krb5_keyblock *key,
void *indata,
int inlen,
void *outdata,
int *outlen
)
{
#define SEC_SUCCESS(Status) ((Status) >= 0)
static const UCHAR iVec[8] = {0};
static HANDLE lsaHandle = NULL;
static ULONG packageId = 0;
NTSTATUS Status, SubStatus;
LSA_STRING Name;
PKERB_DECRYPT_REQUEST DecryptRequest;
ULONG OutLen, DecryptReqLength;
PUCHAR OutBuf;
int retval = 0;
if (!lsaHandle) {
Status = LsaConnectUntrusted(&lsaHandle);
if (!SEC_SUCCESS(Status)) {
fprintf(stderr, "Failed to create LsaHandle - 0x%x\n", Status);
exit(3);
}
Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
Name.Length = (USHORT)strlen(Name.Buffer);
Name.MaximumLength = Name.Length + 1;
Status = LsaLookupAuthenticationPackage(lsaHandle,
&Name,
&packageId);
if (!SEC_SUCCESS(Status)) {
LsaDeregisterLogonProcess(lsaHandle);
fprintf(stderr, "Failed to register LsaHandle - 0x%x\n", Status);
exit(3);
}
}
DecryptReqLength =
sizeof(KERB_DECRYPT_REQUEST) + key->length + 8 + inlen;
DecryptRequest = (PKERB_DECRYPT_REQUEST)LocalAlloc(LMEM_ZEROINIT, DecryptReqLength);
DecryptRequest->MessageType = KerbDecryptDataMessage;
DecryptRequest->LogonId.LowPart = 0;
DecryptRequest->LogonId.HighPart = 0;
DecryptRequest->Flags = 0;
DecryptRequest->KeyUsage = KERB_TICKET_SALT;
DecryptRequest->CryptoType = key->enctype;
DecryptRequest->Key.KeyType = key->enctype;
DecryptRequest->Key.Length = key->length;
DecryptRequest->Key.Value = (PUCHAR) (DecryptRequest + 1);
memcpy(DecryptRequest->Key.Value, key->contents, key->length);
DecryptRequest->InitialVectorSize = 8;
DecryptRequest->InitialVector = (PUCHAR)
((PUCHAR)DecryptRequest->Key.Value + DecryptRequest->Key.Length);
memcpy(DecryptRequest->InitialVector, iVec, 8);
DecryptRequest->EncryptedDataSize = inlen;
DecryptRequest->EncryptedData = (PUCHAR)
((PUCHAR)DecryptRequest->InitialVector + DecryptRequest->InitialVectorSize);
memcpy(DecryptRequest->EncryptedData, indata, inlen);
Status = LsaCallAuthenticationPackage(lsaHandle,
packageId,
DecryptRequest,
DecryptReqLength,
(PVOID *)&OutBuf,
&OutLen,
&SubStatus);
if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) {
fprintf(stderr, "Decrypt: LsaCallAuthPackage failed: %s\n",
get_error_text(SubStatus));
exit(4);
}
if ((long)OutLen > *outlen) {
fprintf(stderr, "Decrypt: outbuf too small (%d < %d)\n",
OutLen, *outlen);
*outlen = OutLen;
retval = -1;
}
else if (outdata) {
*outlen = OutLen;
memcpy(outdata, OutBuf, OutLen);
}
LsaFreeReturnBuffer(OutBuf);
return(retval);
}
void
print_key_data(
int n_key_data,
krb5_key_data *kd
)
{
int n, i;
krb5_keyblock key;
krb5_octet *ptr;
int tmplen;
for (n = 0; n < n_key_data; n++) {
ptr = kd[n].key_data_contents[0];
key.enctype = kd[n].key_data_type[0];
key.length = *(short *)ptr;
ptr += 2;
printf("\tkey[%d]: ver=%d kvno=%d\n",
n, kd[n].key_data_ver,
kd[n].key_data_kvno);
printf("\t\tetype=%s [%d]: ",
etype_string(key.enctype),
key.enctype);
printf(" keylength=%d ", key.length);
printf("\n\t\tEncrypted key: ");
for (i = 0; i < kd[n].key_data_length[0]; i++)
printf(" %02x", kd[n].key_data_contents[0][i]);
if (mkey.length) {
// First get the length needed
decrypt_key(&mkey, ptr, (kd[n].key_data_length[0] - 2),
NULL, &tmplen);
key.contents = (krb5_octet *)malloc(tmplen);
assert(key.contents != 0);
// Now decrypt it
decrypt_key(&mkey, ptr, (kd[n].key_data_length[0] - 2),
key.contents, &tmplen);
printf("\n\t\tDecrypted key: ");
for (i = 0; i < key.length; i++)
printf(" %02x", key.contents[i]);
}
printf("\n\t\tsalt=");
print_salt_string(kd[n].key_data_type[1], kd[n].key_data_length[1],
(char *)kd[n].key_data_contents[1]);
}
}
int
ds_put_principal(
IADs *ds,
krb5_db_entry &dbentry
)
{
// Check for accounts that we can't import
if ((strncmp(dbentry.princ, "K/M", 3) == 0) ||
(strncmp(dbentry.princ, "krbtgt/", 7) == 0) ||
(strncmp(dbentry.princ, "kadmin/", 7) == 0)) {
return -1;
}
char *cp;
char *SAMName = StrDupA(dbentry.princ);
// Zap the realm
if (cp = strrchr(SAMName, '@'))
*cp = '\0';
// Check if this princ has an instance - likely SPN
if (cp = strchr(SAMName, '/')) {
// We don't do anything with SPN's right now
return (-1);
}
printf(add_princ_fmt, SAMName);
// Search for the entry in the domain
// If this is to be an SPN; create the base account
// (or use an existing one)
// Now create the user
return 0;
}
/*
* Read a string of bytes while counting the number of lines passed.
*/
static int
read_string(
FILE *f,
char *buf,
int len,
int *lp
)
{
int c;
int i, retval;
retval = 0;
for (i=0; i<len; i++) {
c = fgetc(f);
if (c < 0) {
retval = 1;
break;
}
if (c == '\n')
(*lp)++;
buf[i] = (char) c;
}
buf[len] = '\0';
return(retval);
}
/*
* Read a string of two character representations of bytes.
*/
static int
read_octet_string(
FILE *f,
krb5_octet *buf,
int len
)
{
int c;
int i, retval;
retval = 0;
for (i=0; i<len; i++) {
if (fscanf(f, "%02x", &c) != 1) {
retval = 1;
break;
}
buf[i] = (krb5_octet) c;
}
return(retval);
}
/*
* Find the end of an old format record.
*/
static void
find_record_end(
FILE *f,
const char *fn,
int lineno
)
{
int ch;
if (((ch = fgetc(f)) != ';') || ((ch = fgetc(f)) != '\n')) {
fprintf(stderr, trash_end_fmt, fn, lineno);
while (ch != '\n') {
putc(ch, stderr);
ch = fgetc(f);
}
putc(ch, stderr);
}
}
/*
* process_k5beta6_record() - Handle a dump record in krb5b6 format.
*
* Returns -1 for end of file, 0 for success and 1 for failure.
*/
static int
process_k5beta6_record(
const char *fname,
IADs *ds,
FILE *filep,
int verbose,
int *linenop
)
{
int retval;
krb5_db_entry dbentry;
krb5_int32 t1, t2, t3, t4, t5, t6, t7, t8, t9;
int nread;
int error;
int i, j;
char *name;
krb5_key_data *kp, *kdatap;
krb5_tl_data **tlp, *tl;
krb5_octet *op;
krb5_error_code kret;
const char *try2read;
try2read = (char *) NULL;
memset((char *) &dbentry, 0, sizeof(dbentry));
(*linenop)++;
retval = 1;
name = (char *) NULL;
kp = (krb5_key_data *) NULL;
op = (krb5_octet *) NULL;
error = 0;
kret = 0;
nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t", &t1, &t2, &t3, &t4, &t5);
if (nread == 5) {
/* Get memory for flattened principal name */
if (!(name = (char *) malloc((size_t) t2 + 1)))
error++;
/* Get memory for and form tagged data linked list */
tlp = &dbentry.tl_data;
for (i=0; i<t3; i++) {
if ((*tlp = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)))) {
memset(*tlp, 0, sizeof(krb5_tl_data));
tlp = &((*tlp)->tl_data_next);
dbentry.n_tl_data++;
}
else {
error++;
break;
}
}
/* Get memory for key list */
if (t4 && !(kp = (krb5_key_data *) malloc((size_t)
(t4*sizeof(krb5_key_data)))))
error++;
/* Get memory for extra data */
if (t5 && !(op = (krb5_octet *) malloc((size_t) t5)))
error++;
if (!error) {
dbentry.len = (krb5_int16)t1;
dbentry.n_key_data = (krb5_int16)t4;
dbentry.e_length = (krb5_int16)t5;
if (kp) {
memset(kp, 0, (size_t) (t4*sizeof(krb5_key_data)));
dbentry.key_data = kp;
kp = (krb5_key_data *) NULL;
}
if (op) {
memset(op, 0, (size_t) t5);
dbentry.e_data = op;
op = (krb5_octet *) NULL;
}
/* Read in and parse the principal name */
if (!read_string(filep, name, t2, linenop)) {
dbentry.princ = StrDupA(name);
/* Get the fixed principal attributes */
nread = fscanf(filep, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t",
&t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9);
if (nread == 8) {
dbentry.attributes = (krb5_flags) t2;
dbentry.max_life = (krb5_deltat) t3;
dbentry.max_renewable_life = (krb5_deltat) t4;
dbentry.expiration = (krb5_timestamp) t5;
dbentry.pw_expiration = (krb5_timestamp) t6;
dbentry.last_success = (krb5_timestamp) t7;
dbentry.last_failed = (krb5_timestamp) t8;
dbentry.fail_auth_count = (krb5_kvno) t9;
} else {
try2read = read_nint_data;
error++;
}
/*
* Get the tagged data.
*
* Really, this code ought to discard tl data types
* that it knows are special to the current version
* and were not supported in the previous version.
* But it's a pain to implement that here, and doing
* it at dump time has almost as good an effect, so
* that's what I did. [krb5-admin/89/
*/
if (!error && dbentry.n_tl_data) {
for (tl = dbentry.tl_data; tl; tl = tl->tl_data_next) {
nread = fscanf(filep, "%d\t%d\t", &t1, &t2);
if (nread == 2) {
tl->tl_data_type = (krb5_int16) t1;
tl->tl_data_length = (krb5_int16) t2;
if (tl->tl_data_length) {
if (!(tl->tl_data_contents =
(krb5_octet *) malloc((size_t) t2+1)) ||
read_octet_string(filep,
tl->tl_data_contents,
t2)) {
try2read = read_tcontents;
error++;
break;
}
}
else {
/* Should be a null field */
nread = fscanf(filep, "%d", &t9);
if ((nread != 1) || (t9 != -1)) {
error++;
try2read = read_tcontents;
break;
}
}
}
else {
try2read = read_ttypelen;
error++;
break;
}
}
}
/* Get the key data */
if (!error && dbentry.n_key_data) {
for (i=0; !error && (i<dbentry.n_key_data); i++) {
kdatap = &dbentry.key_data[i];
nread = fscanf(filep, "%d\t%d\t", &t1, &t2);
if (nread == 2) {
kdatap->key_data_ver = (krb5_int16) t1;
kdatap->key_data_kvno = (krb5_int16) t2;
for (j=0; j<t1; j++) {
nread = fscanf(filep, "%d\t%d\t", &t3, &t4);
if (nread == 2) {
kdatap->key_data_type[j] = (krb5_int16)t3;
kdatap->key_data_length[j] = (krb5_int16)t4;
if (t4) {
if (!(kdatap->key_data_contents[j] =
(krb5_octet *)
malloc((size_t) t4+1)) ||
read_octet_string(filep,
kdatap->key_data_contents[j],
t4)) {
try2read = read_kcontents;
error++;
break;
}
}
else {
/* Should be a null field */
nread = fscanf(filep, "%d", &t9);
if ((nread != 1) || (t9 != -1)) {
error++;
try2read = read_kcontents;
break;
}
}
}
else {
try2read = read_ktypelen;
error++;
break;
}
}
}
}
}
/* Get the extra data */
if (!error && dbentry.e_length) {
if (read_octet_string(filep,
dbentry.e_data,
(int) dbentry.e_length)) {
try2read = read_econtents;
error++;
}
}
else {
nread = fscanf(filep, "%d", &t9);
if ((nread != 1) || (t9 != -1)) {
error++;
try2read = read_econtents;
}
}
/* Finally, find the end of the record. */
if (!error)
find_record_end(filep, fname, *linenop);
/*
* We have either read in all the data or choked.
*/
if (!error) {
retval = 0;
if (verbose == 2) {
printf("%s\n", dbentry.princ);
printf("\tattr=0x%x\n", dbentry.attributes);
printf("\tmax_life=%d, max_renewable_life=%d\n",
dbentry.max_life, dbentry.max_renewable_life);
printf("\texpiration=%d, pw_exp=%d\n",
dbentry.expiration, dbentry.pw_expiration);
printf("\te_length=%d n_tl_data=%d, n_key_data=%d\n",
dbentry.e_length, dbentry.n_tl_data,
dbentry.n_key_data);
print_tl_data(dbentry.n_tl_data, dbentry.tl_data);
print_key_data(dbentry.n_key_data, dbentry.key_data);
}
if ((kret = ds_put_principal(ds,
dbentry))) {
fprintf(stderr, store_err_fmt,
fname, *linenop,
name, ""/*error_message(kret)*/);
}
else
{
retval = 0;
}
}
else {
fprintf(stderr, read_err_fmt, fname, *linenop, try2read);
}
}
else {
if (kret)
fprintf(stderr, parse_err_fmt,
fname, *linenop, name, ""/*error_message(kret)*/);
else
fprintf(stderr, no_mem_fmt, fname, *linenop);
}
}
else {
fprintf(stderr, rhead_err_fmt, fname, *linenop);
}
if (op)
free(op);
if (kp)
free(kp);
if (name)
free(name);
if (dbentry.princ)
free(dbentry.princ);
}
else {
if (nread == EOF)
retval = -1;
}
return(retval);
}
int process_k5beta7_policy(
const char *fname,
IADs *ds,
FILE *filep,
int verbose,
int *linenop,
void *pol_db
)
{
char namebuf[1024];
int nread;
struct krb5_policy {
char *name;
int pw_min_life;
int pw_max_life;
int pw_min_length;
int pw_min_classes;
int pw_history_num;
int policy_refcnt;
} rec;
(*linenop)++;
rec.name = namebuf;
nread = fscanf(filep, "%1024s\t%d\t%d\t%d\t%d\t%d\t%d", rec.name,
&rec.pw_min_life, &rec.pw_max_life,
&rec.pw_min_length, &rec.pw_min_classes,
&rec.pw_history_num, &rec.policy_refcnt);
if (nread == EOF)
return -1;
else if (nread != 7) {
fprintf(stderr, "cannot parse policy on line %d (%d read)\n",
*linenop, nread);
return 1;
}
#if 0
if (ret = osa_adb_create_policy(pol_db, &rec)) {
if (ret == OSA_ADB_DUP &&
(ret = osa_adb_put_policy(pol_db, &rec))) {
fprintf(stderr, "cannot create policy on line %d: %s\n",
*linenop, error_message(ret));
return 1;
}
}
#else
fprintf(stderr, "Policy %s : min_life=%d max_life=%d min_len=%d min_classes=%d histnum=%d refcnt=%d\n",
rec.name,
rec.pw_min_life, rec.pw_max_life,
rec.pw_min_length, rec.pw_min_classes,
rec.pw_history_num, rec.policy_refcnt);
#endif
if (verbose)
fprintf(stderr, "created policy %s - \n", rec.name);
return 0;
}
/*
* process_k5beta7_record() - Handle a dump record in krb5b6 format.
*
* Returns -1 for end of file, 0 for success and 1 for failure.
*/
static int
process_k5beta7_record(
const char *fname,
IADs *ds,
FILE *filep,
int verbose,
int *linenop,
void *pol_db
)
{
int nread;
char rectype[100];
nread = fscanf(filep, "%100s\t", rectype);
if (nread == EOF)
return -1;
else if (nread != 1)
return 1;
if (strcmp(rectype, "princ") == 0)
process_k5beta6_record(fname, ds, filep, verbose,
linenop);
else if (strcmp(rectype, "policy") == 0)
process_k5beta7_policy(fname, ds, filep, verbose,
linenop, pol_db);
else {
fprintf(stderr, "unknown record type \"%s\" on line %d\n",
rectype, *linenop);
return 1;
}
return 0;
}
/*
* restore_dump() - Restore the database from a standard dump file.
*/
static int
restore_dump(
const char *programname,
const char *dumpfile,
IADs *ds,
FILE *f,
FILE *k,
int verbose
)
{
int error;
int lineno;
char buf[2*sizeof(k5_dump_header)];
short enctype;
int i;
int pol_db;
if (k) {
/*
* Read the master key file
*/
if (fread(&enctype, 2, 1, k) != 1) {
perror("Unable to read master key file");
exit(2);
}
mkey.enctype = enctype;
if (fread((krb5_pointer) &mkey.length,
sizeof(mkey.length), 1, k) != 1) {
perror("Cannot read master key length");
exit(2);
}
if (!mkey.length || mkey.length < 0) {
fprintf(stderr, "Bad stored master key.\n");
exit(2);
}
if (!(mkey.contents = (krb5_octet *)malloc(mkey.length))) {
fprintf(stderr, "Read mkey memory allocation failure.\n");
exit(2);
}
if (fread(mkey.contents,
sizeof(mkey.contents[0]), mkey.length, k) != mkey.length) {
memset(mkey.contents, 0, mkey.length);
perror("Cannot read master key");
exit(2);
}
fclose(k);
printf("Master key: etype=%s [%d]: ",
etype_string(mkey.enctype), mkey.enctype);
for (i = 0; i < mkey.length; i++)
printf(" %02x", mkey.contents[i]);
printf("\n");
}
/*
* Get/check the header.
*/
error = 0;
if (fgets(buf, sizeof(buf), f) == NULL) {
return(1);
}
if (!strcmp(buf, k5_dump_header)) {
lineno = 1;
/*
* Process the records.
*/
while (!(error = process_k5beta7_record(dumpfile,
ds,
f,
verbose,
&lineno, (void *)&pol_db)))
;
if (error != -1)
fprintf(stderr, err_line_fmt, programname, lineno, dumpfile);
else
error = 0;
/*
* Close the input file.
*/
if (f != stdin)
fclose(f);
}
else {
printf("buf=\"%s\"\n", buf);
fprintf(stderr, head_bad_fmt, programname, dumpfile);
error++;
}
return(error);
}
void __cdecl
main(int argc, char *argv[])
{
FILE *kdbFile, *mkeyFile = NULL;
int retval;
IADs *pDS;
int n = 1;
int verbose = 1;
HRESULT hr;
if (argc < 2 || argc > 5) {
printf("Usage: %s [-m <mkey>] <dumpfile>\n", argv[0]);
exit(1);
}
if (argc == 4) {
if (strcmp(argv[1], "-m") == 0) {
mkeyFile = fopen(argv[2], "rb");
if (!mkeyFile) {
perror("Unable to open master key file");
exit(1);
}
n = 3;
}
}
kdbFile = fopen(argv[n], "rb");
if (!kdbFile) {
perror("Unable to open dump file");
exit(1);
}
// need to open DS and pass that in
hr = CoInitialize(NULL);
if (FAILED(hr)) {
fprintf(stderr, "Unable to init com - %s\n", get_error_text(hr));
exit(2);
}
hr = ADsGetObject(TEXT("LDAP://rootDSE"), IID_IADs,
(void **)&pDS);
if (FAILED(hr)) {
fprintf(stderr, "Unable to bind to DS - %s\n", get_error_text(hr));
exit(2);
}
retval = restore_dump(argv[0], argv[1], pDS, kdbFile, mkeyFile, verbose);
fclose(kdbFile);
exit(retval);
}