diff --git a/admin/Makefile.am b/admin/Makefile.am index 20b85c791..d17d330d1 100644 --- a/admin/Makefile.am +++ b/admin/Makefile.am @@ -2,9 +2,11 @@ AUTOHEADER_FLAGS = no-dependencies -INCLUDES = -I$(top_builddir)/include +INCLUDES = -I$(top_builddir)/include -I/usr/athena/include -bin_PROGRAMS = load dump ank extkeytab +bin_PROGRAMS = kdb_edit -LDADD = -L$(top_builddir)/lib/hdb -lhdb -L$(top_builddir)/lib/krb5 -lkrb5 -L$(top_builddir)/lib/des -ldes -L$(top_builddir)/lib/asn1 -lasn1 +kdb_edit_SOURCES = kdb_edit.c load.c ank.c dump.c init.c get.c delete.c + +LDADD = -L$(top_builddir)/lib/hdb -lhdb -L$(top_builddir)/lib/krb5 -lkrb5 -L$(top_builddir)/lib/des -ldes -L$(top_builddir)/lib/asn1 -lasn1 -L/usr/athena/lib -lsl -leditline -ledit -ltermcap diff --git a/admin/admin_locl.h b/admin/admin_locl.h index 8c1b9ff0f..bd36ef97f 100644 --- a/admin/admin_locl.h +++ b/admin/admin_locl.h @@ -21,5 +21,20 @@ #include "hdb.h" +extern krb5_context context; +extern char *database; + +#define DECL(X) void X(int, char **) + +DECL(get_entry); +DECL(load); +DECL(merge); +DECL(add_new_key); +DECL(mod_entry); +DECL(dump); +DECL(init); +DECL(get_entry); +DECL(del_entry); +DECL(help); #endif /* __ADMIN_LOCL_H__ */ diff --git a/admin/ank.c b/admin/ank.c index 3c4404818..2780b4bd4 100644 --- a/admin/ank.c +++ b/admin/ank.c @@ -2,67 +2,118 @@ RCSID("$Id$"); -int main(int argc, char **argv) +static void +doit(char *principal, int mod) { HDB *db; - krb5_context context; int err; - hdb_entry ent; + hdb_entry def; + int32_t tmp; + char buf[1024]; - krb5_init_context(&context); - while (1){ - int32_t tmp; - char buf[1024]; - - printf("Principal: "); - fgets(buf, sizeof(buf), stdin); - if(buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = 0; - if(buf[0] == 0) - break; - krb5_parse_name(context, buf, &ent.principal); - - hdb_open(context, &db, argv[1], O_RDWR, 0600); - - err = db->fetch(context, db, &ent); - - switch(err){ - case KRB5_HDB_NOENTRY: - ent.kvno = 0; - ent.max_life = 86400; - ent.max_renew = 5 * 86400; - break; - case 0: - break; - default: - fprintf(stderr, "dbget: %s\n", krb5_get_err_text(context, err));; - exit(1); - } - printf("Max ticket life [%d]: ", ent.max_life); - fgets(buf, sizeof(buf), stdin); - if(sscanf(buf, "%d", &tmp) == 1) - ent.max_life = tmp; - printf("Max renewable ticket [%d]: ", ent.max_renew); - fgets(buf, sizeof(buf), stdin); - if(sscanf(buf, "%d", &tmp) == 1) - ent.max_renew = tmp; - des_read_pw_string(buf, sizeof(buf), "Password:", 1); - { - krb5_data salt; - memset(&salt, 0, sizeof(salt)); - krb5_get_salt(ent.principal, &salt); - krb5_string_to_key(buf, &salt, &ent.keyblock); - } - ent.kvno++; - { - err = db->store(context, db, &ent); - if(err == -1){ - perror("dbput"); - exit(1); - } - } - db->close(context, db); + krb5_parse_name(context, principal, &ent.principal); + + if((err = hdb_open(context, &db, database, O_RDWR, 0600))){ + fprintf(stderr, "hdb_open: %s\n", krb5_get_err_text(context, err)); + return; } - return 0; + + err = db->fetch(context, db, &ent); + + switch(err){ + case KRB5_HDB_NOENTRY: + if(mod){ + fprintf(stderr, "Entry not found in database\n"); + return; + }else{ + krb5_data *realm; + + realm = krb5_princ_realm(context, ent.principal); + krb5_build_principal(context, &def.principal, + realm->length, + realm->data, + "default", + NULL); + if(db->fetch(context, db, &def)){ + /* XXX */ + } + ent.kvno = 0; + ent.max_life = def.max_life; + ent.max_renew = def.max_renew; + ent.expires = def.expires; + if(ent.expires) + ent.expires += time(NULL); + break; + } + case 0: + if(!mod){ + warnx("Principal exists"); + return; + } + break; + default: + errx(1, "dbget: %s", krb5_get_err_text(context, err)); + } + printf("Max ticket life [%d]: ", ent.max_life); + fgets(buf, sizeof(buf), stdin); + if(sscanf(buf, "%d", &tmp) == 1) + ent.max_life = tmp; + printf("Max renewable ticket [%d]: ", ent.max_renew); + fgets(buf, sizeof(buf), stdin); + if(sscanf(buf, "%d", &tmp) == 1) + ent.max_renew = tmp; + while(mod){ + fprintf(stderr, "Change password? (y/n) "); + fgets(buf, sizeof(buf), stdin); + if(buf[0] != 'n' || buf[0] != 'y'){ + fprintf(stderr, "Please answer yes or no.\n"); + continue; + } + } + if(mod == 0 || buf[0] == 'y'){ + krb5_data salt; + des_read_pw_string(buf, sizeof(buf), "Password:", 1); + memset(&salt, 0, sizeof(salt)); + krb5_get_salt(ent.principal, &salt); + memset(&ent.keyblock, 0, sizeof(ent.keyblock)); + krb5_string_to_key(buf, &salt, &ent.keyblock); + ent.kvno++; + } + ent.last_change = time(NULL); + krb5_build_principal(context, &ent.changed_by, + krb5_princ_realm(context, ent.principal)->length, + krb5_princ_realm(context, ent.principal)->data, + "kadmin", + NULL); + err = db->store(context, db, &ent); + if(err == -1){ + perror("dbput"); + exit(1); + } + hdb_free_entry(context, &ent); + db->close(context, db); +} + + +void +add_new_key(int argc, char **argv) +{ + if(argc != 2){ + fprintf(stderr, "Usage: add_new_key principal\n"); + return; + } + + doit(argv[1], 0); +} + +void +mod_entry(int argc, char **argv) +{ + if(argc != 2){ + fprintf(stderr, "Usage: mod_entry principal\n"); + return; + } + + doit(argv[1], 1); } diff --git a/admin/delete.c b/admin/delete.c new file mode 100644 index 000000000..02ca41634 --- /dev/null +++ b/admin/delete.c @@ -0,0 +1,35 @@ +#include "admin_locl.h" + +RCSID("$Id$"); + +void +del_entry(int argc, char **argv) +{ + HDB *db; + int err; + hdb_entry ent; + + if(argc != 2){ + warnx("Usage: del_entry principal"); + return; + } + + krb5_parse_name(context, argv[1], &ent.principal); + + if((err = hdb_open(context, &db, database, O_RDWR, 0600))){ + warnx("hdb_open: %s", krb5_get_err_text(context, err)); + return; + } + + err = db->delete(context, db, &ent); + + switch(err){ + case 0: + break; + default: + warnx("delete: %s", krb5_get_err_text(context, err));; + break; + } + memset(&ent, 0, sizeof(ent)); + db->close(context, db); +} diff --git a/admin/dump.c b/admin/dump.c index f876da4fc..9be0c2f48 100644 --- a/admin/dump.c +++ b/admin/dump.c @@ -2,32 +2,73 @@ RCSID("$Id$"); -int main(int argc, char **argv) +char * +time2str(time_t t) +{ + static char s[32]; + struct tm *tm; + tm = gmtime(&t); + strftime(s, sizeof(s), "%Y%m%d%H%M%S", tm); + return s; +} + +char * +key2str(krb5_keyblock *key) +{ + static char *s; + unsigned char *p; + int i; + if(s) + free(s); + s = malloc(key->contents.length/2+10); + sprintf(s, "%d:", key->keytype); + p = (unsigned char*)key->contents.data; + for(i = 0; i < key->contents.length; i++) + sprintf(s + strlen(s), "%02x", p[i]); + return s; +} + +void +dump(int argc, char **argv) { HDB *db; hdb_entry ent; - krb5_context context; int err; int i; + FILE *f; - char *p; + if(argc < 2) + f = stdout; + else + f = fopen(argv[1], "w"); - - krb5_init_context(&context); - err = hdb_open(context, &db, argv[1], O_RDONLY, 0600); + + err = hdb_open(context, &db, database, O_RDONLY, 0600); if(err){ - fprintf(stderr, "%s\n", krb5_get_err_text(context, err)); - exit(1); + warnx("hdb_open: %s", krb5_get_err_text(context, err)); + if(f != stdout) + fclose(f); + return; } err = db->firstkey(context, db, &ent); while(err == 0){ + char *p; krb5_unparse_name(context, ent.principal, &p); - printf("%s ", p); - for(i = 0; i < ent.keyblock.contents.length; i++) - printf("%02x", (int)((unsigned char*)ent.keyblock.contents.data)[i]); - printf(" "); - printf("%d %d %d\n", ent.kvno, ent.max_life, ent.max_renew); + fprintf(f, "%s ", p); + free(p); + fprintf(f, "%d:%s", ent.kvno, key2str(&ent.keyblock)); + fprintf(f, " %d %d %s", + ent.max_life, + ent.max_renew, + time2str(ent.last_change)); + krb5_unparse_name(context, ent.changed_by, &p); + fprintf(f, " %s %s %d\n", + p, + time2str(ent.expires), + ent.u.flags); free(p); err = db->nextkey(context, db, &ent); } + if(f != stdout) + fclose(f); } diff --git a/admin/get.c b/admin/get.c new file mode 100644 index 000000000..c8bae4875 --- /dev/null +++ b/admin/get.c @@ -0,0 +1,51 @@ +#include "admin_locl.h" + +RCSID("$Id$"); + +void +get_entry(int argc, char **argv) +{ + HDB *db; + int err; + hdb_entry ent; + + if(argc != 2){ + fprintf(stderr, "Usage: get_entry principal\n"); + return; + } + + krb5_parse_name(context, argv[1], &ent.principal); + + if((err = hdb_open(context, &db, database, O_RDONLY, 0600))){ + fprintf(stderr, "hdb_open: %s\n", krb5_get_err_text(context, err)); + return; + } + + err = db->fetch(context, db, &ent); + + switch(err){ + case KRB5_HDB_NOENTRY: + fprintf(stderr, "Entry not found in database\n"); + break; + case 0: { + char *name; + krb5_unparse_name(context, ent.principal, &name); + printf("Principal: %s\n", name); + free(name); + printf("Max ticket life: %d\n", ent.max_life); + printf("Max renewable ticket life: %d\n", ent.max_renew); + printf("Key type: "); + if(ent.keyblock.keytype == KEYTYPE_DES) + printf("DES"); + else + printf("%d", (int)ent.keyblock.keytype); + printf("\tKvno: %d\n", ent.kvno); + break; + } + default: + fprintf(stderr, "dbget: %s\n", krb5_get_err_text(context, err));; + break; + } + memset(&ent, 0, sizeof(ent)); + db->close(context, db); +} diff --git a/admin/init.c b/admin/init.c new file mode 100644 index 000000000..55efb8f94 --- /dev/null +++ b/admin/init.c @@ -0,0 +1,125 @@ +#include "admin_locl.h" + +RCSID("$Id$"); + +time_t +get_time(const char *prompt, time_t def) +{ + char buf[1024]; + int tmp; + + while(1){ + if(def == 0) + printf("%s: [infinite] ", prompt); + else + printf("%s: [%d] ", prompt, def); + fgets(buf, sizeof(buf), stdin); + if(buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = 0; + if(buf[0] == 0) + return def; + if(strncmp(buf, "infinite", strlen(buf)) == 0) + return 0; + if(sscanf(buf, "%d", &tmp) == 1) + return tmp; + printf("Please specify a number\n"); + } +} + + +void +init(int argc, char **argv) +{ + HDB *db; + char s[1024]; + char *p; + int line; + int err; + int i; + + int tmp; + int default_life = 86400; + int default_renew = 5 * 86400; + int max_life = 0; + int max_renew = 0; + + hdb_entry ent; + + err = hdb_open(context, &db, database, O_RDWR | O_CREAT, 0600); + if(err){ + warnx("hdb_open: %s", krb5_get_err_text(context, err)); + return; + } + memset(&ent, 0, sizeof(ent)); + for(i = 1; i < argc; i++){ + krb5_build_principal(context, &ent.principal, + strlen(argv[i]), argv[i], + "krbtgt", + argv[i], + NULL); + err = db->fetch(context, db, &ent); + switch(err){ + case 0: + fprintf(stderr, "Entry already exists\n"); + krb5_free_principal(context, ent.principal); + continue; + case KRB5_HDB_NOENTRY: + break; + default: + warnx("hdb_fetch: %s", krb5_get_err_text(context, err)); + db->close(context, db); + return; + } + + max_life = get_time("Realm max ticket life", max_life); + max_renew = get_time("Realm max renewable ticket life", max_renew); + default_life = get_time("Default ticket life", default_life); + default_renew = get_time("Default renewable ticket life", + default_renew); + + + /* Create `krbtgt/REALM' */ + ent.keyblock.keytype = KEYTYPE_DES; + ent.keyblock.contents.length = 8; + ent.keyblock.contents.data = malloc(ent.keyblock.contents.length); + des_rand_data(ent.keyblock.contents.data, + ent.keyblock.contents.length); + ent.kvno = 1; + ent.max_life = max_life; + ent.max_renew = max_renew; + ent.last_change = time(NULL); + krb5_build_principal(context, &ent.changed_by, + strlen(argv[i]), argv[i], + "kadmin", + NULL); + ent.expires = 0; + ent.u.s.forwardable = 1; + ent.u.s.renewable = 1; + ent.u.s.server = 1; + db->store(context, db, &ent); + hdb_free_entry(context, &ent); + + /* Create `default' */ + memset(&ent, 0, sizeof(ent)); + krb5_build_principal(context, &ent.principal, + strlen(argv[i]), argv[i], + "default", + NULL); + ent.keyblock.keytype = KEYTYPE_DES; + ent.keyblock.contents.length = 0; + ent.keyblock.contents.data = NULL; + ent.kvno = 1; + ent.max_life = default_life; + ent.max_renew = default_renew; + ent.last_change = time(NULL); + krb5_build_principal(context, &ent.changed_by, + strlen(argv[i]), argv[i], + "kadmin", + NULL); + ent.expires = 0; + ent.u.s.locked = 1; + db->store(context, db, &ent); + hdb_free_entry(context, &ent); + } + db->close(context, db); +} diff --git a/admin/kdb_edit.c b/admin/kdb_edit.c new file mode 100644 index 000000000..c98832bac --- /dev/null +++ b/admin/kdb_edit.c @@ -0,0 +1,35 @@ +#include "admin_locl.h" +#include + +static SL_cmd commands[] = { + { "add_new_key", add_new_key, "add_new_key principal", "" }, + { "ank", NULL, NULL, NULL }, + { "modify_entry", mod_entry, "modify_entry principal", "" }, + { "dump", dump, "dump [file]", "" }, + { "load", load, "load file", "" }, + { "merge", merge, "merge file", "" }, + { "help", help, "help", "" }, + { "?", NULL, NULL, NULL }, + { "init", init, "init realm...", "" }, + { "get_entry", get_entry, "get_entry principal","" }, + { "delete", del_entry, "delete principal", "" }, + { NULL, NULL, NULL, NULL } +}; + +krb5_context context; +char *database = HDB_DEFAULT_DB; + +void +help(int argc, char **argv) +{ + sl_help(commands, argc, argv); +} + +int +main(int argc, char **argv) +{ + + krb5_init_context(&context); + sl_loop(commands, "kdb_edit> "); + return 0; +} diff --git a/admin/load.c b/admin/load.c index 70a81d910..3e888dcb6 100644 --- a/admin/load.c +++ b/admin/load.c @@ -10,27 +10,33 @@ struct entry{ char *max_renew; }; -int main(int argc, char **argv) +static void +doit(char *filename, int merge) { FILE *f; HDB *db; - krb5_context context; char s[1024]; char *p; int line; int err; int i; + int flags = O_RDWR; struct entry e; hdb_entry ent; - - krb5_init_context(&context); - f = fopen(argv[1], "r"); - err = hdb_open(context, &db, argv[2], O_RDWR | O_CREAT | O_TRUNC, 0600); + f = fopen(filename, "r"); + if(f == NULL){ + fprintf(stderr, "%s: %s\n", filename, strerror(errno)); + return; + } + if(!merge) + flags |= O_CREAT | O_TRUNC; + err = hdb_open(context, &db, database, flags, 0600); if(err){ fprintf(stderr, "hdb_open: %s\n", krb5_get_err_text(context, err)); - exit(1); + fclose(f); + return; } line = 0; while(fgets(s, sizeof(s), f)){ @@ -70,7 +76,7 @@ int main(int argc, char **argv) err = krb5_parse_name(context, e.principal, &ent.principal); if(err){ fprintf(stderr, "%s:%s:%s (%s)\n", - argv[1], + filename, line, krb5_get_err_text(context, err), e.principal); @@ -79,7 +85,7 @@ int main(int argc, char **argv) ent.keyblock.keytype = KEYTYPE_DES; ent.keyblock.contents.data = malloc(strlen(e.key)/2+1); - for(i = 0; i < strlen(e.key); i += 2){ + for(i = 1; i < strlen(e.key) - 1; i += 2){ unsigned tmp; sscanf(e.key + i, "%2x", &tmp); ((unsigned char *)ent.keyblock.contents.data)[i/2] = tmp; @@ -91,4 +97,25 @@ int main(int argc, char **argv) db->store(context, db, &ent); } db->close(context, db); + fclose(f); +} + +void +load(int argc, char **argv) +{ + if(argc < 2){ + fprintf(stderr, "Usage: load filename\n"); + return; + } + doit(argv[1], 0); +} + +void +merge(int argc, char **argv) +{ + if(argc < 2){ + fprintf(stderr, "Usage: merge filename\n"); + return; + } + doit(argv[1], 1); } diff --git a/kadmin/dump.c b/kadmin/dump.c index f876da4fc..9be0c2f48 100644 --- a/kadmin/dump.c +++ b/kadmin/dump.c @@ -2,32 +2,73 @@ RCSID("$Id$"); -int main(int argc, char **argv) +char * +time2str(time_t t) +{ + static char s[32]; + struct tm *tm; + tm = gmtime(&t); + strftime(s, sizeof(s), "%Y%m%d%H%M%S", tm); + return s; +} + +char * +key2str(krb5_keyblock *key) +{ + static char *s; + unsigned char *p; + int i; + if(s) + free(s); + s = malloc(key->contents.length/2+10); + sprintf(s, "%d:", key->keytype); + p = (unsigned char*)key->contents.data; + for(i = 0; i < key->contents.length; i++) + sprintf(s + strlen(s), "%02x", p[i]); + return s; +} + +void +dump(int argc, char **argv) { HDB *db; hdb_entry ent; - krb5_context context; int err; int i; + FILE *f; - char *p; + if(argc < 2) + f = stdout; + else + f = fopen(argv[1], "w"); - - krb5_init_context(&context); - err = hdb_open(context, &db, argv[1], O_RDONLY, 0600); + + err = hdb_open(context, &db, database, O_RDONLY, 0600); if(err){ - fprintf(stderr, "%s\n", krb5_get_err_text(context, err)); - exit(1); + warnx("hdb_open: %s", krb5_get_err_text(context, err)); + if(f != stdout) + fclose(f); + return; } err = db->firstkey(context, db, &ent); while(err == 0){ + char *p; krb5_unparse_name(context, ent.principal, &p); - printf("%s ", p); - for(i = 0; i < ent.keyblock.contents.length; i++) - printf("%02x", (int)((unsigned char*)ent.keyblock.contents.data)[i]); - printf(" "); - printf("%d %d %d\n", ent.kvno, ent.max_life, ent.max_renew); + fprintf(f, "%s ", p); + free(p); + fprintf(f, "%d:%s", ent.kvno, key2str(&ent.keyblock)); + fprintf(f, " %d %d %s", + ent.max_life, + ent.max_renew, + time2str(ent.last_change)); + krb5_unparse_name(context, ent.changed_by, &p); + fprintf(f, " %s %s %d\n", + p, + time2str(ent.expires), + ent.u.flags); free(p); err = db->nextkey(context, db, &ent); } + if(f != stdout) + fclose(f); } diff --git a/kadmin/init.c b/kadmin/init.c new file mode 100644 index 000000000..55efb8f94 --- /dev/null +++ b/kadmin/init.c @@ -0,0 +1,125 @@ +#include "admin_locl.h" + +RCSID("$Id$"); + +time_t +get_time(const char *prompt, time_t def) +{ + char buf[1024]; + int tmp; + + while(1){ + if(def == 0) + printf("%s: [infinite] ", prompt); + else + printf("%s: [%d] ", prompt, def); + fgets(buf, sizeof(buf), stdin); + if(buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = 0; + if(buf[0] == 0) + return def; + if(strncmp(buf, "infinite", strlen(buf)) == 0) + return 0; + if(sscanf(buf, "%d", &tmp) == 1) + return tmp; + printf("Please specify a number\n"); + } +} + + +void +init(int argc, char **argv) +{ + HDB *db; + char s[1024]; + char *p; + int line; + int err; + int i; + + int tmp; + int default_life = 86400; + int default_renew = 5 * 86400; + int max_life = 0; + int max_renew = 0; + + hdb_entry ent; + + err = hdb_open(context, &db, database, O_RDWR | O_CREAT, 0600); + if(err){ + warnx("hdb_open: %s", krb5_get_err_text(context, err)); + return; + } + memset(&ent, 0, sizeof(ent)); + for(i = 1; i < argc; i++){ + krb5_build_principal(context, &ent.principal, + strlen(argv[i]), argv[i], + "krbtgt", + argv[i], + NULL); + err = db->fetch(context, db, &ent); + switch(err){ + case 0: + fprintf(stderr, "Entry already exists\n"); + krb5_free_principal(context, ent.principal); + continue; + case KRB5_HDB_NOENTRY: + break; + default: + warnx("hdb_fetch: %s", krb5_get_err_text(context, err)); + db->close(context, db); + return; + } + + max_life = get_time("Realm max ticket life", max_life); + max_renew = get_time("Realm max renewable ticket life", max_renew); + default_life = get_time("Default ticket life", default_life); + default_renew = get_time("Default renewable ticket life", + default_renew); + + + /* Create `krbtgt/REALM' */ + ent.keyblock.keytype = KEYTYPE_DES; + ent.keyblock.contents.length = 8; + ent.keyblock.contents.data = malloc(ent.keyblock.contents.length); + des_rand_data(ent.keyblock.contents.data, + ent.keyblock.contents.length); + ent.kvno = 1; + ent.max_life = max_life; + ent.max_renew = max_renew; + ent.last_change = time(NULL); + krb5_build_principal(context, &ent.changed_by, + strlen(argv[i]), argv[i], + "kadmin", + NULL); + ent.expires = 0; + ent.u.s.forwardable = 1; + ent.u.s.renewable = 1; + ent.u.s.server = 1; + db->store(context, db, &ent); + hdb_free_entry(context, &ent); + + /* Create `default' */ + memset(&ent, 0, sizeof(ent)); + krb5_build_principal(context, &ent.principal, + strlen(argv[i]), argv[i], + "default", + NULL); + ent.keyblock.keytype = KEYTYPE_DES; + ent.keyblock.contents.length = 0; + ent.keyblock.contents.data = NULL; + ent.kvno = 1; + ent.max_life = default_life; + ent.max_renew = default_renew; + ent.last_change = time(NULL); + krb5_build_principal(context, &ent.changed_by, + strlen(argv[i]), argv[i], + "kadmin", + NULL); + ent.expires = 0; + ent.u.s.locked = 1; + db->store(context, db, &ent); + hdb_free_entry(context, &ent); + } + db->close(context, db); +} diff --git a/kadmin/load.c b/kadmin/load.c index 70a81d910..3e888dcb6 100644 --- a/kadmin/load.c +++ b/kadmin/load.c @@ -10,27 +10,33 @@ struct entry{ char *max_renew; }; -int main(int argc, char **argv) +static void +doit(char *filename, int merge) { FILE *f; HDB *db; - krb5_context context; char s[1024]; char *p; int line; int err; int i; + int flags = O_RDWR; struct entry e; hdb_entry ent; - - krb5_init_context(&context); - f = fopen(argv[1], "r"); - err = hdb_open(context, &db, argv[2], O_RDWR | O_CREAT | O_TRUNC, 0600); + f = fopen(filename, "r"); + if(f == NULL){ + fprintf(stderr, "%s: %s\n", filename, strerror(errno)); + return; + } + if(!merge) + flags |= O_CREAT | O_TRUNC; + err = hdb_open(context, &db, database, flags, 0600); if(err){ fprintf(stderr, "hdb_open: %s\n", krb5_get_err_text(context, err)); - exit(1); + fclose(f); + return; } line = 0; while(fgets(s, sizeof(s), f)){ @@ -70,7 +76,7 @@ int main(int argc, char **argv) err = krb5_parse_name(context, e.principal, &ent.principal); if(err){ fprintf(stderr, "%s:%s:%s (%s)\n", - argv[1], + filename, line, krb5_get_err_text(context, err), e.principal); @@ -79,7 +85,7 @@ int main(int argc, char **argv) ent.keyblock.keytype = KEYTYPE_DES; ent.keyblock.contents.data = malloc(strlen(e.key)/2+1); - for(i = 0; i < strlen(e.key); i += 2){ + for(i = 1; i < strlen(e.key) - 1; i += 2){ unsigned tmp; sscanf(e.key + i, "%2x", &tmp); ((unsigned char *)ent.keyblock.contents.data)[i/2] = tmp; @@ -91,4 +97,25 @@ int main(int argc, char **argv) db->store(context, db, &ent); } db->close(context, db); + fclose(f); +} + +void +load(int argc, char **argv) +{ + if(argc < 2){ + fprintf(stderr, "Usage: load filename\n"); + return; + } + doit(argv[1], 0); +} + +void +merge(int argc, char **argv) +{ + if(argc < 2){ + fprintf(stderr, "Usage: merge filename\n"); + return; + } + doit(argv[1], 1); }