[694] in Kerberos-V5-bugs
kdb5_edit can't load dump files with "weird" principals in them
daemon@ATHENA.MIT.EDU (Jonathan I. Kamens)
Thu Sep 1 18:22:27 1994
Date: Thu, 1 Sep 1994 18:23:36 -0400
From: "Jonathan I. Kamens" <jik@cam.ov.com>
To: krb5-bugs@MIT.EDU
kdb5_edit can't load a dump file containing principals with spaces in
their names.
There are two patches below which fix this problem. The first fixes
only this problem. The second fixes this problem and incorporates the
changes I submitted earlier today to make kdb5_edit exit with non-zero
status when there are errors. You pick which one to use :-).
Jonathan Kamens | OpenVision Technologies, Inc. | jik@cam.ov.com
Patch 1:
--- /afs/gza.com/development/krb5.beta4/src/admin/edit/dump.c Thu Jun 9 11:34:00 1994
+++ dump.c Thu Sep 1 18:20:04 1994
@@ -185,6 +185,51 @@
return;
}
+
+/*
+ * Reads a name (actually, any string) of the specified length,
+ * containing any characters, and the character following the string.
+ * Returns a negative number if the specified number of characters
+ * can't be read or if the character following them isn't a tab.
+ *
+ * If successful, adds a null to the end of the string and returns the
+ * number of newlines read into it (usually 0).
+ *
+ * There must be enough space in the passed-in buffer for len
+ * characters followed by a null.
+ */
+int read_name(f, buf, len)
+ FILE *f;
+ char *buf;
+ int len;
+{
+ char *ptr;
+ int c;
+ int newlines = 0;
+
+ for (ptr = buf;
+ (ptr - buf < len) && ((c = fgetc(f)) >= 0);
+ ptr++) {
+ *ptr = c;
+ if (c == '\n')
+ newlines++;
+ }
+
+ if (ptr - buf < len)
+ return -1;
+
+ if ((c = fgetc(f)) < 0)
+ return -1;
+
+ if (c != '\t')
+ return -1;
+
+ *ptr = '\0';
+
+ return newlines;
+}
+
+
void load_db(argc, argv)
int argc;
char **argv;
@@ -196,6 +241,7 @@
int salt_len, alt_salt_len;
int i, one;
char *name, *mod_name;
+ int name_ret;
char *new_dbname;
int ch;
int load_error = 0;
@@ -251,9 +297,9 @@
load_error++;
goto error_out;
}
+ lineno++;
for (;;) {
int nitems;
- unsigned int stop_loop = 0;
lineno++;
memset((char *)&entry, 0, sizeof(entry));
@@ -271,7 +317,6 @@
com_err(argv[0], errno,
"While allocating space for name");
load_error++;
- stop_loop++;
goto cleanup;
}
if (!(mod_name = malloc(mod_name_len+1))) {
@@ -278,7 +323,6 @@
com_err(argv[0], errno,
"While allocating space for mod_name");
load_error++;
- stop_loop++;
goto cleanup;
}
entry.key.length = key_len;
@@ -288,7 +332,6 @@
com_err(argv[0], errno,
"While allocating space for the key");
load_error++;
- stop_loop++;
goto cleanup;
}
}
@@ -299,7 +342,6 @@
com_err(argv[0], errno,
"While allocating space for alt_key");
load_error++;
- stop_loop++;
goto cleanup;
}
}
@@ -309,7 +351,6 @@
com_err(argv[0], errno,
"While allocating space for the salt");
load_error++;
- stop_loop++;
goto cleanup;
}
}
@@ -320,15 +361,20 @@
com_err(argv[0], errno,
"While allocating space for the alt_salt");
load_error++;
- stop_loop++;
goto cleanup;
}
}
- if (fscanf(f, "%s\t%d\t", name, &tmp1) != 2) {
+ if ((name_ret = read_name(f, name, name_len)) < 0) {
fprintf(stderr, "Couldn't parse line #%d\n", lineno);
load_error++;
break;
}
+ lineno += name_ret;
+ if (fscanf(f, "%d\t", &tmp1) != 1) {
+ fprintf(stderr, "Couldn't parse line #%d\n", lineno);
+ load_error++;
+ break;
+ }
/* keytype is probably a short, but might not be.
To avoid problems with scanf, read into a variable of
known type then copy the value. */
@@ -342,16 +388,25 @@
}
entry.key.contents[i] = tmp1;
}
- if (fscanf(f,
- "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%s\t%u\t%u\t%u\t",
+ if (fscanf(f, "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
&tmp1, &entry.max_life, &entry.max_renewable_life,
&tmp2, &entry.expiration, &entry.pw_expiration,
&entry.last_pwd_change, &entry.last_success,
- &entry.last_failed, &entry.fail_auth_count,
- mod_name, &entry.mod_date,
- &entry.attributes, &stype) != 14) {
+ &entry.last_failed, &entry.fail_auth_count) != 10) {
fprintf(stderr, "Couldn't parse line #%d\n",
lineno);
+ load_error++;
+ break;
+ }
+ if ((name_ret = read_name(f, mod_name, mod_name_len)) < 0) {
+ fprintf(stderr, "Couldn't parse line #%d\n", lineno);
+ load_error++;
+ break;
+ }
+ lineno += name_ret;
+ if (fscanf(f, "%u\t%u\t%u\t",
+ &entry.mod_date, &entry.attributes, &stype) != 3) {
+ fprintf(stderr, "Couldn't parse line #%d\n", lineno);
load_error++;
break;
}
Patch 2:
--- /afs/gza.com/development/krb5.beta4/src/admin/edit/dump.c Thu Jun 9 11:34:00 1994
+++ dump.c Thu Sep 1 18:18:30 1994
@@ -55,6 +55,7 @@
krb5_encrypt_block master_encblock;
extern char *current_dbname;
extern krb5_boolean dbactive;
+extern int exit_status;
void update_ok_file();
@@ -70,11 +71,13 @@
if (retval = krb5_unparse_name(entry->principal, &name)) {
com_err(arg->comerr_name, retval, "while unparsing principal");
+ exit_status++;
return retval;
}
if (retval = krb5_unparse_name(entry->mod_name, &mod_name)) {
free(name);
com_err(arg->comerr_name, retval, "while unparsing principal");
+ exit_status++;
return retval;
}
fprintf(arg->f, "%d\t%d\t%d\t%d\t%d\t%d\t%s\t%d\t", strlen(name),
@@ -121,10 +124,12 @@
if (argc > 2) {
com_err(argv[0], 0, "Usage: %s filename", argv[0]);
+ exit_status++;
return;
}
if (!dbactive) {
com_err(argv[0], 0, Err_no_database);
+ exit_status++;
return;
}
if (argc == 2) {
@@ -142,6 +147,7 @@
if (!(f = fopen(argv[1], "w"))) {
com_err(argv[0], errno,
"While opening file %s for writing", argv[1]);
+ exit_status++;
return;
}
} else {
@@ -170,6 +176,7 @@
== NULL) {
com_err(progname, ENOMEM,
"while allocating filename for update_ok_file");
+ exit_status++;
return;
}
strcpy(file_ok, file_name);
@@ -177,6 +184,7 @@
if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
com_err(progname, errno, "while creating 'ok' file, '%s'",
file_ok);
+ exit_status++;
free(file_ok);
return;
}
@@ -185,6 +193,51 @@
return;
}
+
+/*
+ * Reads a name (actually, any string) of the specified length,
+ * containing any characters, and the character following the string.
+ * Returns a negative number if the specified number of characters
+ * can't be read or if the character following them isn't a tab.
+ *
+ * If successful, adds a null to the end of the string and returns the
+ * number of newlines read into it (usually 0).
+ *
+ * There must be enough space in the passed-in buffer for len
+ * characters followed by a null.
+ */
+int read_name(f, buf, len)
+ FILE *f;
+ char *buf;
+ int len;
+{
+ char *ptr;
+ int c;
+ int newlines = 0;
+
+ for (ptr = buf;
+ (ptr - buf < len) && ((c = fgetc(f)) >= 0);
+ ptr++) {
+ *ptr = c;
+ if (c == '\n')
+ newlines++;
+ }
+
+ if (ptr - buf < len)
+ return -1;
+
+ if ((c = fgetc(f)) < 0)
+ return -1;
+
+ if (c != '\t')
+ return -1;
+
+ *ptr = '\0';
+
+ return newlines;
+}
+
+
void load_db(argc, argv)
int argc;
char **argv;
@@ -196,6 +249,7 @@
int salt_len, alt_salt_len;
int i, one;
char *name, *mod_name;
+ int name_ret;
char *new_dbname;
int ch;
int load_error = 0;
@@ -206,10 +260,12 @@
if (argc != 3) {
com_err(argv[0], 0, "Usage: %s filename dbname", argv[0]);
+ exit_status++;
return;
}
if (!(new_dbname = malloc(strlen(argv[2])+2))) {
com_err(argv[0], 0, "No room to allocate new database name!");
+ exit_status++;
return;
}
strcpy(new_dbname, argv[2]);
@@ -217,6 +273,7 @@
if (retval = krb5_db_create(new_dbname)) {
com_err(argv[0], retval, "while creating database '%s'",
new_dbname);
+ exit_status++;
return;
}
if (dbactive) {
@@ -224,6 +281,7 @@
retval != KRB5_KDB_DBNOTINITED) {
com_err(argv[0], retval,
"while closing previous database");
+ exit_status++;
return;
}
}
@@ -243,6 +301,7 @@
if (!(f = fopen(argv[1], "r"))) {
com_err(argv[0], errno,
"While opening file %s for writing", argv[1]);
+ exit_status++;
return;
}
fgets(buf, sizeof(buf), f);
@@ -251,9 +310,9 @@
load_error++;
goto error_out;
}
+ lineno++;
for (;;) {
int nitems;
- unsigned int stop_loop = 0;
lineno++;
memset((char *)&entry, 0, sizeof(entry));
@@ -271,7 +330,6 @@
com_err(argv[0], errno,
"While allocating space for name");
load_error++;
- stop_loop++;
goto cleanup;
}
if (!(mod_name = malloc(mod_name_len+1))) {
@@ -278,7 +336,6 @@
com_err(argv[0], errno,
"While allocating space for mod_name");
load_error++;
- stop_loop++;
goto cleanup;
}
entry.key.length = key_len;
@@ -288,7 +345,6 @@
com_err(argv[0], errno,
"While allocating space for the key");
load_error++;
- stop_loop++;
goto cleanup;
}
}
@@ -299,7 +355,6 @@
com_err(argv[0], errno,
"While allocating space for alt_key");
load_error++;
- stop_loop++;
goto cleanup;
}
}
@@ -309,7 +364,6 @@
com_err(argv[0], errno,
"While allocating space for the salt");
load_error++;
- stop_loop++;
goto cleanup;
}
}
@@ -320,15 +374,20 @@
com_err(argv[0], errno,
"While allocating space for the alt_salt");
load_error++;
- stop_loop++;
goto cleanup;
}
}
- if (fscanf(f, "%s\t%d\t", name, &tmp1) != 2) {
+ if ((name_ret = read_name(f, name, name_len)) < 0) {
fprintf(stderr, "Couldn't parse line #%d\n", lineno);
load_error++;
break;
}
+ lineno += name_ret;
+ if (fscanf(f, "%d\t", &tmp1) != 1) {
+ fprintf(stderr, "Couldn't parse line #%d\n", lineno);
+ load_error++;
+ break;
+ }
/* keytype is probably a short, but might not be.
To avoid problems with scanf, read into a variable of
known type then copy the value. */
@@ -342,19 +401,28 @@
}
entry.key.contents[i] = tmp1;
}
- if (fscanf(f,
- "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%s\t%u\t%u\t%u\t",
+ if (fscanf(f, "\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
&tmp1, &entry.max_life, &entry.max_renewable_life,
&tmp2, &entry.expiration, &entry.pw_expiration,
&entry.last_pwd_change, &entry.last_success,
- &entry.last_failed, &entry.fail_auth_count,
- mod_name, &entry.mod_date,
- &entry.attributes, &stype) != 14) {
+ &entry.last_failed, &entry.fail_auth_count) != 10) {
fprintf(stderr, "Couldn't parse line #%d\n",
lineno);
load_error++;
break;
}
+ if ((name_ret = read_name(f, mod_name, mod_name_len)) < 0) {
+ fprintf(stderr, "Couldn't parse line #%d\n", lineno);
+ load_error++;
+ break;
+ }
+ lineno += name_ret;
+ if (fscanf(f, "%u\t%u\t%u\t",
+ &entry.mod_date, &entry.attributes, &stype) != 3) {
+ fprintf(stderr, "Couldn't parse line #%d\n", lineno);
+ load_error++;
+ break;
+ }
entry.kvno = tmp1;
entry.mkvno = tmp2;
entry.salt_type = stype;
@@ -452,6 +520,7 @@
}
if (load_error) {
printf("Error while loading database, aborting load.\n");
+ exit_status += load_error;
if (retval = kdb5_db_destroy(new_dbname)) {
com_err(argv[0], retval,
"while destroying temporary database '%s'",