Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / admin / kdb_edit.c
1 /*
2  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
3  * of Technology.
4  *
5  * For copying and distribution information, please see the file
6  * <mit-copyright.h>.
7  *
8  * This routine changes the Kerberos encryption keys for principals,
9  * i.e., users or services. 
10  */
11 /* $FreeBSD: src/crypto/kerberosIV/admin/kdb_edit.c,v 1.1.1.3.2.1 2003/02/14 22:37:37 nectar Exp $ */
12
13 /*
14  * exit returns          0 ==> success -1 ==> error 
15  */
16
17 #include "adm_locl.h"
18
19 RCSID("$Id: kdb_edit.c,v 1.28 1999/09/16 20:37:21 assar Exp $");
20
21 #ifdef DEBUG
22 extern  kerb_debug;
23 #endif
24
25 static int     nflag = 0;
26 static int     debug;
27
28 static des_cblock new_key;
29
30 static int     i, j;
31 static int     more;
32
33 static char    input_name[ANAME_SZ];
34 static char    input_instance[INST_SZ];
35
36 #define MAX_PRINCIPAL   10
37 static Principal principal_data[MAX_PRINCIPAL];
38
39 static Principal old_principal;
40 static Principal default_princ;
41
42 static des_cblock master_key;
43 static des_cblock session_key;
44 static des_key_schedule master_key_schedule;
45 static char pw_str[255];
46 static long master_key_version;
47
48 static void
49 Usage(void)
50 {
51     fprintf(stderr, "Usage: %s [-n]\n", __progname);
52     exit(1);
53 }
54
55 static char *
56 n_gets(char *buf, int size)
57 {
58     char *p;
59     char *ret;
60     ret = fgets(buf, size, stdin);
61   
62     if (ret && (p = strchr(buf, '\n')))
63         *p = 0;
64     return ret;
65 }
66
67
68 static int
69 change_principal(void)
70 {
71     static char temp[255];
72     int     creating = 0;
73     int     editpw = 0;
74     int     changed = 0;
75     long    temp_long;          /* Don't change to int32_t, used by scanf */
76     struct tm   edate;
77
78     fprintf(stdout, "\nPrincipal name: ");
79     fflush(stdout);
80     if (!n_gets(input_name, sizeof(input_name)) || *input_name == '\0')
81         return 0;
82     fprintf(stdout, "Instance: ");
83     fflush(stdout);
84     /* instance can be null */
85     n_gets(input_instance, sizeof(input_instance));
86     j = kerb_get_principal(input_name, input_instance, principal_data,
87                            MAX_PRINCIPAL, &more);
88     if (!j) {
89         fprintf(stdout, "\n\07\07<Not found>, Create [y] ? ");
90         fflush(stdout);
91         n_gets(temp, sizeof(temp));             /* Default case should work, it didn't */
92         if (temp[0] != 'y' && temp[0] != 'Y' && temp[0] != '\0')
93             return -1;
94         /* make a new principal, fill in defaults */
95         j = 1;
96         creating = 1;
97         strlcpy(principal_data[0].name,
98                         input_name,
99                         ANAME_SZ);
100         strlcpy(principal_data[0].instance,
101                         input_instance,
102                         INST_SZ);
103         principal_data[0].old = NULL;
104         principal_data[0].exp_date = default_princ.exp_date;
105         if (strcmp(input_instance, "admin") == 0)
106           principal_data[0].max_life = 1 + (CLOCK_SKEW/(5*60)); /*5+5 minutes*/
107         else if (strcmp(input_instance, "root") == 0)
108           principal_data[0].max_life = 96; /* 8 hours */
109         else
110           principal_data[0].max_life = default_princ.max_life;
111         principal_data[0].attributes = default_princ.attributes;
112         principal_data[0].kdc_key_ver = (unsigned char) master_key_version;
113         principal_data[0].key_version = 0; /* bumped up later */
114     }
115     *principal_data[0].exp_date_txt = '\0';
116     for (i = 0; i < j; i++) {
117         for (;;) {
118             fprintf(stdout,
119                     "\nPrincipal: %s, Instance: %s, kdc_key_ver: %d",
120                     principal_data[i].name, principal_data[i].instance,
121                     principal_data[i].kdc_key_ver);
122             fflush(stdout);
123             editpw = 1;
124             changed = 0;
125             if (!creating) {
126                 /*
127                  * copy the existing data so we can use the old values
128                  * for the qualifier clause of the replace 
129                  */
130                 principal_data[i].old = (char *) &old_principal;
131                 memcpy(&old_principal, &principal_data[i],
132                        sizeof(old_principal));
133                 printf("\nChange password [n] ? ");
134                 n_gets(temp, sizeof(temp));
135                 if (strcmp("y", temp) && strcmp("Y", temp))
136                     editpw = 0;
137             }
138             /* password */
139             if (editpw) {
140 #ifdef NOENCRYPTION
141                 placebo_read_pw_string(pw_str, sizeof pw_str,
142                     "\nNew Password: ", TRUE);
143 #else
144                 if(des_read_pw_string(pw_str, sizeof pw_str,
145                         "\nNew Password: ", TRUE))
146                     continue;
147 #endif
148                 if (   strcmp(pw_str, "RANDOM") == 0
149                     || strcmp(pw_str, "") == 0) {
150                     printf("\nRandom password [y] ? ");
151                     n_gets(temp, sizeof(temp));
152                     if (!strcmp("n", temp) || !strcmp("N", temp)) {
153                         /* no, use literal */
154 #ifdef NOENCRYPTION
155                         memset(new_key, 0, sizeof(des_cblock));
156                         new_key[0] = 127;
157 #else
158                         des_string_to_key(pw_str, &new_key);
159 #endif
160                         memset(pw_str, 0, sizeof pw_str);       /* "RANDOM" */
161                     } else {
162 #ifdef NOENCRYPTION
163                         memset(new_key, 0, sizeof(des_cblock));
164                         new_key[0] = 127;
165 #else
166                         des_random_key(new_key);
167 #endif
168                         memset(pw_str, 0, sizeof pw_str);
169                     }
170                 } else if (!strcmp(pw_str, "NULL")) {
171                     printf("\nNull Key [y] ? ");
172                     n_gets(temp, sizeof(temp));
173                     if (!strcmp("n", temp) || !strcmp("N", temp)) {
174                         /* no, use literal */
175 #ifdef NOENCRYPTION
176                         memset(new_key, 0, sizeof(des_cblock));
177                         new_key[0] = 127;
178 #else
179                         des_string_to_key(pw_str, &new_key);
180 #endif
181                         memset(pw_str, 0, sizeof pw_str);       /* "NULL" */
182                     } else {
183
184                         principal_data[i].key_low = 0;
185                         principal_data[i].key_high = 0;
186                         goto null_key;
187                     }
188                 } else {
189 #ifdef NOENCRYPTION
190                     memset(new_key, 0, sizeof(des_cblock));
191                     new_key[0] = 127;
192 #else
193                     des_string_to_key(pw_str, &new_key);
194 #endif
195                     memset(pw_str, 0, sizeof pw_str);
196                 }
197
198                 /* seal it under the kerberos master key */
199                 kdb_encrypt_key (&new_key, &new_key, 
200                                  &master_key, master_key_schedule,
201                                  DES_ENCRYPT);
202                 copy_from_key(new_key,
203                               &principal_data[i].key_low,
204                               &principal_data[i].key_high);
205                 memset(new_key, 0, sizeof(new_key));
206         null_key:
207                 /* set master key version */
208                 principal_data[i].kdc_key_ver =
209                     (unsigned char) master_key_version;
210                 /* bump key version # */
211                 principal_data[i].key_version++;
212                 fprintf(stdout,
213                         "\nPrincipal's new key version = %d\n",
214                         principal_data[i].key_version);
215                 fflush(stdout);
216                 changed = 1;
217             }
218             /* expiration date */
219             {
220                 char d[DATE_SZ];
221                 struct tm *tm;
222                 tm = k_localtime(&principal_data[i].exp_date);
223                 strftime(d, sizeof(d), "%Y-%m-%d", tm);
224                 while(1) {
225                     printf("Expiration date (yyyy-mm-dd) [ %s ] ? ", d);
226                     fflush(stdout);
227                     if(n_gets(temp, sizeof(temp)) == NULL) {
228                         printf("Invalid date.\n");
229                         continue;
230                     }
231                     if (*temp) {
232                         memset(&edate, 0, sizeof(edate));
233                         if (sscanf(temp, "%d-%d-%d", &edate.tm_year,
234                                    &edate.tm_mon, &edate.tm_mday) != 3) {
235                             printf("Invalid date.\n");
236                             continue;
237                         }
238                         edate.tm_mon--;     /* January is 0, not 1 */
239                         edate.tm_hour = 23; /* at the end of the */
240                         edate.tm_min = 59;  /* specified day */
241                         if (krb_check_tm (edate)) {
242                             printf("Invalid date.\n");
243                             continue;
244                         }
245                         edate.tm_year -= 1900;
246                         principal_data[i].exp_date = tm2time (edate, 1);
247                         changed = 1;
248                     }
249                     break;
250                 }
251             }
252
253             /* maximum lifetime */
254             fprintf(stdout, "Max ticket lifetime (*5 minutes) [ %d ] ? ",
255                     principal_data[i].max_life);
256             fflush(stdout);
257             while (n_gets(temp, sizeof(temp)) && *temp) {
258                 if (sscanf(temp, "%ld", &temp_long) != 1)
259                     goto bad_life;
260                 if (temp_long > 255 || (temp_long < 0)) {
261                 bad_life:
262                     fprintf(stdout, "\07\07Invalid, choose 0-255\n");
263                     fprintf(stdout,
264                             "Max ticket lifetime (*5 minutes) [ %d ] ? ",
265                             principal_data[i].max_life);
266                     fflush(stdout);
267                     continue;
268                 }
269                 changed = 1;
270                 /* dont clobber */
271                 principal_data[i].max_life = (unsigned short) temp_long;
272                 break;
273             }
274
275             /* attributes */
276             fprintf(stdout, "Attributes [ %d ] ? ",
277                     principal_data[i].attributes);
278             fflush(stdout);
279             while (n_gets(temp, sizeof(temp)) && *temp) {
280                 if (sscanf(temp, "%ld", &temp_long) != 1)
281                     goto bad_att;
282                 if (temp_long > 65535 || (temp_long < 0)) {
283                 bad_att:
284                     fprintf(stdout, "Invalid, choose 0-65535\n");
285                     fprintf(stdout, "Attributes [ %d ] ? ",
286                             principal_data[i].attributes);
287                     fflush(stdout);
288                     continue;
289                 }
290                 changed = 1;
291                 /* dont clobber */
292                 principal_data[i].attributes =
293                     (unsigned short) temp_long;
294                 break;
295             }
296
297             /*
298              * remaining fields -- key versions and mod info, should
299              * not be directly manipulated 
300              */
301             if (changed) {
302                 if (kerb_put_principal(&principal_data[i], 1)) {
303                     fprintf(stdout,
304                         "\nError updating Kerberos database");
305                 } else {
306                     fprintf(stdout, "Edit O.K.");
307                 }
308             } else {
309                 fprintf(stdout, "Unchanged");
310             }
311
312
313             memset(&principal_data[i].key_low, 0, 4);
314             memset(&principal_data[i].key_high, 0, 4);
315             fflush(stdout);
316             break;
317         }
318     }
319     if (more) {
320         fprintf(stdout, "\nThere were more tuples found ");
321         fprintf(stdout, "than there were space for");
322       }
323     return 1;
324 }
325
326 static void
327 cleanup(void)
328 {
329
330     memset(master_key, 0, sizeof(master_key));
331     memset(session_key, 0, sizeof(session_key));
332     memset(master_key_schedule, 0, sizeof(master_key_schedule));
333     memset(principal_data, 0, sizeof(principal_data));
334     memset(new_key, 0, sizeof(new_key));
335     memset(pw_str, 0, sizeof(pw_str));
336 }
337
338 int
339 main(int argc, char **argv)
340 {
341     /* Local Declarations */
342
343     long    n;
344
345     set_progname (argv[0]);
346
347     while (--argc > 0 && (*++argv)[0] == '-')
348         for (i = 1; argv[0][i] != '\0'; i++) {
349             switch (argv[0][i]) {
350
351                 /* debug flag */
352             case 'd':
353                 debug = 1;
354                 continue;
355
356                 /* debug flag */
357 #ifdef DEBUG
358             case 'l':
359                 kerb_debug |= 1;
360                 continue;
361 #endif
362             case 'n':           /* read MKEYFILE for master key */
363                 nflag = 1;
364                 continue;
365
366             default:
367                 warnx ("illegal flag \"%c\"", argv[0][i]);
368                 Usage();        /* Give message and die */
369             }
370         }
371
372     fprintf(stdout, "Opening database...\n");
373     fflush(stdout);
374     kerb_init();
375     if (argc > 0)
376         if (kerb_db_set_name(*argv) != 0)
377             errx (1, "Could not open altername database name");
378
379     if (kdb_get_master_key ((nflag == 0) ? KDB_GET_PROMPT : 0, 
380                             &master_key, master_key_schedule) != 0)
381         errx (1, "Couldn't read master key.");
382
383     if ((master_key_version = kdb_verify_master_key(&master_key,
384                                                     master_key_schedule,
385                                                     stdout)) < 0)
386       return 1;
387
388     /* lookup the default values */
389     n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
390                            &default_princ, 1, &more);
391     if (n != 1)
392         errx (1, "Kerberos error on default value lookup, %ld found.", n);
393     fprintf(stdout, "Previous or default values are in [brackets] ,\n");
394     fprintf(stdout, "enter return to leave the same, or new value.\n");
395
396     while (change_principal()) {
397     }
398
399     cleanup();
400     return 0;
401 }