1 /* tool/get_localid.c -- Retrieve local identity credentials
3 * Provide a config, a NAI and see what types of credentials are available
6 * From: Rick van Rein <rick@openfortress.nl>
15 #include <sys/types.h>
22 #include <arpa/inet.h>
26 #include <tlspool/internal.h>
29 const char const *usage =
30 "Usage: %s tlspool.conf [user@]fqdn type [outfile.der]\n"
31 " - tlspool.conf is the configuration file for the TLS Pool\n"
32 " - user@fqdn or fqdn is a network access identifier\n"
33 " - type X.509,OpenPGP,Kerberos,valexp,client,server,noP11,chained\n"
34 " - outfile.der optional output file for binary encoded public data\n"
35 "Since the public data is stored in a binary format, it will never be printed\n"
36 "on stdout; in absense of outfile.der the value is simply not output.\n";
44 struct typemap_t typemap [] = {
58 /* Setup and tear down management */
59 int setup_management (DB_ENV **dbenv, DB_TXN **txn, DB **dbh) {
60 char *dbenv_dir = cfg_dbenv_dir ();
61 char *dblid_fnm = cfg_db_localid ();
62 if (dbenv_dir == NULL) {
63 fprintf (stderr, "Please configure database environment directory\n");
66 if (dblid_fnm == NULL) {
67 fprintf (stderr, "Please configure localid database name\n");
70 if (db_env_create (dbenv, 0) != 0) {
71 fprintf (stderr, "Failed to create database environment");
74 if ((*dbenv)->open (*dbenv, dbenv_dir, DB_CREATE | DB_RECOVER | DB_INIT_TXN | DB_INIT_LOG | DB_INIT_LOCK | DB_THREAD | DB_INIT_MPOOL, S_IRUSR | S_IWUSR) != 0) {
75 fprintf (stderr, "Failed to open database environment");
78 if ((*dbenv)->txn_begin (*dbenv, NULL, txn, 0) != 0) {
79 fprintf (stderr, "Failed to start transaction\n");
82 if (db_create (dbh, *dbenv, 0) != 0) {
83 fprintf (stderr, "Failed to create localid database\n");
86 if ((*dbh)->set_flags (*dbh, DB_DUP) != 0) {
87 fprintf (stderr, "Failed to setup localid database for duplicate entries\n");
90 if ((*dbh)->open (*dbh, *txn, dblid_fnm, NULL, DB_HASH, DB_THREAD | DB_RDONLY, 0) != 0) {
91 fprintf (stderr, "Failed to open localid database\n");
97 /* Cleanup maangement structures */
98 void cleanup_management (DB_ENV *dbenv, DB *db) {
100 dbenv->close (dbenv, 0);
103 int main (int argc, char *argv []) {
104 char *localid = NULL;
105 char *partstr = NULL;
106 char *saveptr = NULL;
108 uint8_t e_buf [5000];
126 if ((argc < 4) || (argc > 5)) {
127 fprintf (stderr, usage, argv [0]);
131 outfile = open (argv [4], O_WRONLY | O_CREAT | O_TRUNC, 0644);
133 perror ("Failed to open output file");
138 // Initialise the modules taken from the src directory
139 parse_cfgfile (argv [1], 0);
141 // Prepare variables from arguments
143 partstr = strtok_r (argv [3], ",", &saveptr);
144 if (partstr == NULL) {
145 fprintf (stderr, "Flags must not be empty\n");
148 while (partstr != NULL) {
149 struct typemap_t *walker = typemap;
150 while (walker->name != NULL) {
151 if (strcasecmp (walker->name, partstr) == 0) {
152 flags |= walker->bits;
157 if (walker->name == NULL) {
158 fprintf (stderr, "Flag name %s not recognised\n", partstr);
161 partstr = strtok_r (NULL, ",", &saveptr);
164 // Now retrieve the matching entries
165 if (!setup_management (&dbenv, &txn, &dbh)) {
168 if (dbh->cursor (dbh, txn, &crs, 0) != 0) {
169 fprintf (stderr, "Failed to open cursor on localid.db\n");
172 memset (&k_localid, 0, sizeof (k_localid));
173 k_localid.data = localid;
174 k_localid.size = strlen (localid);
175 nomore = crs->get (crs, &k_localid, &e_value, DB_SET);
176 while (nomore == 0) {
177 uint32_t e_flags = 0;
178 char *e_p11uri = NULL;
181 if (e_value.size < 4) {
182 fprintf (stderr, "Found too-short entry?!?\n");
186 e_flags = ntohl (* (uint32_t *) e_value.data);
187 e_p11uri = (char *) & ((uint32_t *) e_value.data) [1];
188 e_bindata = e_p11uri + strnlen (e_p11uri, e_value.size - 4) + 1;
189 e_binlen = e_value.size - 4 - strnlen (e_p11uri, e_value.size - 4) - 1;
191 fprintf (stderr, "Error retrieving binary data\n");
195 if ((e_flags & 0xff) == (flags & 0xff)) {
196 uint32_t todo_flags = e_flags;
197 struct typemap_t *tm = typemap;
198 printf ("Flags: 0x%x:", e_flags);
199 while (tm->name != NULL) {
200 if (todo_flags & tm->bits) {
201 printf (" %s", tm->name);
202 todo_flags = todo_flags & ~tm->bits;
206 if (todo_flags != 0) {
207 printf (" UNKNOWN_%d", todo_flags);
209 printf ("\nPrivate: %s\n", e_p11uri);
212 if (write (outfile, e_bindata, e_binlen) == e_binlen) {
213 printf ("Written %d bytes\n", e_binlen);
217 outfile = -1; // No more than one binary write
219 printf ("Public: %02x %02x...%02x %02x (length %d)%s\n",
220 e_bindata [0], e_bindata [1],
221 e_bindata [e_binlen-2], e_bindata [e_binlen-1],
223 written? " (written)": "");
225 nomore = crs->get (crs, &k_localid, &e_value, DB_NEXT_DUP);
228 if (nomore != DB_NOTFOUND) {
229 fprintf (stderr, "Database error encountered while iterating\n");
232 if (txn->commit (txn, 0) != 0) {
233 fprintf (stderr, "Failed to commit readonly transaction\n");
237 // Finish up and report success
239 cleanup_management (dbenv, dbh);
242 // Handle failure during database interactions
244 fprintf (stderr, "Rolling back transaction\n");
246 cleanup_management (dbenv, dbh);