gdp / apps / gdp-name-add.c @ master
History | View | Annotate | Download (9.02 KB)
1 | 59c6c7e0 | Eric Allman | /* vim: set ai sw=4 sts=4 ts=4 : */
|
---|---|---|---|
2 | |||
3 | /*
|
||
4 | ** GDP-NAME-ADD --- add a name to the external to internal name database.
|
||
5 | **
|
||
6 | ** ----- BEGIN LICENSE BLOCK -----
|
||
7 | ** Applications for the Global Data Plane
|
||
8 | ** From the Ubiquitous Swarm Lab, 490 Cory Hall, U.C. Berkeley.
|
||
9 | **
|
||
10 | c87dd166 | Eric Allman | ** Copyright (c) 2015-2019, Regents of the University of California.
|
11 | 59c6c7e0 | Eric Allman | ** All rights reserved.
|
12 | **
|
||
13 | ** Permission is hereby granted, without written agreement and without
|
||
14 | ** license or royalty fees, to use, copy, modify, and distribute this
|
||
15 | ** software and its documentation for any purpose, provided that the above
|
||
16 | ** copyright notice and the following two paragraphs appear in all copies
|
||
17 | ** of this software.
|
||
18 | **
|
||
19 | ** IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||
20 | ** SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
|
||
21 | ** PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
|
||
22 | ** EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
23 | **
|
||
24 | ** REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
||
25 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
26 | ** FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
|
||
27 | ** IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
|
||
28 | ** OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
||
29 | ** OR MODIFICATIONS.
|
||
30 | ** ----- END LICENSE BLOCK -----
|
||
31 | */
|
||
32 | |||
33 | #include <ep/ep.h> |
||
34 | #include <ep/ep_app.h> |
||
35 | #include <ep/ep_dbg.h> |
||
36 | #include <gdp/gdp.h> |
||
37 | 0e2c49f6 | Eric Allman | #include "../gdp/gdp_hongd.h" // cheat |
38 | 59c6c7e0 | Eric Allman | |
39 | #include <mysql.h> |
||
40 | |||
41 | #include <string.h> |
||
42 | #include <sysexits.h> |
||
43 | |||
44 | |||
45 | static EP_DBG Dbg = EP_DBG_INIT("gdp-name-add", "Update name database app"); |
||
46 | |||
47 | #define MILLISECONDS * INT64_C(1000000) |
||
48 | |||
49 | static MYSQL *NameDb; // name mapping database |
||
50 | |||
51 | /*
|
||
52 | ** This is essentially a copy of the standard startup routine but
|
||
53 | ** with different database credentials.
|
||
54 | */
|
||
55 | |||
56 | EP_STAT |
||
57 | 0e2c49f6 | Eric Allman | name_init(struct hongdargs *ha)
|
58 | 59c6c7e0 | Eric Allman | { |
59 | EP_STAT estat = EP_STAT_OK; |
||
60 | 35aacf70 | Eric Allman | bool i_own_passwd = false; |
61 | 59c6c7e0 | Eric Allman | |
62 | // open a connection to the external => internal mapping database
|
||
63 | 0e2c49f6 | Eric Allman | if (ha->dbhost == NULL) |
64 | ha->dbhost = ep_adm_getstrparam("swarm.gdp.hongdb.host",
|
||
65 | GDP_DEFAULT_HONGD_HOST); |
||
66 | if (ha->dbhost == NULL) |
||
67 | 59c6c7e0 | Eric Allman | { |
68 | 0c195bbd | Eric Allman | ep_app_error("No database name available; set swarm.gdp.hongdb.host");
|
69 | 59c6c7e0 | Eric Allman | estat = GDP_STAT_NAK_SVCUNAVAIL; |
70 | goto fail0;
|
||
71 | } |
||
72 | |||
73 | // read database password if we don't have one already
|
||
74 | 0e2c49f6 | Eric Allman | if (ha->dbpasswd == NULL) |
75 | 59c6c7e0 | Eric Allman | { |
76 | char prompt_buf[100]; |
||
77 | 0e2c49f6 | Eric Allman | snprintf(prompt_buf, sizeof prompt_buf, "Password for %s: ", ha->dbuser); |
78 | ha->dbpasswd = getpass(prompt_buf); |
||
79 | 35aacf70 | Eric Allman | i_own_passwd = true;
|
80 | 59c6c7e0 | Eric Allman | } |
81 | |||
82 | // attempt the actual connect and authentication
|
||
83 | 0e2c49f6 | Eric Allman | _gdp_name_init(ha); |
84 | |||
85 | 59c6c7e0 | Eric Allman | fail0:
|
86 | // make sure password isn't visible to intruders
|
||
87 | 0e2c49f6 | Eric Allman | if (ha->dbpasswd != NULL && i_own_passwd) |
88 | memset(ha->dbpasswd, 0, strlen(ha->dbpasswd));
|
||
89 | 59c6c7e0 | Eric Allman | return estat;
|
90 | } |
||
91 | |||
92 | |||
93 | c9af3429 | Eric Allman | int
|
94 | do_insert(const char *hname, const gdp_name_t gname) |
||
95 | { |
||
96 | int l = strlen(hname);
|
||
97 | char xescaped[2 * l + 1]; |
||
98 | char gescaped[2 * sizeof (gdp_name_t) + 1]; |
||
99 | char qbuf[1024]; |
||
100 | |||
101 | if (ep_dbg_test(Dbg, 9)) |
||
102 | { |
||
103 | gdp_pname_t pname; |
||
104 | |||
105 | ep_dbg_printf("adding %s -> %s\n",
|
||
106 | hname, gdp_printable_name(gname, pname)); |
||
107 | } |
||
108 | |||
109 | mysql_real_escape_string(NameDb, xescaped, hname, l); |
||
110 | mysql_real_escape_string(NameDb, gescaped, (const char *) gname, |
||
111 | sizeof (gdp_name_t));
|
||
112 | const char *q = |
||
113 | "INSERT INTO human_to_gdp (hname, gname)\n"
|
||
114 | " VALUES('%s', '%s')";
|
||
115 | snprintf(qbuf, sizeof qbuf, q, xescaped, gescaped);
|
||
116 | ep_dbg_cprintf(Dbg, 28, " %s\n", qbuf); |
||
117 | return mysql_query(NameDb, qbuf);
|
||
118 | } |
||
119 | |||
120 | |||
121 | int
|
||
122 | do_delete(const char *hname) |
||
123 | { |
||
124 | int l = strlen(hname);
|
||
125 | char xescaped[2 * l + 1]; |
||
126 | char qbuf[1024]; |
||
127 | |||
128 | ep_dbg_cprintf(Dbg, 9, "deleting %s\n", hname); |
||
129 | |||
130 | mysql_real_escape_string(NameDb, xescaped, hname, l); |
||
131 | const char *q = |
||
132 | "DELETE FROM human_to_gdp WHERE hname = '%s'\n";
|
||
133 | snprintf(qbuf, sizeof qbuf, q, xescaped);
|
||
134 | ep_dbg_cprintf(Dbg, 28, " %s\n", qbuf); |
||
135 | return mysql_query(NameDb, qbuf);
|
||
136 | } |
||
137 | |||
138 | |||
139 | 59c6c7e0 | Eric Allman | void
|
140 | usage(void)
|
||
141 | { |
||
142 | fprintf(stderr, |
||
143 | c9af3429 | Eric Allman | "Usage: %s [-d] [-D dbgspec] [-H db_host] [-p passwd] [-P pw_file]\n"
|
144 | 35aacf70 | Eric Allman | " [-q] [-u db_user] human_name gdp_name\n"
|
145 | c9af3429 | Eric Allman | " -d delete (instead of add)\n"
|
146 | 59c6c7e0 | Eric Allman | " -D set debugging flags\n"
|
147 | 35aacf70 | Eric Allman | " -H database host name (default: %s)\n"
|
148 | " -p database password\n"
|
||
149 | " -P name of file containing password\n"
|
||
150 | 59c6c7e0 | Eric Allman | " -q suppress output (exit status only)\n"
|
151 | 35aacf70 | Eric Allman | " -u database creation service user name (default: %s)\n"
|
152 | "human_name is the human-oriented log name\n"
|
||
153 | "gdp_name is the base-64 encoded 256-bit internal name\n",
|
||
154 | ep_app_getprogname(), |
||
155 | ep_adm_getstrparam("swarm.gdp.hongdb.host",
|
||
156 | 0e2c49f6 | Eric Allman | GDP_DEFAULT_HONGD_HOST), |
157 | b364b308 | Eric Allman | ep_adm_getstrparam("swarm.gdp.creation-service.user",
|
158 | 35aacf70 | Eric Allman | "gdp_creation_service"));
|
159 | 59c6c7e0 | Eric Allman | exit(EX_USAGE); |
160 | } |
||
161 | |||
162 | |||
163 | int
|
||
164 | main(int argc, char **argv) |
||
165 | { |
||
166 | 80da996e | Eric Allman | const char *hname; // external name, human-oriented text |
167 | 59c6c7e0 | Eric Allman | const char *pname; // internal name, base64-encoded |
168 | gdp_name_t gname; // internal name, binary
|
||
169 | 35aacf70 | Eric Allman | const char *db_passwd_file = NULL; // file containing associated password |
170 | 59c6c7e0 | Eric Allman | bool quiet = false; |
171 | c9af3429 | Eric Allman | bool delete = false; |
172 | 59c6c7e0 | Eric Allman | int opt;
|
173 | EP_STAT estat = EP_STAT_OK; |
||
174 | int xstat = EX_OK; // exit status |
||
175 | bool show_usage = false; |
||
176 | const char *phase; |
||
177 | 0e2c49f6 | Eric Allman | struct hongdargs *ha = ep_mem_zalloc(sizeof *ha); |
178 | 59c6c7e0 | Eric Allman | |
179 | // collect command-line arguments
|
||
180 | c9af3429 | Eric Allman | while ((opt = getopt(argc, argv, "dD:H:p:P:qu:")) > 0) |
181 | 59c6c7e0 | Eric Allman | { |
182 | switch (opt)
|
||
183 | { |
||
184 | c9af3429 | Eric Allman | case 'd': |
185 | delete = true;
|
||
186 | break;
|
||
187 | |||
188 | 59c6c7e0 | Eric Allman | case 'D': |
189 | ep_dbg_set(optarg); |
||
190 | break;
|
||
191 | |||
192 | case 'H': |
||
193 | 0e2c49f6 | Eric Allman | ha->dbhost = optarg; |
194 | 59c6c7e0 | Eric Allman | break;
|
195 | |||
196 | 35aacf70 | Eric Allman | case 'p': |
197 | 0e2c49f6 | Eric Allman | ha->dbpasswd = optarg; |
198 | 35aacf70 | Eric Allman | break;
|
199 | |||
200 | case 'P': |
||
201 | db_passwd_file = optarg; |
||
202 | break;
|
||
203 | |||
204 | 59c6c7e0 | Eric Allman | case 'q': |
205 | quiet = true;
|
||
206 | break;
|
||
207 | |||
208 | case 'u': |
||
209 | 0e2c49f6 | Eric Allman | ha->dbuser = optarg; |
210 | 59c6c7e0 | Eric Allman | break;
|
211 | |||
212 | default:
|
||
213 | show_usage = true;
|
||
214 | break;
|
||
215 | } |
||
216 | } |
||
217 | argc -= optind; |
||
218 | argv += optind; |
||
219 | |||
220 | c9af3429 | Eric Allman | if (show_usage || argc-- != (delete ? 1 : 2)) |
221 | 59c6c7e0 | Eric Allman | usage(); |
222 | |||
223 | 80da996e | Eric Allman | hname = *argv++; |
224 | c9af3429 | Eric Allman | if (!delete)
|
225 | pname = *argv++; |
||
226 | 59c6c7e0 | Eric Allman | |
227 | // initialize the GDP library
|
||
228 | phase = "initialization";
|
||
229 | e6bd4828 | Eric Allman | estat = gdp_init_phase_0(NULL, 0); |
230 | 59c6c7e0 | Eric Allman | if (!EP_STAT_ISOK(estat))
|
231 | { |
||
232 | if (!quiet)
|
||
233 | ep_app_error("GDP Library Initialization failed");
|
||
234 | goto fail0;
|
||
235 | } |
||
236 | |||
237 | c9af3429 | Eric Allman | // figure out appropriate defaults
|
238 | if (delete)
|
||
239 | 35aacf70 | Eric Allman | { |
240 | 0e2c49f6 | Eric Allman | if (ha->dbuser == NULL) |
241 | ha->dbuser = ep_adm_getstrparam("swarm.gdp.hongd.admin.user",
|
||
242 | c9af3429 | Eric Allman | "hongd_admin");
|
243 | if (db_passwd_file == NULL) |
||
244 | db_passwd_file = ep_adm_getstrparam("swarm.gdp.hongd.admin.passwd-file",
|
||
245 | "/etc/gdp/hongd_admin_pw.txt");
|
||
246 | } |
||
247 | else
|
||
248 | { |
||
249 | 0e2c49f6 | Eric Allman | if (ha->dbuser == NULL) |
250 | ha->dbuser = ep_adm_getstrparam("swarm.gdp.creation-service.user",
|
||
251 | c9af3429 | Eric Allman | "gdp_creation_service");
|
252 | 35aacf70 | Eric Allman | if (db_passwd_file == NULL) |
253 | db_passwd_file = ep_adm_getstrparam( |
||
254 | b364b308 | Eric Allman | "swarm.gdp.creation-service.passwd-file",
|
255 | 35aacf70 | Eric Allman | "/etc/gdp/creation_service_pw.txt");
|
256 | c9af3429 | Eric Allman | } |
257 | 0e2c49f6 | Eric Allman | if (ha->dbpasswd == NULL && db_passwd_file != NULL) |
258 | c9af3429 | Eric Allman | { |
259 | FILE *pw_fp = fopen(db_passwd_file, "r");
|
||
260 | if (pw_fp != NULL) |
||
261 | 35aacf70 | Eric Allman | { |
262 | c9af3429 | Eric Allman | char pbuf[128]; |
263 | 35aacf70 | Eric Allman | |
264 | c9af3429 | Eric Allman | if (fgets(pbuf, sizeof pbuf, pw_fp) != NULL && pbuf[0] != '\0') |
265 | 597d9a16 | Eric Allman | { |
266 | char *p = strchr(pbuf, '\n'); |
||
267 | if (p != NULL) |
||
268 | *p = '\0';
|
||
269 | 0e2c49f6 | Eric Allman | ha->dbpasswd = strdup(pbuf); |
270 | 597d9a16 | Eric Allman | } |
271 | c9af3429 | Eric Allman | fclose(pw_fp); |
272 | 35aacf70 | Eric Allman | } |
273 | c9af3429 | Eric Allman | else if (!quiet) |
274 | ep_app_warn("Cannot read %s", db_passwd_file);
|
||
275 | 35aacf70 | Eric Allman | } |
276 | 0e2c49f6 | Eric Allman | if (ha->dbpasswd == NULL && !quiet) |
277 | ep_app_warn("No password for %s", ha->dbuser);
|
||
278 | |||
279 | NameDb = _gdp_hongd_conn_open(ha); |
||
280 | |||
281 | if (!quiet)
|
||
282 | ep_app_info("Using HONGD server %s", ha->dbhost);
|
||
283 | 35aacf70 | Eric Allman | |
284 | 59c6c7e0 | Eric Allman | // translate GDP name from base64 to binary
|
285 | c9af3429 | Eric Allman | if (!delete)
|
286 | 59c6c7e0 | Eric Allman | { |
287 | c9af3429 | Eric Allman | phase = "name translate";
|
288 | estat = gdp_internal_name(pname, gname); |
||
289 | if (!EP_STAT_ISOK(estat))
|
||
290 | 59c6c7e0 | Eric Allman | { |
291 | c9af3429 | Eric Allman | if (!quiet)
|
292 | { |
||
293 | ep_app_message(estat, "cannot decode %s", pname);
|
||
294 | fprintf(stderr, "\t(Should be base64-encoded log name)\n");
|
||
295 | } |
||
296 | xstat = EX_DATAERR; |
||
297 | goto fail0;
|
||
298 | 59c6c7e0 | Eric Allman | } |
299 | } |
||
300 | |||
301 | 9caa9f1c | Eric Allman | // figure out ultimate human name (perhaps using $GDP_NAME_ROOT)
|
302 | const char *root = getenv("GDP_NAME_ROOT"); |
||
303 | ep_dbg_cprintf(Dbg, 10, "GDP_NAME_ROOT=%s\n", root); |
||
304 | if (root != NULL && root[0] != '\0' && strchr(hname, '.') == NULL) |
||
305 | { |
||
306 | int plen = strlen(root) + strlen(hname) + 2; |
||
307 | char *p = ep_mem_malloc(plen);
|
||
308 | snprintf(p, plen, "%s.%s", root, hname);
|
||
309 | hname = p; |
||
310 | } |
||
311 | |||
312 | if (!quiet)
|
||
313 | c9af3429 | Eric Allman | { |
314 | if (delete)
|
||
315 | ep_app_info("deleting %s", hname);
|
||
316 | else
|
||
317 | ep_app_info("adding %s => %s", hname, pname);
|
||
318 | } |
||
319 | 9caa9f1c | Eric Allman | |
320 | 59c6c7e0 | Eric Allman | // open database connection
|
321 | phase = "database open";
|
||
322 | 0e2c49f6 | Eric Allman | estat = name_init(ha); |
323 | 59c6c7e0 | Eric Allman | if (!EP_STAT_ISOK(estat))
|
324 | { |
||
325 | if (!quiet)
|
||
326 | ep_app_message(estat, "cannot initialize name database (%s)",
|
||
327 | mysql_error(NameDb)); |
||
328 | xstat = EX_UNAVAILABLE; |
||
329 | goto fail0;
|
||
330 | } |
||
331 | |||
332 | // now attempt the actual database update
|
||
333 | c9af3429 | Eric Allman | int istat;
|
334 | if (delete)
|
||
335 | 59c6c7e0 | Eric Allman | { |
336 | c9af3429 | Eric Allman | phase = "DELETE";
|
337 | istat = do_delete(hname); |
||
338 | if (istat == 0) |
||
339 | 59c6c7e0 | Eric Allman | { |
340 | c9af3429 | Eric Allman | my_ulonglong nrows = mysql_affected_rows(NameDb); |
341 | if (nrows == 0) |
||
342 | xstat = EX_NOINPUT; |
||
343 | 59c6c7e0 | Eric Allman | if (!quiet)
|
344 | c9af3429 | Eric Allman | { |
345 | if (nrows == 0) |
||
346 | ep_app_warn("no rows matched");
|
||
347 | else
|
||
348 | ep_app_info("%lld rows deleted", nrows);
|
||
349 | } |
||
350 | 59c6c7e0 | Eric Allman | } |
351 | } |
||
352 | c9af3429 | Eric Allman | else
|
353 | { |
||
354 | phase = "INSERT";
|
||
355 | istat = do_insert(hname, gname); |
||
356 | } |
||
357 | 59c6c7e0 | Eric Allman | |
358 | // cleanup and exit
|
||
359 | c9af3429 | Eric Allman | if (istat != 0) |
360 | 59c6c7e0 | Eric Allman | { |
361 | if (EP_STAT_ISOK(estat))
|
||
362 | estat = GDP_STAT_MYSQL_ERROR; |
||
363 | c9af3429 | Eric Allman | if (!quiet)
|
364 | ep_app_error("%s failed: %s", phase, mysql_error(NameDb));
|
||
365 | 59c6c7e0 | Eric Allman | } |
366 | |||
367 | fail0:
|
||
368 | if (NameDb != NULL) |
||
369 | mysql_close(NameDb); |
||
370 | NameDb = NULL;
|
||
371 | |||
372 | // OK status can have values; hide that from the user
|
||
373 | if (EP_STAT_ISOK(estat))
|
||
374 | estat = EP_STAT_OK; |
||
375 | else if (xstat == EX_OK) |
||
376 | xstat = EX_UNAVAILABLE; |
||
377 | exit(xstat); |
||
378 | } |