Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/tests/create/kdb5_mkdums.c
34878 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* tests/create/kdb5_mkdums.c */
3
/*
4
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
5
* All Rights Reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
27
/*
28
*
29
* Edit a KDC database.
30
*/
31
32
#include "k5-int.h"
33
#include "kdb.h"
34
#include "com_err.h"
35
#include <ss/ss.h>
36
#include <stdio.h>
37
38
39
#define REALM_SEP '@'
40
#define REALM_SEP_STR "@"
41
42
struct mblock {
43
krb5_deltat max_life;
44
krb5_deltat max_rlife;
45
krb5_timestamp expiration;
46
krb5_flags flags;
47
krb5_kvno mkvno;
48
} mblock = { /* XXX */
49
KRB5_KDB_MAX_LIFE,
50
KRB5_KDB_MAX_RLIFE,
51
KRB5_KDB_EXPIRATION,
52
KRB5_KDB_DEF_FLAGS,
53
1
54
};
55
56
int set_dbname_help (char *, char *);
57
58
static void
59
usage(char *who, int status)
60
{
61
fprintf(stderr,
62
"usage: %s -p prefix -n num_to_create [-d dbpathname] [-r realmname]\n",
63
who);
64
fprintf(stderr, "\t [-D depth] [-k enctype] [-M mkeyname]\n");
65
66
exit(status);
67
}
68
69
int master_princ_set = 0;
70
krb5_keyblock master_keyblock;
71
krb5_principal master_princ;
72
krb5_pointer master_random;
73
krb5_context test_context;
74
75
static char *progname;
76
static char *cur_realm = 0;
77
static char *mkey_name = 0;
78
static char *mkey_password = 0;
79
static krb5_boolean manual_mkey = FALSE;
80
81
void add_princ (krb5_context, char *);
82
83
int
84
main(int argc, char *argv[])
85
{
86
extern char *optarg;
87
int optchar, i, n;
88
char tmp[4096], tmp2[BUFSIZ], *str_newprinc;
89
90
krb5_error_code retval;
91
char *dbname = 0;
92
int enctypedone = 0;
93
int num_to_create;
94
char principal_string[BUFSIZ];
95
char *suffix = 0;
96
size_t suffix_size = 0;
97
int depth;
98
99
krb5_init_context(&test_context);
100
101
if (strrchr(argv[0], '/'))
102
argv[0] = strrchr(argv[0], '/')+1;
103
104
progname = argv[0];
105
106
memset(principal_string, 0, sizeof(principal_string));
107
num_to_create = 0;
108
depth = 1;
109
110
while ((optchar = getopt(argc, argv, "D:P:p:n:d:r:k:M:e:m")) != -1) {
111
switch(optchar) {
112
case 'D':
113
depth = atoi(optarg); /* how deep to go */
114
break;
115
case 'P': /* Only used for testing!!! */
116
mkey_password = optarg;
117
break;
118
case 'p': /* prefix name to create */
119
strncpy(principal_string, optarg, sizeof(principal_string) - 1);
120
principal_string[sizeof(principal_string) - 1] = '\0';
121
suffix = principal_string + strlen(principal_string);
122
suffix_size = sizeof(principal_string) -
123
(suffix - principal_string);
124
break;
125
case 'n': /* how many to create */
126
num_to_create = atoi(optarg);
127
break;
128
case 'd': /* set db name */
129
dbname = optarg;
130
break;
131
case 'r':
132
cur_realm = optarg;
133
break;
134
case 'k':
135
master_keyblock.enctype = atoi(optarg);
136
enctypedone++;
137
break;
138
case 'M': /* master key name in DB */
139
mkey_name = optarg;
140
break;
141
case 'm':
142
manual_mkey = TRUE;
143
break;
144
case '?':
145
default:
146
usage(progname, 1);
147
/*NOTREACHED*/
148
}
149
}
150
151
if (!(num_to_create && suffix)) usage(progname, 1);
152
153
if (!enctypedone)
154
master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
155
156
if (!krb5_c_valid_enctype(master_keyblock.enctype)) {
157
com_err(progname, KRB5_PROG_ETYPE_NOSUPP,
158
"while setting up enctype %d", master_keyblock.enctype);
159
exit(1);
160
}
161
162
if (!dbname)
163
dbname = DEFAULT_KDB_FILE; /* XXX? */
164
165
if (!cur_realm) {
166
if ((retval = krb5_get_default_realm(test_context, &cur_realm))) {
167
com_err(progname, retval, "while retrieving default realm name");
168
exit(1);
169
}
170
}
171
if ((retval = set_dbname_help(progname, dbname)))
172
exit(retval);
173
174
for (n = 1; n <= num_to_create; n++) {
175
/* build the new principal name */
176
/* we can't pick random names because we need to generate all the names
177
again given a prefix and count to test the db lib and kdb */
178
(void) snprintf(suffix, suffix_size, "%d", n);
179
(void) snprintf(tmp, sizeof(tmp), "%s-DEPTH-1", principal_string);
180
tmp[sizeof(tmp) - 1] = '\0';
181
str_newprinc = tmp;
182
add_princ(test_context, str_newprinc);
183
184
for (i = 2; i <= depth; i++) {
185
(void) snprintf(tmp2, sizeof(tmp2), "/%s-DEPTH-%d",
186
principal_string, i);
187
tmp2[sizeof(tmp2) - 1] = '\0';
188
strncat(tmp, tmp2, sizeof(tmp) - 1 - strlen(tmp));
189
str_newprinc = tmp;
190
add_princ(test_context, str_newprinc);
191
}
192
}
193
194
retval = krb5_db_fini(test_context);
195
memset(master_keyblock.contents, 0,
196
(size_t) master_keyblock.length);
197
if (retval && retval != KRB5_KDB_DBNOTINITED) {
198
com_err(progname, retval, "while closing database");
199
exit(1);
200
}
201
if (master_princ_set)
202
krb5_free_principal(test_context, master_princ);
203
krb5_free_context(test_context);
204
exit(0);
205
}
206
207
void
208
add_princ(krb5_context context, char *str_newprinc)
209
{
210
krb5_error_code retval;
211
krb5_principal newprinc;
212
krb5_db_entry *newentry;
213
char princ_name[4096];
214
215
newentry = calloc(1, sizeof(*newentry));
216
if (newentry == NULL) {
217
com_err(progname, ENOMEM, "while allocating DB entry");
218
return;
219
}
220
snprintf(princ_name, sizeof(princ_name), "%s@%s", str_newprinc, cur_realm);
221
if ((retval = krb5_parse_name(context, princ_name, &newprinc))) {
222
com_err(progname, retval, "while parsing '%s'", princ_name);
223
return;
224
}
225
226
/* Add basic data */
227
newentry->len = KRB5_KDB_V1_BASE_LENGTH;
228
newentry->attributes = mblock.flags;
229
newentry->max_life = mblock.max_life;
230
newentry->max_renewable_life = mblock.max_rlife;
231
newentry->expiration = mblock.expiration;
232
newentry->pw_expiration = mblock.expiration;
233
234
/* Add princ to db entry */
235
if ((retval = krb5_copy_principal(context, newprinc, &newentry->princ))) {
236
com_err(progname, retval, "while encoding princ to db entry for '%s'",
237
princ_name);
238
krb5_free_principal(context, newprinc);
239
goto error;
240
}
241
242
{
243
/* Add mod princ to db entry */
244
krb5_timestamp now;
245
246
retval = krb5_timeofday(context, &now);
247
if (retval) {
248
com_err(progname, retval, "while fetching date");
249
krb5_free_principal(context, newprinc);
250
goto error;
251
}
252
retval = krb5_dbe_update_mod_princ_data(context, newentry, now,
253
master_princ);
254
if (retval) {
255
com_err(progname, retval, "while encoding mod_princ data");
256
krb5_free_principal(context, newprinc);
257
goto error;
258
}
259
}
260
261
{ /* Add key and salt data to db entry */
262
krb5_data pwd, salt;
263
krb5_keyblock key;
264
265
if ((retval = krb5_principal2salt(context, newprinc, &salt))) {
266
com_err(progname, retval, "while converting princ to salt for '%s'",
267
princ_name);
268
krb5_free_principal(context, newprinc);
269
goto error;
270
}
271
272
krb5_free_principal(context, newprinc);
273
274
pwd.length = strlen(princ_name);
275
pwd.data = princ_name; /* must be able to regenerate */
276
if ((retval = krb5_c_string_to_key(context, master_keyblock.enctype,
277
&pwd, &salt, &key))) {
278
com_err(progname,retval,"while converting password to key for '%s'",
279
princ_name);
280
krb5_free_data_contents(context, &salt);
281
goto error;
282
}
283
krb5_free_data_contents(context, &salt);
284
285
if ((retval = krb5_dbe_create_key_data(context, newentry))) {
286
com_err(progname, retval, "while creating key_data for '%s'",
287
princ_name);
288
free(key.contents);
289
goto error;
290
}
291
292
if ((retval = krb5_dbe_encrypt_key_data(context, &master_keyblock,
293
&key, NULL, 1,
294
newentry->key_data))) {
295
com_err(progname, retval, "while encrypting key for '%s'",
296
princ_name);
297
free(key.contents);
298
goto error;
299
}
300
free(key.contents);
301
}
302
303
if ((retval = krb5_db_put_principal(context, newentry))) {
304
com_err(progname, retval, "while storing principal date");
305
goto error;
306
}
307
308
error: /* Do cleanup of newentry regardless of error */
309
krb5_db_free_principal(context, newentry);
310
return;
311
}
312
313
int
314
set_dbname_help(char *pname, char *dbname)
315
{
316
krb5_error_code retval;
317
krb5_data pwd, scratch;
318
char *args[2];
319
krb5_db_entry *master_entry;
320
321
/* assemble & parse the master key name */
322
323
if ((retval = krb5_db_setup_mkey_name(test_context, mkey_name, cur_realm,
324
0, &master_princ))) {
325
com_err(pname, retval, "while setting up master key name");
326
return(1);
327
}
328
master_princ_set = 1;
329
if (mkey_password) {
330
pwd.data = mkey_password;
331
pwd.length = strlen(mkey_password);
332
retval = krb5_principal2salt(test_context, master_princ, &scratch);
333
if (retval) {
334
com_err(pname, retval, "while calculated master key salt");
335
return(1);
336
}
337
if ((retval = krb5_c_string_to_key(test_context,
338
master_keyblock.enctype,
339
&pwd, &scratch,
340
&master_keyblock))) {
341
com_err(pname, retval,
342
"while transforming master key from password");
343
return(1);
344
}
345
free(scratch.data);
346
} else {
347
if ((retval = krb5_db_fetch_mkey(test_context, master_princ,
348
master_keyblock.enctype, manual_mkey,
349
FALSE, 0, NULL, NULL,
350
&master_keyblock))) {
351
com_err(pname, retval, "while reading master key");
352
return(1);
353
}
354
}
355
356
/* Ick! Current DAL interface requires that the default_realm
357
field be set in the krb5_context. */
358
if ((retval = krb5_set_default_realm(test_context, cur_realm))) {
359
com_err(pname, retval, "setting default realm");
360
return 1;
361
}
362
/* Pathname is passed to db2 via 'args' parameter. */
363
args[1] = NULL;
364
if (asprintf(&args[0], "dbname=%s", dbname) < 0) {
365
com_err(pname, errno, "while setting up db parameters");
366
return 1;
367
}
368
369
if ((retval = krb5_db_open(test_context, args, KRB5_KDB_OPEN_RO))) {
370
com_err(pname, retval, "while initializing database");
371
return(1);
372
}
373
/* Done with args */
374
free(args[0]);
375
376
if ((retval = krb5_db_fetch_mkey_list(test_context, master_princ,
377
&master_keyblock))){
378
com_err(pname, retval, "while verifying master key");
379
(void) krb5_db_fini(test_context);
380
return(1);
381
}
382
if ((retval = krb5_db_get_principal(test_context, master_princ, 0,
383
&master_entry))) {
384
com_err(pname, retval, "while retrieving master entry");
385
(void) krb5_db_fini(test_context);
386
return(1);
387
}
388
389
mblock.max_life = master_entry->max_life;
390
mblock.max_rlife = master_entry->max_renewable_life;
391
mblock.expiration = master_entry->expiration;
392
393
/* don't set flags, master has some extra restrictions */
394
mblock.mkvno = master_entry->key_data[0].key_data_kvno;
395
396
krb5_db_free_principal(test_context, master_entry);
397
return 0;
398
}
399
400