s3:utils: let smbstatus report anonymous signing/encryption explicitly
[samba.git] / source3 / utils / dbwrap_tool.c
1 /*
2    Samba Unix/Linux CIFS implementation
3
4    low level TDB/CTDB tool using the dbwrap interface
5
6    Copyright (C) 2009 Michael Adam <obnox@samba.org>
7    Copyright (C) 2011 Bjoern Baumbach <bb@sernet.de>
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "lib/cmdline/cmdline.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_open.h"
28 #include "messages.h"
29 #include "util_tdb.h"
30 #include "cmdline_contexts.h"
31 #include "lib/param/param.h"
32
33 enum dbwrap_op { OP_FETCH, OP_STORE, OP_DELETE, OP_ERASE, OP_LISTKEYS,
34                  OP_EXISTS };
35
36 enum dbwrap_type { TYPE_INT32, TYPE_UINT32, TYPE_STRING, TYPE_HEX, TYPE_NONE };
37
38 static int dbwrap_tool_fetch_int32(struct db_context *db,
39                                    const char *keyname,
40                                    const char *data)
41 {
42         int32_t value;
43         NTSTATUS status;
44
45         status = dbwrap_fetch_int32_bystring(db, keyname, &value);
46         if (!NT_STATUS_IS_OK(status)) {
47                 d_printf("Error fetching int32 from key '%s': %s\n",
48                          keyname, nt_errstr(status));
49                 return -1;
50         }
51         d_printf("%d\n", value);
52
53         return 0;
54 }
55
56 static int dbwrap_tool_fetch_uint32(struct db_context *db,
57                                     const char *keyname,
58                                     const char *data)
59 {
60         uint32_t value;
61         NTSTATUS ret;
62
63         ret = dbwrap_fetch_uint32_bystring(db, keyname, &value);
64         if (NT_STATUS_IS_OK(ret)) {
65                 d_printf("%u\n", value);
66                 return 0;
67         } else {
68                 d_fprintf(stderr, "ERROR: could not fetch uint32 key '%s': "
69                           "%s\n", nt_errstr(ret), keyname);
70                 return -1;
71         }
72 }
73
74 static int dbwrap_tool_fetch_string(struct db_context *db,
75                                     const char *keyname,
76                                     const char *data)
77 {
78         TDB_DATA tdbdata;
79         NTSTATUS status;
80         TALLOC_CTX *tmp_ctx = talloc_stackframe();
81         int ret;
82
83         status = dbwrap_fetch_bystring(db, tmp_ctx, keyname, &tdbdata);
84         if (NT_STATUS_IS_OK(status)) {
85                 d_printf("%-*.*s\n", (int)tdbdata.dsize, (int)tdbdata.dsize,
86                          tdbdata.dptr);
87                 ret = 0;
88         } else {
89                 d_fprintf(stderr, "ERROR: could not fetch string key '%s': "
90                           "%s\n", nt_errstr(status), keyname);
91                 ret = -1;
92         }
93
94         talloc_free(tmp_ctx);
95         return ret;
96 }
97
98 static int dbwrap_tool_fetch_hex(struct db_context *db,
99                                  const char *keyname,
100                                  const char *data)
101 {
102         TDB_DATA tdbdata;
103         DATA_BLOB datablob;
104         NTSTATUS status;
105         TALLOC_CTX *tmp_ctx = talloc_stackframe();
106         char *hex_string;
107         int ret;
108
109         status = dbwrap_fetch_bystring(db, tmp_ctx, keyname, &tdbdata);
110         if (NT_STATUS_IS_OK(status)) {
111                 datablob.data = tdbdata.dptr;
112                 datablob.length = tdbdata.dsize;
113
114                 hex_string = data_blob_hex_string_upper(tmp_ctx, &datablob);
115                 if (hex_string == NULL) {
116                         d_fprintf(stderr, "ERROR: could not get hex string "
117                                   "from data blob\n");
118                         ret = -1;
119                 } else {
120                         d_printf("%s\n", hex_string);
121                         ret =  0;
122                 }
123         } else {
124                 d_fprintf(stderr, "ERROR: could not fetch hex key '%s': "
125                           "%s\n", nt_errstr(status), keyname);
126                 ret = -1;
127         }
128
129         talloc_free(tmp_ctx);
130         return ret;
131 }
132
133 static int dbwrap_tool_store_int32(struct db_context *db,
134                                    const char *keyname,
135                                    const char *data)
136 {
137         NTSTATUS status;
138         int32_t value = (int32_t)strtol(data, NULL, 10);
139
140         if (dbwrap_is_persistent(db)) {
141                 status = dbwrap_trans_store_int32_bystring(db, keyname, value);
142         } else {
143                 status = dbwrap_store_int32_bystring(db, keyname, value);
144         }
145         if (!NT_STATUS_IS_OK(status)) {
146                 d_fprintf(stderr, "ERROR: could not store int32 key '%s': %s\n",
147                           keyname, nt_errstr(status));
148                 return -1;
149         }
150
151         return 0;
152 }
153
154 static int dbwrap_tool_store_uint32(struct db_context *db,
155                                     const char *keyname,
156                                     const char *data)
157 {
158         NTSTATUS status;
159         uint32_t value = (uint32_t)strtol(data, NULL, 10);
160
161         if (dbwrap_is_persistent(db)) {
162                 status = dbwrap_trans_store_uint32_bystring(db, keyname, value);
163         } else {
164                 status = dbwrap_store_uint32_bystring(db, keyname, value);
165         }
166         if (!NT_STATUS_IS_OK(status)) {
167                 d_fprintf(stderr,
168                           "ERROR: could not store uint32 key '%s': %s\n",
169                           keyname, nt_errstr(status));
170                 return -1;
171         }
172
173         return 0;
174 }
175
176 static int dbwrap_tool_store_string(struct db_context *db,
177                                     const char *keyname,
178                                     const char *data)
179 {
180         NTSTATUS status;
181         TDB_DATA tdbdata;
182
183         tdbdata = string_term_tdb_data(data);
184
185         if (dbwrap_is_persistent(db)) {
186                 status = dbwrap_trans_store_bystring(db, keyname,
187                                                      tdbdata,
188                                                      TDB_REPLACE);
189         } else {
190                 status = dbwrap_store_bystring(db, keyname,
191                                               tdbdata,
192                                               TDB_REPLACE);
193         }
194         if (!NT_STATUS_IS_OK(status)) {
195                 d_fprintf(stderr,
196                           "ERROR: could not store string key '%s': %s\n",
197                           keyname, nt_errstr(status));
198                 return -1;
199         }
200
201         return 0;
202 }
203
204 static int dbwrap_tool_store_hex(struct db_context *db,
205                                     const char *keyname,
206                                     const char *data)
207 {
208         NTSTATUS status;
209         DATA_BLOB datablob;
210         TDB_DATA tdbdata;
211         TALLOC_CTX *tmp_ctx = talloc_stackframe();
212
213         datablob = strhex_to_data_blob(tmp_ctx, data);
214         if(strlen(data) > 0 && datablob.length == 0) {
215                 d_fprintf(stderr,
216                           "ERROR: could not convert hex string to data blob\n"
217                           "       Not a valid hex string?\n");
218                 talloc_free(tmp_ctx);
219                 return -1;
220         }
221
222         tdbdata.dptr = (unsigned char *)datablob.data;
223         tdbdata.dsize = datablob.length;
224
225         if (dbwrap_is_persistent(db)) {
226                 status = dbwrap_trans_store_bystring(db, keyname,
227                                                      tdbdata,
228                                                      TDB_REPLACE);
229         } else {
230                 status = dbwrap_store_bystring(db, keyname,
231                                                tdbdata,
232                                                TDB_REPLACE);
233         }
234         if (!NT_STATUS_IS_OK(status)) {
235                 d_fprintf(stderr,
236                           "ERROR: could not store string key '%s': %s\n",
237                           keyname, nt_errstr(status));
238                 talloc_free(tmp_ctx);
239                 return -1;
240         }
241
242         talloc_free(tmp_ctx);
243         return 0;
244 }
245
246 static int dbwrap_tool_delete(struct db_context *db,
247                               const char *keyname,
248                               const char *data)
249 {
250         NTSTATUS status;
251
252         if (dbwrap_is_persistent(db)) {
253                 status = dbwrap_trans_delete_bystring(db, keyname);
254         } else {
255                 status = dbwrap_delete_bystring(db, keyname);
256         }
257
258         if (!NT_STATUS_IS_OK(status)) {
259                 d_fprintf(stderr, "ERROR deleting record %s : %s\n",
260                           keyname, nt_errstr(status));
261                 return -1;
262         }
263
264         return 0;
265 }
266
267 static int dbwrap_tool_exists(struct db_context *db,
268                               const char *keyname,
269                               const char *data)
270 {
271         bool result;
272
273         result = dbwrap_exists(db, string_term_tdb_data(keyname));
274
275         if (result) {
276                 d_fprintf(stdout, "Key %s exists\n", keyname);
277         } else {
278                 d_fprintf(stdout, "Key %s does not exist\n", keyname);
279         }
280
281         return (result)?0:1;
282 }
283
284 /**
285  * dbwrap_tool_erase: erase the whole data base
286  * the keyname argument is not used.
287  */
288 static int dbwrap_tool_erase(struct db_context *db,
289                              const char *keyname,
290                              const char *data)
291 {
292         int ret;
293
294         ret = dbwrap_wipe(db);
295
296         if (ret != 0) {
297                 d_fprintf(stderr, "ERROR erasing the database\n");
298                 return -1;
299         }
300
301         return 0;
302 }
303
304 static int listkey_fn(struct db_record *rec, void *private_data)
305 {
306         TDB_DATA key = dbwrap_record_get_key(rec);
307         size_t length = key.dsize;
308         unsigned char *p = (unsigned char *)key.dptr;
309
310         while (length--) {
311                 if (isprint(*p) && !strchr("\"\\", *p)) {
312                         d_printf("%c", *p);
313                 } else {
314                         d_printf("\\%02X", *p);
315                 }
316                 p++;
317         }
318
319         d_printf("\n");
320
321         return 0;
322 }
323
324 static int dbwrap_tool_listkeys(struct db_context *db,
325                                 const char *keyname,
326                                 const char *data)
327 {
328         NTSTATUS status;
329
330         status = dbwrap_traverse_read(db, listkey_fn, NULL, NULL);
331
332         if (!NT_STATUS_IS_OK(status)) {
333                 d_fprintf(stderr, "ERROR listing db keys\n");
334                 return -1;
335         }
336
337         return 0;
338 }
339
340 struct dbwrap_op_dispatch_table {
341         enum dbwrap_op op;
342         enum dbwrap_type type;
343         int (*cmd)(struct db_context *db,
344                    const char *keyname,
345                    const char *data);
346 };
347
348 struct dbwrap_op_dispatch_table dispatch_table[] = {
349         { OP_FETCH,  TYPE_INT32,  dbwrap_tool_fetch_int32 },
350         { OP_FETCH,  TYPE_UINT32, dbwrap_tool_fetch_uint32 },
351         { OP_FETCH,  TYPE_STRING, dbwrap_tool_fetch_string },
352         { OP_FETCH,  TYPE_HEX,    dbwrap_tool_fetch_hex },
353         { OP_STORE,  TYPE_INT32,  dbwrap_tool_store_int32 },
354         { OP_STORE,  TYPE_UINT32, dbwrap_tool_store_uint32 },
355         { OP_STORE,  TYPE_STRING, dbwrap_tool_store_string },
356         { OP_STORE,  TYPE_HEX,    dbwrap_tool_store_hex },
357         { OP_DELETE, TYPE_INT32,  dbwrap_tool_delete },
358         { OP_ERASE,  TYPE_INT32,  dbwrap_tool_erase },
359         { OP_LISTKEYS, TYPE_INT32, dbwrap_tool_listkeys },
360         { OP_EXISTS, TYPE_STRING, dbwrap_tool_exists },
361         { 0, 0, NULL },
362 };
363
364 int main(int argc, const char **argv)
365 {
366         struct tevent_context *evt_ctx;
367         struct messaging_context *msg_ctx;
368         struct db_context *db;
369
370         uint16_t count;
371
372         const char *dbname;
373         const char *opname;
374         enum dbwrap_op op;
375         const char *keyname = "";
376         const char *keytype = "int32";
377         enum dbwrap_type type;
378         const char *valuestr = "0";
379         int persistent = 0;
380         int non_persistent = 0;
381         int tdb_flags = TDB_DEFAULT;
382
383         TALLOC_CTX *mem_ctx = talloc_stackframe();
384         struct loadparm_context *lp_ctx = NULL;
385
386         int ret = 1;
387         bool ok;
388
389         struct poptOption popt_options[] = {
390                 POPT_AUTOHELP
391                 POPT_COMMON_SAMBA
392                 { "non-persistent", 0, POPT_ARG_NONE, &non_persistent, 0,
393                   "treat the database as non-persistent "
394                   "(CAVEAT: This mode might wipe your database!)",
395                   NULL },
396                 { "persistent", 0, POPT_ARG_NONE, &persistent, 0,
397                   "treat the database as persistent",
398                   NULL },
399                 POPT_COMMON_VERSION
400                 POPT_TABLEEND
401         };
402         int opt;
403         const char **extra_argv;
404         int extra_argc = 0;
405         poptContext pc;
406
407         smb_init_locale();
408
409         setup_logging(argv[0], DEBUG_DEFAULT_STDERR);
410
411         ok = samba_cmdline_init(mem_ctx,
412                                 SAMBA_CMDLINE_CONFIG_CLIENT,
413                                 false /* require_smbconf */);
414         if (!ok) {
415                 DBG_ERR("Failed to init cmdline parser!\n");
416                 TALLOC_FREE(mem_ctx);
417                 exit(1);
418         }
419         lp_ctx = samba_cmdline_get_lp_ctx();
420         lpcfg_set_cmdline(lp_ctx, "log level", "0");
421
422         pc = samba_popt_get_context(getprogname(),
423                                     argc,
424                                     argv,
425                                     popt_options,
426                                     POPT_CONTEXT_KEEP_FIRST);
427         if (!ok) {
428                 DBG_ERR("Failed to setup popt context!\n");
429                 TALLOC_FREE(mem_ctx);
430                 exit(1);
431         }
432
433         while ((opt = poptGetNextOpt(pc)) != -1) {
434                 switch (opt) {
435                 default:
436                         fprintf(stderr, "Invalid option %s: %s\n",
437                                 poptBadOption(pc, 0), poptStrerror(opt));
438                         goto done;
439                 }
440         }
441
442         /* setup the remaining options for the main program to use */
443         extra_argv = poptGetArgs(pc);
444         if (extra_argv) {
445                 extra_argv++;
446                 while (extra_argv[extra_argc]) extra_argc++;
447         }
448
449         if ((extra_argc < 2) || (extra_argc > 5)) {
450                 d_fprintf(stderr,
451                           "USAGE: %s [options] <database> <op> [<key> [<type> "
452                           "[<value>]]]\n"
453                           "       ops: fetch, store, delete, exists, "
454                           "erase, listkeys\n"
455                           "       types: int32, uint32, string, hex\n",
456                          argv[0]);
457                 goto done;
458         }
459
460         if ((persistent + non_persistent) != 1) {
461                 d_fprintf(stderr, "ERROR: you must specify exactly one "
462                           "of --persistent and --non-persistent\n");
463                 goto done;
464         }
465         if (non_persistent == 1) {
466                 tdb_flags |= TDB_CLEAR_IF_FIRST;
467         }
468
469         dbname = extra_argv[0];
470         opname = extra_argv[1];
471
472         if (strcmp(opname, "store") == 0) {
473                 if (extra_argc != 5) {
474                         d_fprintf(stderr, "ERROR: operation 'store' requires "
475                                   "value argument\n");
476                         goto done;
477                 }
478                 valuestr = extra_argv[4];
479                 keytype = extra_argv[3];
480                 keyname = extra_argv[2];
481                 op = OP_STORE;
482         } else if (strcmp(opname, "fetch") == 0) {
483                 if (extra_argc != 4) {
484                         d_fprintf(stderr, "ERROR: operation 'fetch' requires "
485                                   "type but not value argument\n");
486                         goto done;
487                 }
488                 op = OP_FETCH;
489                 keytype = extra_argv[3];
490                 keyname = extra_argv[2];
491         } else if (strcmp(opname, "delete") == 0) {
492                 if (extra_argc != 3) {
493                         d_fprintf(stderr, "ERROR: operation 'delete' does "
494                                   "not allow type nor value argument\n");
495                         goto done;
496                 }
497                 keyname = extra_argv[2];
498                 op = OP_DELETE;
499         } else if (strcmp(opname, "erase") == 0) {
500                 if (extra_argc != 2) {
501                         d_fprintf(stderr, "ERROR: operation 'erase' does "
502                                   "not take a key argument\n");
503                         goto done;
504                 }
505                 op = OP_ERASE;
506         } else if (strcmp(opname, "listkeys") == 0) {
507                 if (extra_argc != 2) {
508                         d_fprintf(stderr, "ERROR: operation 'listkeys' does "
509                                   "not take a key argument\n");
510                         goto done;
511                 }
512                 op = OP_LISTKEYS;
513         } else if (strcmp(opname, "exists") == 0) {
514                 if (extra_argc != 3) {
515                         d_fprintf(stderr, "ERROR: operation 'exists' does "
516                                   "not allow type nor value argument\n");
517                         goto done;
518                 }
519                 keyname = extra_argv[2];
520                 op = OP_EXISTS;
521                 keytype = "string";
522         } else {
523                 d_fprintf(stderr,
524                           "ERROR: invalid op '%s' specified\n"
525                           "       supported ops: fetch, store, delete, exists, "
526                           "erase, listkeys\n",
527                           opname);
528                 goto done;
529         }
530
531         if (strcmp(keytype, "int32") == 0) {
532                 type = TYPE_INT32;
533         } else if (strcmp(keytype, "uint32") == 0) {
534                 type = TYPE_UINT32;
535         } else if (strcmp(keytype, "string") == 0) {
536                 type = TYPE_STRING;
537         } else if (strcmp(keytype, "hex") == 0) {
538                 type = TYPE_HEX;
539         } else if (strcmp(keytype, "none") == 0) {
540                 type = TYPE_NONE;
541         } else {
542                 d_fprintf(stderr, "ERROR: invalid type '%s' specified.\n"
543                                   "       supported types: int32, uint32, "
544                                   "string, hex, none\n",
545                                   keytype);
546                 goto done;
547         }
548
549         evt_ctx = samba_tevent_context_init(mem_ctx);
550         if (evt_ctx == NULL) {
551                 d_fprintf(stderr, "ERROR: could not init event context\n");
552                 goto done;
553         }
554
555         msg_ctx = messaging_init(mem_ctx, evt_ctx);
556         if (msg_ctx == NULL) {
557                 d_fprintf(stderr, "ERROR: could not init messaging context\n");
558                 goto done;
559         }
560
561         switch (op) {
562         case OP_FETCH:
563         case OP_STORE:
564         case OP_DELETE:
565         case OP_ERASE:
566         case OP_LISTKEYS:
567         case OP_EXISTS:
568                 db = db_open(mem_ctx, dbname, 0, tdb_flags, O_RDWR | O_CREAT,
569                              0644, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
570                 if (db == NULL) {
571                         d_fprintf(stderr, "ERROR: could not open dbname\n");
572                         goto done;
573                 }
574                 break;
575         default:
576                 db = NULL;
577                 break;
578         }
579
580         for (count = 0; dispatch_table[count].cmd != NULL; count++) {
581                 if ((op == dispatch_table[count].op) &&
582                     (type == dispatch_table[count].type))
583                 {
584                         ret = dispatch_table[count].cmd(db, keyname, valuestr);
585                         break;
586                 }
587         }
588
589 done:
590         poptFreeContext(pc);
591         TALLOC_FREE(mem_ctx);
592         return ret;
593 }