First working TLS-KDH system! (Still with possible memleaks)
[tlspool] / tool / set_disclose.c
1 /* tool/set_disclose.c -- Setup disclosure for local identities
2  *
3  * Provide a config, a selector for remote peers and a list of local DoNAIs.
4  * The command erases all matching old entries, and installs any new ones.
5  *
6  * From: Rick van Rein <rick@openfortress.nl>
7  */
8
9
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <string.h>
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <errno.h>
20
21 #include <db.h>
22
23 #include <tlspool/internal.h>
24
25
26 const char const *usage =
27 "Usage: %s tlspool.conf selector [[user@]domain...]\n"
28 " - tlspool.conf      is the configuration file for the TLS Pool\n"
29 " - selector              is a matcher for remote peer identities\n"
30 " - user@domain or domain is a local client network access identifier\n"
31 "The list of client identities replaces the old list.  An empty list is nothing\n"
32 "special; it replaces the old content with zero entries.\n"
33 "The selector may take the following forms:\n"
34 " - domain      matches remote peer DoNAI  completely but    with no username\n"
35 " - .domain     matches remote peer DoNAIs ending in .domain with no username\n"
36 " - .           matches any remote peer                      with no username\n"
37 " - user@domain matches remote peer DoNAI  with the username given\n"
38 " - @domain     matches remote peer DoNAIs with any username\n"
39 " - @.domain    matches remote peer DoNAIs with any username ending in .domain\n"
40 " - @.          matches remote peer DoNAIs with any username and any domain\n"
41 "When multiple selectors match a remote DoNAI, only the most concrete applies.\n"
42 "When no selector matches a remote DoNAI, the default policy is to reject.\n"
43 "An empty [[user@]domain] list is nothing special; it removes old content.\n";
44
45
46 /* Setup and tear down management */
47 int setup_management (DB_ENV **dbenv, DB_TXN **txn, DB **dbh_disc, DB **dbh_lid) {
48         char *dbenv_dir = cfg_dbenv_dir ();
49         char *dblid_fnm = cfg_db_localid ();
50         char *dbdisc_fnm = cfg_db_disclose ();
51         if (dbenv_dir == NULL) {
52                 fprintf (stderr, "Please configure database environment directory\n");
53                 return 0;
54         }
55         if (dbdisc_fnm == NULL) {
56                 fprintf (stderr, "Please configure disclose database name\n");
57                 return 0;
58         }
59         if (dblid_fnm == NULL) {
60                 fprintf (stderr, "Please configure localid database name\n");
61                 return 0;
62         }
63         if (db_env_create (dbenv, 0) != 0) {
64                 fprintf (stderr, "Failed to create database environment");
65                 return 0;
66         }
67         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) {
68                 fprintf (stderr, "Failed to open database environment");
69                 return 0;
70         }
71         if ((*dbenv)->txn_begin (*dbenv, NULL, txn, 0) != 0) {
72                 fprintf (stderr, "Failed to start transaction\n");
73                 exit (1);
74         }
75         if (db_create (dbh_disc, *dbenv, 0) != 0) {
76                 fprintf (stderr, "Failed to create disclose database\n");
77                 return 0;
78         }
79         if (db_create (dbh_lid, *dbenv, 0) != 0) {
80                 fprintf (stderr, "Failed to create localid database\n");
81                 return 0;
82         }
83         if ((*dbh_disc)->set_flags (*dbh_disc, DB_DUP) != 0) {
84                 fprintf (stderr, "Failed to setup disclose database for duplicate entries\n");
85                 return 0;
86         }
87         if ((*dbh_lid)->set_flags (*dbh_lid, DB_DUP) != 0) {
88                 fprintf (stderr, "Failed to setup localid database for duplicate entries\n");
89                 return 0;
90         }
91         if ((*dbh_disc)->open (*dbh_disc, *txn, dbdisc_fnm, NULL, DB_HASH, DB_CREATE | DB_THREAD, 0) != 0) {
92                 fprintf (stderr, "Failed to open disclose database\n");
93                 return 0;
94         }
95         if ((*dbh_lid)->open (*dbh_lid, *txn, dblid_fnm, NULL, DB_HASH, DB_CREATE | DB_THREAD, 0) != 0) {
96                 fprintf (stderr, "Failed to open disclose database\n");
97                 return 0;
98         }
99         return 1;
100 }
101
102 /* Cleanup maangement structures */
103 void cleanup_management (DB_ENV *dbenv, DB *db_disc, DB *db_lid) {
104         db_lid->close (db_lid, 0);
105         db_disc->close (db_disc, 0);
106         dbenv->close (dbenv, 0);
107 }
108
109 int main (int argc, char *argv []) {
110         char *selector = NULL;
111         char *partstr = NULL;
112         char *saveptr = NULL;
113         char *p11uri = NULL;
114         uint8_t e_buf [5000];
115         int argi = argc;
116         int filesz = 0;
117         int p11len = 0;
118         struct stat statbuf;
119         uint32_t flags = 0;
120         DB_ENV *dbenv;
121         DB_TXN *txn;
122         DB *dbh_disc;
123         DB *dbh_lid;
124         DBC *crs;
125         DBT k_localid;
126         DBT k_selector;
127         DBT e_value;
128         int nomore;
129         int fd;
130         //
131         // Sanity check
132         if (argc < 3) {
133                 fprintf (stderr, usage, argv [0]);
134                 exit (1);
135         }
136         //
137         // Initialise the modules taken from the src directory
138         parse_cfgfile (argv [1], 0);
139         //
140         // Prepare variables from arguments
141         selector = argv [2];
142         //
143         // Now prepare the database for changes
144         if (!setup_management (&dbenv, &txn, &dbh_disc, &dbh_lid)) {
145                 exit (1);
146         }
147         //
148         // Verify that the to-be-introduced localid values occur in localid.db
149         argi = 3;
150         if (dbh_lid->cursor (dbh_lid, txn, &crs, 0) != 0) {
151                 fprintf (stderr, "Failed to open cursor on localid.db\n");
152                 goto failure;
153         }
154         while (argi < argc) {
155                 memset (&k_localid, 0, sizeof (k_localid));
156                 k_localid.data = argv [argi];
157                 k_localid.size = strlen (argv [argi]);
158                 if (crs->get (crs, &k_localid, &e_value, DB_SET) != 0) {
159                         fprintf (stderr, "Unknown local identity: %s\n", argv [argi]);
160                         crs->close (crs);
161                         goto failure;
162                 }
163                 argi++;
164         }
165         crs->close (crs);
166         //
167         // We now know that all localid values are present in this transaction
168         // We can safely continue into removal of the old values and add new ones
169         if (dbh_disc->cursor (dbh_disc, txn, &crs, 0) != 0) {
170                 fprintf (stderr, "Failed to open cursor on disclose.db\n");
171                 goto failure;
172         }
173         memset (&k_selector, 0, sizeof (k_selector));
174         k_selector.data = selector;
175         k_selector.size = strlen (selector);
176         nomore = crs->get (crs, &k_selector, &e_value, DB_SET);
177         while (nomore == 0) {
178                 printf ("Removing local identity %.*s\n",
179                                 e_value.size, e_value.data);
180                 if (crs->del (crs, 0) != 0) {
181                         fprintf (stderr, "Failed to delete record\n");
182                         crs->close (crs);
183                         goto failure;
184                 }
185                 nomore = crs->get (crs, &k_selector, &e_value, DB_NEXT_DUP);
186         }
187         crs->close (crs);
188         if (nomore != DB_NOTFOUND) {
189                 fprintf (stderr, "Database error encountered while iterating\n");
190                 goto failure;
191         }
192         //
193         // Now append the new loclid values
194         argi = 3;
195         while (argi < argc) {
196                 k_localid.data = argv [argi];
197                 k_localid.size = strlen (argv [argi]);
198                 printf ("Adding local identity %.*s\n",
199                                 k_localid.size, k_localid.data);
200                 if (dbh_disc->put (dbh_disc, txn, &k_selector, &k_localid, 0) != 0) {
201                         fprintf (stderr, "Failed to write record\n");
202                         crs->close (crs);
203                         goto failure;
204                 }
205                 argi++;
206         }
207         //
208         // Finally, commit the transaction
209         if (txn->commit (txn, 0) != 0) {
210                 fprintf (stderr, "Failed to commit transaction\n");
211                 exit (1);
212         } else {
213                 fprintf (stderr, "Committed transaction\n");
214         }
215         //
216         // Finish up and report success
217 success:
218         cleanup_management (dbenv, dbh_disc, dbh_lid);
219         return 0;
220         //
221         // Handle failure during database interactions
222 failure:
223         fprintf (stderr, "Rolling back transaction\n");
224         txn->abort (txn);
225         cleanup_management (dbenv, dbh_disc, dbh_lid);
226         exit (1);
227 }