Skip to content

Commit

Permalink
s4:heimdal Extend the 'hdb as a keytab' code
Browse files Browse the repository at this point in the history
This extends the hdb_keytab code to allow enumeration of all the keys.

The plan is to allow ktutil's copy command to copy from Samba4's
hdb_samba4 into a file-based keytab used in wireshark.

One day, with a few more hacks, we might even make this a loadable
module that can be used directly...

Andrew Bartlett
  • Loading branch information
abartlet committed Jul 27, 2009
1 parent afb6ac2 commit 0c2dca7
Showing 1 changed file with 145 additions and 4 deletions.
149 changes: 145 additions & 4 deletions source4/heimdal/lib/hdb/keytab.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@

struct hdb_data {
char *dbname;
char *mkey;
char *mkey;
};

struct hdb_cursor {
HDB *db;
hdb_entry_ex hdb_entry;
bool first, next;
int key_idx;
};

/*
Expand Down Expand Up @@ -247,16 +254,150 @@ hdb_get_entry(krb5_context context,
return ret;
}

/*
* find the keytab entry in `id' for `principal, kvno, enctype' and return
* it in `entry'. return 0 or an error code
*/

static krb5_error_code
hdb_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
krb5_error_code ret;
struct hdb_cursor *c;
struct hdb_data *d = id->data;
const char *dbname = d->dbname;
const char *mkey = d->mkey;
HDB *db;

if (dbname == NULL) {
/* We don't support enumerating without being told what backend to enumerate on */
ret = KRB5_KT_NOTFOUND;
return ret;
}

ret = hdb_create (context, &db, dbname);
if (ret)
return ret;
ret = hdb_set_master_keyfile (context, db, mkey);
if (ret) {
(*db->hdb_destroy)(context, db);
return ret;
}

ret = (*db->hdb_open)(context, db, O_RDONLY, 0);
if (ret) {
(*db->hdb_destroy)(context, db);
return ret;
}

cursor->data = c = malloc (sizeof(*c));
if(c == NULL){
(*db->hdb_close)(context, db);
(*db->hdb_destroy)(context, db);
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}

c->db = db;
c->first = true;
c->next = true;
c->key_idx = 0;

cursor->data = c;
return ret;
}

static int hdb_next_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *cursor)
{
struct hdb_cursor *c = cursor->data;
krb5_error_code ret;

if (c->first) {
c->first = false;
ret = (c->db->hdb_firstkey)(context, c->db,
HDB_F_DECRYPT|
HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
&c->hdb_entry);
if (ret == HDB_ERR_NOENTRY) {
return KRB5_KT_END;
} else if (ret) {
return ret;
}

if (c->hdb_entry.entry.keys.len == 0) {
hdb_free_entry(context, &c->hdb_entry);
} else {
c->next = false;
}
}

while (c->next) {
ret = (c->db->hdb_nextkey)(context, c->db,
HDB_F_DECRYPT|
HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
&c->hdb_entry);
if (ret == HDB_ERR_NOENTRY) {
return KRB5_KT_END;
} else if (ret) {
return ret;
}
if (c->hdb_entry.entry.keys.len == 0) {
/* If no keys on this entry, try again */
hdb_free_entry(context, &c->hdb_entry);
} else {
/* We have an entry, set the flag */
c->next = false;
}
};

/* return next enc type (keytabs are one slot per key, while hdb is one record per principal */
krb5_copy_principal(context,
c->hdb_entry.entry.principal,
&entry->principal);
entry->vno = c->hdb_entry.entry.kvno;
krb5_copy_keyblock_contents(context,
&c->hdb_entry.entry.keys.val[c->key_idx].key,
&entry->keyblock);
c->key_idx++;

/* Once we get to the end of the list, signal that we want the next entry */
if (c->key_idx == c->hdb_entry.entry.keys.len) {
hdb_free_entry(context, &c->hdb_entry);
c->next = true;
c->key_idx = 0;
}
return 0;
}


static int hdb_end_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor) {
struct hdb_cursor *c = cursor->data;
(c->db->hdb_close)(context, c->db);
(c->db->hdb_destroy)(context, c->db);
if (!c->next) {
hdb_free_entry(context, &c->hdb_entry);
}
free(c);
return 0;
}

krb5_kt_ops hdb_kt_ops = {
"HDB",
hdb_resolve,
hdb_get_name,
hdb_close,
NULL, /* destroy */
hdb_get_entry,
NULL, /* start_seq_get */
NULL, /* next_entry */
NULL, /* end_seq_get */
hdb_start_seq_get,
hdb_next_entry,
hdb_end_seq_get,
NULL, /* add */
NULL /* remove */
};

0 comments on commit 0c2dca7

Please sign in to comment.