2 Copyright (C) 1989 by the Massachusetts Institute of Technology
4 Export of this software from the United States of America is assumed
5 to require a specific license from the United States Government.
6 It is the responsibility of any person or organization contemplating
7 export to obtain such a license before exporting.
9 WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10 distribute this software and its documentation for any purpose and
11 without fee is hereby granted, provided that the above copyright
12 notice appear in all copies and that both that copyright notice and
13 this permission notice appear in supporting documentation, and that
14 the name of M.I.T. not be used in advertising or publicity pertaining
15 to distribution of the software without specific, written prior
16 permission. M.I.T. makes no representations about the suitability of
17 this software for any purpose. It is provided "as is" without express
23 * Utility routines for Kerberos programs which directly access
24 * the database. This code was duplicated in too many places
25 * before I gathered it here.
27 * Jon Rochlis, MIT Telecom, March 1988
34 RCSID("$Id: krb_kdb_utils.c,v 1.25 1999/03/13 21:24:21 assar Exp $");
36 /* always try /.k for backwards compatibility */
37 static char *master_key_files[] = { MKEYFILE, "/.k", NULL };
40 #define k_strerror(e) strerror(e)
47 extern char *sys_errlist[];
49 static char emsg[128];
51 if (eno < 0 || eno >= sys_nerr)
52 snprintf(emsg, sizeof(emsg), "Error %d occurred.", eno);
54 return sys_errlist[eno];
61 kdb_new_get_master_key(des_cblock *key, des_key_schedule schedule)
69 for(mkey = master_key_files; *mkey; mkey++){
70 kfile = open(*mkey, O_RDONLY);
71 if(kfile < 0 && errno != ENOENT)
72 fprintf(stderr, "Failed to open master key file \"%s\": %s\n",
80 bytes = read(kfile, (char*)key, sizeof(des_cblock));
82 if(bytes == sizeof(des_cblock)){
83 des_key_sched(key, schedule);
86 fprintf(stderr, "Could only read %d bytes from master key file %s\n",
89 fprintf(stderr, "No master key file found.\n");
95 if(des_read_pw_string(buf, sizeof(buf), "Enter master password: ", 0))
98 /* buffer now contains either an old format master key password or a
99 * new format base64 encoded master key
102 /* try to verify as old password */
103 des_string_to_key(buf, key);
104 des_key_sched(key, schedule);
106 if(kdb_verify_master_key(key, schedule, NULL) != -1){
107 memset(buf, 0, sizeof(buf));
111 /* failed test, so must be base64 encoded */
113 if(base64_decode(buf, key) == 8){
114 des_key_sched(key, schedule);
115 if(kdb_verify_master_key(key, schedule, NULL) != -1){
116 memset(buf, 0, sizeof(buf));
121 memset(buf, 0, sizeof(buf));
122 fprintf(stderr, "Failed to verify master key.\n");
127 fprintf(stderr, "You loose.\n");
132 kdb_new_get_new_master_key(des_cblock *key,
133 des_key_schedule schedule,
137 des_read_password(key, "\nEnter Kerberos master password: ", verify);
141 des_generate_random_block (key);
142 des_key_sched(key, schedule);
144 des_read_pw_string(buf, sizeof(buf), "Enter master key seed: ", 0);
145 des_cbc_cksum((des_cblock*)buf, key, sizeof(buf), schedule, key);
146 memset(buf, 0, sizeof(buf));
148 des_key_sched(key, schedule);
153 kdb_get_master_key(int prompt,
154 des_cblock *master_key,
155 des_key_schedule master_key_sched)
157 int ask = (prompt == KDB_GET_TWICE);
159 ask |= (prompt == KDB_GET_PROMPT);
163 kdb_new_get_new_master_key(master_key, master_key_sched,
164 prompt == KDB_GET_TWICE);
166 kdb_new_get_master_key(master_key, master_key_sched);
171 kdb_kstash(des_cblock *master_key, char *file)
175 kfile = open(file, O_TRUNC | O_RDWR | O_CREAT, 0600);
179 if (write(kfile, master_key, sizeof(des_cblock)) != sizeof(des_cblock)) {
187 /* The old algorithm used the key schedule as the initial vector which
188 was byte order depedent ... */
191 kdb_encrypt_key (des_cblock (*in), des_cblock (*out),
192 des_cblock (*master_key),
193 des_key_schedule master_key_sched, int e_d_flag)
197 memcpy(out, in, sizeof(des_cblock));
199 des_pcbc_encrypt(in,out,(long)sizeof(des_cblock),master_key_sched,master_key,
204 /* The caller is reasponsible for cleaning up the master key and sched,
205 even if we can't verify the master key */
207 /* Returns master key version if successful, otherwise -1 */
210 kdb_verify_master_key (des_cblock *master_key,
211 des_key_schedule master_key_sched,
212 FILE *out) /* NULL -> no output */
214 des_cblock key_from_db;
215 Principal principal_data[1];
217 long master_key_version;
219 /* lookup the master key version */
220 n = kerb_get_principal(KERB_M_NAME, KERB_M_INST, principal_data,
221 1 /* only one please */, &more);
222 if ((n != 1) || more) {
225 "verify_master_key: %s, %d found.\n",
226 "Kerberos error on master key version lookup",
231 master_key_version = (long) principal_data[0].key_version;
233 /* set up the master key */
234 if (out != NULL) /* should we punt this? */
235 fprintf(out, "Current Kerberos master key version is %d.\n",
236 principal_data[0].kdc_key_ver);
239 * now use the master key to decrypt the key in the db, had better
242 copy_to_key(&principal_data[0].key_low,
243 &principal_data[0].key_high,
245 kdb_encrypt_key (&key_from_db, &key_from_db,
246 master_key, master_key_sched, DES_DECRYPT);
248 /* the decrypted database key had better equal the master key */
249 n = memcmp(master_key, key_from_db, sizeof(master_key));
250 /* this used to zero the master key here! */
251 memset(key_from_db, 0, sizeof(key_from_db));
252 memset(principal_data, 0, sizeof (principal_data));
254 if (n && (out != NULL)) {
255 fprintf(out, "\n\07\07verify_master_key: Invalid master key; ");
256 fprintf(out, "does not match database.\n");
261 if (out != (FILE *) NULL) {
262 fprintf(out, "\nMaster key entered. BEWARE!\07\07\n");
266 return (master_key_version);