Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

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
}