aboutsummaryrefslogtreecommitdiff
path: root/crypto/heimdal/kdc/mit_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/kdc/mit_dump.c')
-rw-r--r--crypto/heimdal/kdc/mit_dump.c383
1 files changed, 88 insertions, 295 deletions
diff --git a/crypto/heimdal/kdc/mit_dump.c b/crypto/heimdal/kdc/mit_dump.c
index f28e932b15b4..4397d1ad897d 100644
--- a/crypto/heimdal/kdc/mit_dump.c
+++ b/crypto/heimdal/kdc/mit_dump.c
@@ -33,6 +33,17 @@
#include "hprop.h"
+extern krb5_error_code _hdb_mdb_value2entry(krb5_context context,
+ krb5_data *data,
+ krb5_kvno target_kvno,
+ hdb_entry *entry);
+
+extern int _hdb_mit_dump2mitdb_entry(krb5_context context,
+ char *line,
+ krb5_storage *sp);
+
+
+
/*
can have any number of princ stanzas.
format is as follows (only \n indicates newlines)
@@ -74,19 +85,6 @@ unless no extra data
*/
-static int
-hex_to_octet_string(const char *ptr, krb5_data *data)
-{
- size_t i;
- unsigned int v;
- for(i = 0; i < data->length; i++) {
- if(sscanf(ptr + 2 * i, "%02x", &v) != 1)
- return -1;
- ((unsigned char*)data->data)[i] = v;
- }
- return 2 * i;
-}
-
static char *
nexttoken(char **p)
{
@@ -97,321 +95,116 @@ nexttoken(char **p)
return q;
}
-static size_t
-getdata(char **p, unsigned char *buf, size_t len)
-{
- size_t i;
- int v;
- char *q = nexttoken(p);
- i = 0;
- while(*q && i < len) {
- if(sscanf(q, "%02x", &v) != 1)
- break;
- buf[i++] = v;
- q += 2;
- }
- return i;
-}
-
-static int
-getint(char **p)
-{
- int val;
- char *q = nexttoken(p);
- sscanf(q, "%d", &val);
- return val;
-}
-
#include <kadm5/admin.h>
-static void
-attr_to_flags(unsigned attr, HDBFlags *flags)
-{
- flags->postdate = !(attr & KRB5_KDB_DISALLOW_POSTDATED);
- flags->forwardable = !(attr & KRB5_KDB_DISALLOW_FORWARDABLE);
- flags->initial = !!(attr & KRB5_KDB_DISALLOW_TGT_BASED);
- flags->renewable = !(attr & KRB5_KDB_DISALLOW_RENEWABLE);
- flags->proxiable = !(attr & KRB5_KDB_DISALLOW_PROXIABLE);
- /* DUP_SKEY */
- flags->invalid = !!(attr & KRB5_KDB_DISALLOW_ALL_TIX);
- flags->require_preauth = !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH);
- flags->require_hwauth = !!(attr & KRB5_KDB_REQUIRES_HW_AUTH);
- flags->server = !(attr & KRB5_KDB_DISALLOW_SVR);
- flags->change_pw = !!(attr & KRB5_KDB_PWCHANGE_SERVICE);
- flags->client = 1; /* XXX */
-}
-
-#define KRB5_KDB_SALTTYPE_NORMAL 0
-#define KRB5_KDB_SALTTYPE_V4 1
-#define KRB5_KDB_SALTTYPE_NOREALM 2
-#define KRB5_KDB_SALTTYPE_ONLYREALM 3
-#define KRB5_KDB_SALTTYPE_SPECIAL 4
-#define KRB5_KDB_SALTTYPE_AFS3 5
-
-static krb5_error_code
-fix_salt(krb5_context context, hdb_entry *ent, int key_num)
+static int
+my_fgetln(FILE *f, char **buf, size_t *sz, size_t *len)
{
- krb5_error_code ret;
- Salt *salt = ent->keys.val[key_num].salt;
- /* fix salt type */
- switch((int)salt->type) {
- case KRB5_KDB_SALTTYPE_NORMAL:
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_V4:
- krb5_data_free(&salt->salt);
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_NOREALM:
- {
- size_t len;
- size_t i;
- char *p;
-
- len = 0;
- for (i = 0; i < ent->principal->name.name_string.len; ++i)
- len += strlen(ent->principal->name.name_string.val[i]);
- ret = krb5_data_alloc (&salt->salt, len);
- if (ret)
- return ret;
- p = salt->salt.data;
- for (i = 0; i < ent->principal->name.name_string.len; ++i) {
- memcpy (p,
- ent->principal->name.name_string.val[i],
- strlen(ent->principal->name.name_string.val[i]));
- p += strlen(ent->principal->name.name_string.val[i]);
- }
-
- salt->type = KRB5_PADATA_PW_SALT;
- break;
+ char *p, *n;
+
+ if (!*buf) {
+ *buf = malloc(*sz ? *sz : 2048);
+ if (!*buf)
+ return ENOMEM;
+ if (!*sz)
+ *sz = 2048;
}
- case KRB5_KDB_SALTTYPE_ONLYREALM:
- krb5_data_free(&salt->salt);
- ret = krb5_data_copy(&salt->salt,
- ent->principal->realm,
- strlen(ent->principal->realm));
- if(ret)
- return ret;
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_SPECIAL:
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_AFS3:
- krb5_data_free(&salt->salt);
- ret = krb5_data_copy(&salt->salt,
- ent->principal->realm,
- strlen(ent->principal->realm));
- if(ret)
- return ret;
- salt->type = KRB5_PADATA_AFS3_SALT;
- break;
- default:
- abort();
+ *len = 0;
+ while ((p = fgets(&(*buf)[*len], *sz, f))) {
+ if (strcspn(*buf, "\r\n") || feof(f)) {
+ *len = strlen(*buf);
+ return 0;
+ }
+ *len += strlen(&(*buf)[*len]); /* *len should be == *sz */
+ n = realloc(buf, *sz + (*sz >> 1));
+ if (!n) {
+ free(*buf);
+ *buf = NULL;
+ *sz = 0;
+ *len = 0;
+ return ENOMEM;
+ }
+ *buf = n;
+ *sz += *sz >> 1;
}
- return 0;
+ return 0; /* *len == 0 || no EOL -> EOF */
}
int
mit_prop_dump(void *arg, const char *file)
{
krb5_error_code ret;
- char line [2048];
- FILE *f;
+ size_t line_bufsz = 0;
+ size_t line_len = 0;
+ char *line = NULL;
int lineno = 0;
+ FILE *f;
struct hdb_entry_ex ent;
-
struct prop_data *pd = arg;
+ krb5_storage *sp = NULL;
+ krb5_data kdb_ent;
+ memset(&ent, 0, sizeof (ent));
f = fopen(file, "r");
- if(f == NULL)
+ if (f == NULL)
return errno;
- while(fgets(line, sizeof(line), f)) {
- char *p = line, *q;
-
- int i;
-
- int num_tl_data;
- int num_key_data;
- int high_kvno;
- int attributes;
+ ret = ENOMEM;
+ sp = krb5_storage_emem();
+ if (!sp)
+ goto out;
+ while ((ret = my_fgetln(f, &line, &line_bufsz, &line_len)) == 0) {
+ char *p = line;
+ char *q;
+ lineno++;
- int tmp;
-
- lineno++;
-
- memset(&ent, 0, sizeof(ent));
-
- q = nexttoken(&p);
- if(strcmp(q, "kdb5_util") == 0) {
+ if(strncmp(line, "kdb5_util", strlen("kdb5_util")) == 0) {
int major;
+ q = nexttoken(&p);
+ if (strcmp(q, "kdb5_util"))
+ errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* load_dump */
- if(strcmp(q, "load_dump"))
+ if (strcmp(q, "load_dump"))
errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* load_dump */
- if(strcmp(q, "version"))
+ if (strcmp(q, "version"))
errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* x.0 */
- if(sscanf(q, "%d", &major) != 1)
+ if (sscanf(q, "%d", &major) != 1)
errx(1, "line %d: unknown version", lineno);
- if(major != 4 && major != 5 && major != 6)
+ if (major != 4 && major != 5 && major != 6)
errx(1, "unknown dump file format, got %d, expected 4-6",
major);
continue;
- } else if(strcmp(q, "policy") == 0) {
+ } else if(strncmp(p, "policy", strlen("policy")) == 0) {
+ warnx("line: %d: ignoring policy (not supported)", lineno);
continue;
- } else if(strcmp(q, "princ") != 0) {
+ } else if(strncmp(p, "princ", strlen("princ")) != 0) {
warnx("line %d: not a principal", lineno);
continue;
}
- tmp = getint(&p);
- if(tmp != 38) {
- warnx("line %d: bad base length %d != 38", lineno, tmp);
- continue;
- }
- nexttoken(&p); /* length of principal */
- num_tl_data = getint(&p); /* number of tl-data */
- num_key_data = getint(&p); /* number of key-data */
- getint(&p); /* length of extra data */
- q = nexttoken(&p); /* principal name */
- krb5_parse_name(pd->context, q, &ent.entry.principal);
- attributes = getint(&p); /* attributes */
- attr_to_flags(attributes, &ent.entry.flags);
- tmp = getint(&p); /* max life */
- if(tmp != 0) {
- ALLOC(ent.entry.max_life);
- *ent.entry.max_life = tmp;
- }
- tmp = getint(&p); /* max renewable life */
- if(tmp != 0) {
- ALLOC(ent.entry.max_renew);
- *ent.entry.max_renew = tmp;
- }
- tmp = getint(&p); /* expiration */
- if(tmp != 0 && tmp != 2145830400) {
- ALLOC(ent.entry.valid_end);
- *ent.entry.valid_end = tmp;
- }
- tmp = getint(&p); /* pw expiration */
- if(tmp != 0) {
- ALLOC(ent.entry.pw_end);
- *ent.entry.pw_end = tmp;
- }
- nexttoken(&p); /* last auth */
- nexttoken(&p); /* last failed auth */
- nexttoken(&p); /* fail auth count */
- for(i = 0; i < num_tl_data; i++) {
- unsigned long val;
- int tl_type, tl_length;
- unsigned char *buf;
- krb5_principal princ;
-
- tl_type = getint(&p); /* data type */
- tl_length = getint(&p); /* data length */
-
-#define mit_KRB5_TL_LAST_PWD_CHANGE 1
-#define mit_KRB5_TL_MOD_PRINC 2
- switch(tl_type) {
- case mit_KRB5_TL_LAST_PWD_CHANGE:
- buf = malloc(tl_length);
- if (buf == NULL)
- errx(ENOMEM, "malloc");
- getdata(&p, buf, tl_length); /* data itself */
- val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- free(buf);
- ALLOC(ent.entry.extensions);
- ALLOC_SEQ(ent.entry.extensions, 1);
- ent.entry.extensions->val[0].mandatory = 0;
- ent.entry.extensions->val[0].data.element
- = choice_HDB_extension_data_last_pw_change;
- ent.entry.extensions->val[0].data.u.last_pw_change = val;
- break;
- case mit_KRB5_TL_MOD_PRINC:
- buf = malloc(tl_length);
- if (buf == NULL)
- errx(ENOMEM, "malloc");
- getdata(&p, buf, tl_length); /* data itself */
- val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ);
- if (ret)
- krb5_err(pd->context, 1, ret,
- "parse_name: %s", (char *)buf + 4);
- free(buf);
- ALLOC(ent.entry.modified_by);
- ent.entry.modified_by->time = val;
- ent.entry.modified_by->principal = princ;
- break;
- default:
- nexttoken(&p);
- break;
- }
- }
- ALLOC_SEQ(&ent.entry.keys, num_key_data);
- high_kvno = -1;
- for(i = 0; i < num_key_data; i++) {
- int key_versions;
- int kvno;
- key_versions = getint(&p); /* key data version */
- kvno = getint(&p);
-
- /*
- * An MIT dump file may contain multiple sets of keys with
- * different kvnos. Since the Heimdal database can only represent
- * one kvno per principal, we only want the highest set. Assume
- * that set will be given first, and discard all keys with lower
- * kvnos.
- */
- if (kvno > high_kvno && high_kvno != -1)
- errx(1, "line %d: high kvno keys given after low kvno keys",
- lineno);
- else if (kvno < high_kvno) {
- nexttoken(&p); /* key type */
- nexttoken(&p); /* key length */
- nexttoken(&p); /* key */
- if (key_versions > 1) {
- nexttoken(&p); /* salt type */
- nexttoken(&p); /* salt length */
- nexttoken(&p); /* salt */
- }
- ent.entry.keys.len--;
- continue;
- }
- ent.entry.kvno = kvno;
- high_kvno = kvno;
- ALLOC(ent.entry.keys.val[i].mkvno);
- *ent.entry.keys.val[i].mkvno = 1;
-
- /* key version 0 -- actual key */
- ent.entry.keys.val[i].key.keytype = getint(&p); /* key type */
- tmp = getint(&p); /* key length */
- /* the first two bytes of the key is the key length --
- skip it */
- krb5_data_alloc(&ent.entry.keys.val[i].key.keyvalue, tmp - 2);
- q = nexttoken(&p); /* key itself */
- hex_to_octet_string(q + 4, &ent.entry.keys.val[i].key.keyvalue);
-
- if(key_versions > 1) {
- /* key version 1 -- optional salt */
- ALLOC(ent.entry.keys.val[i].salt);
- ent.entry.keys.val[i].salt->type = getint(&p); /* salt type */
- tmp = getint(&p); /* salt length */
- if(tmp > 0) {
- krb5_data_alloc(&ent.entry.keys.val[i].salt->salt, tmp - 2);
- q = nexttoken(&p); /* salt itself */
- hex_to_octet_string(q + 4,
- &ent.entry.keys.val[i].salt->salt);
- } else {
- ent.entry.keys.val[i].salt->salt.length = 0;
- ent.entry.keys.val[i].salt->salt.data = NULL;
- getint(&p); /* -1, if no data. */
- }
- fix_salt(pd->context, &ent.entry, i);
- }
- }
- nexttoken(&p); /* extra data */
- v5_prop(pd->context, NULL, &ent, arg);
+ krb5_storage_truncate(sp, 0);
+ ret = _hdb_mit_dump2mitdb_entry(pd->context, line, sp);
+ if (ret) break;
+ ret = krb5_storage_to_data(sp, &kdb_ent);
+ if (ret) break;
+ ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry);
+ krb5_data_free(&kdb_ent);
+ if (ret) break;
+ ret = v5_prop(pd->context, NULL, &ent, arg);
+ hdb_free_entry(pd->context, &ent);
+ if (ret) break;
}
+
+out:
fclose(f);
- return 0;
+ free(line);
+ if (sp)
+ krb5_storage_free(sp);
+ if (ret && ret == ENOMEM)
+ errx(1, "out of memory");
+ if (ret)
+ errx(1, "line %d: problem parsing dump line", lineno);
+ return ret;
}
+