4 * asetkey - Manipulates an AFS KeyFile
6 * Updated for Kerberos 5
10 #include <afs/param.h>
15 #define KERBEROS_APPLE_DEPRECATED(x)
18 #ifndef HAVE_KERBEROSV_HEIM_ERR_H
19 #include <afs/com_err.h>
21 #include <afs/cellconfig.h>
23 #include <afs/dirpath.h>
25 #ifdef HAVE_KRB5_CREDS_KEYBLOCK
28 #ifdef HAVE_KRB5_CREDS_SESSION
29 #define USING_HEIMDAL 1
33 stringToType(const char *string) {
34 if (strcmp(string, "rxkad") == 0)
36 if (strcmp(string, "rxkad_krb5") == 0)
37 return afsconf_rxkad_krb5;
38 if (strcmp(string, "rxgk") == 0)
45 printKey(const struct rx_opaque *key)
49 for (i = 0; i < key->len; i++)
50 printf("%02x", ((unsigned char *)key->val)[i]);
58 if (c >= '0' && c <= '9')
60 if ((c >= 'a') && (c <= 'f'))
61 return (c - 'a' + 10);
63 if ((c >= 'A') && (c <= 'F'))
64 return (c - 'A' + 10);
69 static struct afsconf_typedKey *
70 keyFromCommandLine(afsconf_keyType type, int kvno, int subType,
71 const char *string, size_t length)
74 struct afsconf_typedKey *typedKey;
78 if (strlen(string) != 2*length) {
79 printf("key %s is not in right format\n", string);
80 printf(" <key> should be an %d byte hex representation \n", (int) length);
84 rx_opaque_alloc(&key, length);
86 for (i = 0; i< length; i++) {
87 ((char *)key.val)[i] = char2hex(*cp) * 16 + char2hex(*(cp+1));
91 typedKey = afsconf_typedKey_new(type, kvno, subType, &key);
92 rx_opaque_freeContents(&key);
97 #define deref_key_length(key) \
100 #define deref_key_contents(key) \
103 #define deref_key_length(key) \
106 #define deref_key_contents(key) \
110 static struct afsconf_typedKey *
111 keyFromKeytab(int kvno, afsconf_keyType type, int subtype, const char *keytab, const char *princ)
114 krb5_principal principal;
116 krb5_context context;
117 struct rx_opaque buffer;
118 struct afsconf_typedKey *typedKey;
120 krb5_init_context(&context);
122 retval = krb5_parse_name(context, princ, &principal);
124 afs_com_err("asetkey", retval, "while parsing AFS principal");
128 if (type == afsconf_rxkad) {
129 retval = krb5_kt_read_service_key(context, (char *)keytab, principal,
130 kvno, ENCTYPE_DES_CBC_CRC, &key);
131 if (retval == KRB5_KT_NOTFOUND)
132 retval = krb5_kt_read_service_key(context, (char *)keytab,
134 ENCTYPE_DES_CBC_MD5, &key);
135 if (retval == KRB5_KT_NOTFOUND)
136 retval = krb5_kt_read_service_key(context, (char *)keytab,
138 ENCTYPE_DES_CBC_MD4, &key);
139 } else if (type == afsconf_rxkad_krb5 || type == afsconf_rxgk) {
140 retval = krb5_kt_read_service_key(context, (char *)keytab, principal,
141 kvno, subtype, &key);
143 retval=AFSCONF_BADKEY;
145 if (retval == KRB5_KT_NOTFOUND) {
146 char * princname = NULL;
148 krb5_unparse_name(context, principal, &princname);
150 if (type == afsconf_rxkad) {
151 afs_com_err("asetkey", retval,
152 "for keytab entry with Principal %s, kvno %u, "
153 "DES-CBC-CRC/MD5/MD4",
154 princname ? princname : princ, kvno);
156 afs_com_err("asetkey", retval,
157 "for keytab entry with Principal %s, kvno %u",
158 princname ? princname : princ, kvno);
164 afs_com_err("asetkey", retval, "while extracting AFS service key");
168 if (type == afsconf_rxkad && deref_key_length(key) != 8) {
169 fprintf(stderr, "Key length should be 8, but is really %u!\n",
170 (unsigned int)deref_key_length(key));
174 rx_opaque_populate(&buffer, deref_key_contents(key), deref_key_length(key));
176 typedKey = afsconf_typedKey_new(type, kvno, subtype, &buffer);
177 rx_opaque_freeContents(&buffer);
178 krb5_free_principal(context, principal);
179 krb5_free_keyblock(context, key);
184 addKey(struct afsconf_dir *dir, int argc, char **argv) {
185 struct afsconf_typedKey *typedKey;
192 typedKey = keyFromCommandLine(afsconf_rxkad, atoi(argv[2]), 0,
196 typedKey = keyFromKeytab(atoi(argv[2]), afsconf_rxkad, 0, argv[3], argv[4]);
199 type = stringToType(argv[2]);
200 kvno = atoi(argv[3]);
201 if (type == afsconf_rxkad) {
202 typedKey = keyFromCommandLine(afsconf_rxkad, kvno, 0, argv[5], 8);
203 } else if (type == afsconf_rxgk || type == afsconf_rxkad_krb5) {
204 typedKey = keyFromCommandLine(type, kvno, atoi(argv[4]), argv[5], strlen(argv[5])/2);
206 fprintf(stderr, "Unknown key type %s\n", argv[2]);
211 type = stringToType(argv[2]);
212 kvno = atoi(argv[3]);
213 if (type == afsconf_rxkad || type == afsconf_rxkad_krb5 || type == afsconf_rxgk) {
214 typedKey = keyFromKeytab(kvno, type, atoi(argv[4]), argv[5],
217 fprintf(stderr, "Unknown key type %s\n", argv[2]);
222 fprintf(stderr, "%s add: usage is '%s add <kvno> <keyfile> "
223 "<princ>\n", argv[0], argv[0]);
224 fprintf(stderr, "\tOR\n\t%s add <kvno> <key>\n", argv[0]);
225 fprintf(stderr, "\tOR\n\t%s add <type> <kvno> <subtype> <key>\n",
227 fprintf(stderr, "\tOR\n\t%s add <type> <kvno> <subtype> <keyfile> <princ>\n",
229 fprintf(stderr, "\t\tEx: %s add 0 \"80b6a7cd7a9dadb6\"\n", argv[0]);
232 code = afsconf_AddTypedKey(dir, typedKey, 1);
233 afsconf_typedKey_put(&typedKey);
235 afs_com_err("asetkey", code, "while adding new key");
240 static struct afsconf_typedKey *
241 random_key(char **argv, int type, int kvno, int subtype)
243 struct afsconf_typedKey *typedKey;
245 krb5_keyblock keyblock;
246 struct rx_opaque key;
249 code = krb5_init_context(&ctx);
251 afs_com_err(argv[0], code, "while initializing krb5 ctx");
255 memset(&keyblock, 0, sizeof(keyblock));
256 code = krb5_c_make_random_key(ctx, subtype, &keyblock);
258 afs_com_err(argv[0], code, "while generating random key");
262 memset(&key, 0, sizeof(key));
263 key.len = keyblock.length;
264 key.val = keyblock.contents;
266 typedKey = afsconf_typedKey_new(type, kvno, subtype, &key);
268 krb5_free_keyblock_contents(ctx, &keyblock);
269 krb5_free_context(ctx);
275 addRandomKey(struct afsconf_dir *dir, int argc, char **argv)
277 struct afsconf_typedKey *typedKey;
283 /* Just pick a reasonable enctype */
284 const int RAND_ENCTYPE = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
286 subtype = RAND_ENCTYPE;
290 subtype = atoi(argv[4]);
293 type = stringToType(argv[2]);
294 kvno = atoi(argv[3]);
296 typedKey = random_key(argv, type, kvno, subtype);
298 code = afsconf_AddTypedKey(dir, typedKey, 1);
299 afsconf_typedKey_put(&typedKey);
301 afs_com_err(argv[0], code, "while adding random key");
305 printf("Added random key with type %d kvno %d subtype %d\n",
306 type, kvno, subtype);
310 fprintf(stderr, "%s add-random: usage is '%s add-random <type> <kvno>\n",
312 fprintf(stderr, "\tOR\n\t%s add-random <type> <kvno> <subtype>\n", argv[0]);
318 deleteKey(struct afsconf_dir *dir, int argc, char **argv)
327 kvno = atoi(argv[2]);
328 code = afsconf_DeleteKey(dir, kvno);
330 afs_com_err(argv[0], code, "while deleting key %d", kvno);
333 printf("Deleted rxkad key %d\n", kvno);
337 type = stringToType(argv[2]);
338 kvno = atoi(argv[3]);
339 code = afsconf_DeleteKeyByType(dir, type, kvno);
341 afs_com_err(argv[0], code, "while deleting key (type %d kvno %d)",
345 printf("Deleted key (type %d kvno %d)\n", type, kvno);
349 type = stringToType(argv[2]);
350 kvno = atoi(argv[3]);
351 subtype = atoi(argv[4]);
352 code = afsconf_DeleteKeyBySubType(dir, type, kvno, subtype);
354 afs_com_err(argv[0], code, "while deleting key (type %d kvno %d subtype %d)\n",
355 type, kvno, subtype);
358 printf("Deleted key (type %d kvno %d subtype %d)\n", type, kvno, subtype);
362 fprintf(stderr, "%s delete: usage is '%s delete <kvno>\n",
364 fprintf(stderr, "\tOR\n\t%s delete <type> <kvno>\n", argv[0]);
365 fprintf(stderr, "\tOR\n\t%s delete <type> <kvno> <subtype>\n", argv[0]);
371 listKey(struct afsconf_dir *dir, int argc, char **argv)
373 struct afsconf_typedKeyList *keys;
377 code = afsconf_GetAllKeys(dir, &keys);
379 afs_com_err("asetkey", code, "while retrieving keys");
382 for (i = 0; i < keys->nkeys; i++) {
383 afsconf_keyType type;
386 struct rx_opaque *keyMaterial;
388 afsconf_typedKey_values(keys->keys[i], &type, &kvno, &minorType,
393 printf("rxkad\tkvno %4d: key is: ", kvno);
394 printKey(keyMaterial);
397 case afsconf_rxkad_krb5:
399 printf("rxkad_krb5\tkvno %4d enctype %d; key is: ",
401 printKey(keyMaterial);
406 printf("rxgk\tkvno %4d enctype %d; key is: ",
408 printKey(keyMaterial);
412 printf("unknown(%d)\tkvno %4d subtype %d; key is: ", type,
414 printKey(keyMaterial);
418 printf("All done.\n");
422 main(int argc, char *argv[])
424 struct afsconf_dir *tdir;
428 fprintf(stderr, "%s: usage is '%s <opcode> options, e.g.\n",
430 fprintf(stderr, "\t%s add <kvno> <keyfile> <princ>\n", argv[0]);
431 fprintf(stderr, "\tOR\n\t%s add <kvno> <key>\n", argv[0]);
432 fprintf(stderr, "\tOR\n\t%s add <type> <kvno> <subtype> <key>\n",
434 fprintf(stderr, "\tOR\n\t%s add <type> <kvno> <subtype> <keyfile> <princ>\n",
436 fprintf(stderr, "\t\tEx: %s add 0 \"80b6a7cd7a9dadb6\"\n", argv[0]);
437 fprintf(stderr, "\t%s add-random <type> <kvno>\n", argv[0]);
438 fprintf(stderr, "\t%s add-random <type> <kvno> <subtype>\n", argv[0]);
439 fprintf(stderr, "\t%s delete <kvno>\n", argv[0]);
440 fprintf(stderr, "\t%s delete <type> <kvno>\n", argv[0]);
441 fprintf(stderr, "\t%s delete <type> <kvno> <subtype>\n", argv[0]);
442 fprintf(stderr, "\t%s list\n", argv[0]);
446 confdir = AFSDIR_SERVER_ETC_DIRPATH;
448 tdir = afsconf_Open(confdir);
450 fprintf(stderr, "%s: can't initialize conf dir '%s'\n", argv[0],
454 if (strcmp(argv[1], "add")==0) {
455 addKey(tdir, argc, argv);
457 else if (strcmp(argv[1], "delete")==0) {
458 deleteKey(tdir, argc, argv);
460 else if (strcmp(argv[1], "list") == 0) {
461 listKey(tdir, argc, argv);
464 else if (strcmp(argv[1], "add-random") == 0) {
465 addRandomKey(tdir, argc, argv);
468 fprintf(stderr, "%s: unknown operation '%s', type '%s' for "
469 "assistance\n", argv[0], argv[1], argv[0]);