aboutsummaryrefslogtreecommitdiff
path: root/src/lib/kdb/fetch_mkey.c
blob: 0f074258fe28a2c2cf847933693a8b0659a9e68c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * $Source$
 * $Author$
 *
 * Copyright 1990 by the Massachusetts Institute of Technology.
 *
 * For copying and distribution information, please see the file
 * <krb5/copyright.h>.
 *
 * krb5_db_fetch_mkey():
 * Fetch a database master key from somewhere.
 */

#if !defined(lint) && !defined(SABER)
static char rcsid_fetch_mkey_c[] =
"$Id$";
#endif	/* !lint & !SABER */

#include <krb5/copyright.h>
#include <krb5/krb5.h>
#include <krb5/kdb.h>
#include <krb5/libos-proto.h>
#include <krb5/ext-proto.h>
#include <krb5/sysincl.h>		/* for MAXPATHLEN */
#include "kdbint.h"

/* these are available to other funcs, and the pointers may be reassigned */

char *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
char *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;

/*
 * Get the KDC database master key from somewhere, filling it into *key.
 *
 * key->keytype should be set to the desired key type.
 *
 * if fromkeyboard is TRUE, then the master key is read as a password
 * from the user's terminal.  In this case,
 * eblock should point to a block with an appropriate string_to_key function.
 * if twice is TRUE, the password is read twice for verification.
 *
 * mname is the name of the key sought; this can be used by the string_to_key
 * function or by some other method to isolate the desired key.
 *
 */

#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif

krb5_error_code
krb5_db_fetch_mkey(DECLARG(krb5_principal, mname),
		   DECLARG(krb5_encrypt_block *, eblock),
		   DECLARG(krb5_boolean, fromkeyboard),
		   DECLARG(krb5_boolean, twice),
		   DECLARG(krb5_keyblock *,key))
OLDDECLARG(krb5_principal, mname)
OLDDECLARG(krb5_encrypt_block *, eblock)
OLDDECLARG(krb5_boolean, fromkeyboard)
OLDDECLARG(krb5_boolean, twice)
OLDDECLARG(krb5_keyblock *,key)
{
    krb5_error_code retval;
    char password[BUFSIZ];
    krb5_data pwd;
    int size = sizeof(password);


    if (fromkeyboard) {
	if (retval = krb5_read_password(krb5_mkey_pwd_prompt1,
					twice ? krb5_mkey_pwd_prompt2 : 0,
					password,
					&size))
	    return(retval);

	pwd.data = password;
	pwd.length = size;
	retval = krb5_string_to_key(eblock, key->keytype, key, &pwd, mname);
	bzero(password, sizeof(password)); /* erase it */
	return retval;

    } else {
	/* from somewhere else */
	krb5_keytype keytype;
	char defkeyfile[MAXPATHLEN+1];
	krb5_data *realm = krb5_princ_realm(mname);
	FILE *kf;

	retval = 0;
	(void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
	(void) strncat(defkeyfile, realm->data,
		       min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
			   realm->length));
	(void) strcat(defkeyfile, "");
	
	if (!(kf = fopen(defkeyfile, "r")))
	    return KRB5_KDB_CANTREAD_STORED;
	if (fread((krb5_pointer) &keytype, sizeof(keytype), 1, kf) != 1) {
	    retval = KRB5_KDB_CANTREAD_STORED;
	    goto errout;
	}
	if (keytype != key->keytype) {
	    retval = KRB5_KDB_BADSTORED_MKEY;
	    goto errout;
	}
	if (fread((krb5_pointer) &key->length,
		  sizeof(key->length), 1, kf) != 1) {
	    retval = KRB5_KDB_CANTREAD_STORED;
	    goto errout;
	}
	if (!key->length || key->length < 0) {
	    retval = KRB5_KDB_BADSTORED_MKEY;
	    goto errout;
	}
	if (!(key->contents = (krb5_octet *)malloc(key->length))) {
	    retval = ENOMEM;
	    goto errout;
	}
	if (fread((krb5_pointer) key->contents,
		  sizeof(key->contents[0]), key->length, kf) != key->length)
	    retval = KRB5_KDB_CANTREAD_STORED;
	else
	    retval = 0;
    errout:
	(void) fclose(kf);
	return retval;
    }
}