root/source4/lib/registry/tools/regshell.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cmd_info
  2. cmd_predef
  3. cmd_pwd
  4. cmd_set
  5. cmd_ck
  6. cmd_print
  7. cmd_ls
  8. cmd_mkkey
  9. cmd_rmkey
  10. cmd_rmval
  11. cmd_exit
  12. cmd_help
  13. process_cmd
  14. reg_complete_command
  15. reg_complete_key
  16. reg_completion
  17. main

   1 /*
   2    Unix SMB/CIFS implementation.
   3    simple registry frontend
   4 
   5    Copyright (C) Jelmer Vernooij 2004-2007
   6 
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11 
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16 
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "lib/registry/registry.h"
  23 #include "lib/cmdline/popt_common.h"
  24 #include "lib/events/events.h"
  25 #include "system/time.h"
  26 #include "lib/smbreadline/smbreadline.h"
  27 #include "librpc/gen_ndr/ndr_security.h"
  28 #include "lib/registry/tools/common.h"
  29 #include "param/param.h"
  30 
  31 struct regshell_context {
  32         struct registry_context *registry;
  33         const char *path;
  34         struct registry_key *current;
  35 };
  36 
  37 /* *
  38  * ck/cd - change key
  39  * ls - list values/keys
  40  * rmval/rm - remove value
  41  * rmkey/rmdir - remove key
  42  * mkkey/mkdir - make key
  43  * ch - change hive
  44  * info - show key info
  45  * save - save hive
  46  * print - print value
  47  * help
  48  * exit
  49  */
  50 
  51 static WERROR cmd_info(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
  52 {
  53         struct security_descriptor *sec_desc = NULL;
  54         time_t last_mod;
  55         WERROR error;
  56         const char *classname = NULL;
  57         NTTIME last_change;
  58         uint32_t max_subkeynamelen;
  59         uint32_t max_valnamelen;
  60         uint32_t max_valbufsize;
  61         uint32_t num_subkeys;
  62         uint32_t num_values;
  63 
  64         error = reg_key_get_info(ctx, ctx->current, &classname, &num_subkeys, &num_values,
  65                                  &last_change, &max_subkeynamelen, &max_valnamelen, &max_valbufsize);
  66         if (!W_ERROR_IS_OK(error)) {
  67                 printf("Error getting key info: %s\n", win_errstr(error));
  68                 return error;
  69         }
  70 
  71 
  72         printf("Name: %s\n", strchr(ctx->path, '\\')?strrchr(ctx->path, '\\')+1:
  73                    ctx->path);
  74         printf("Full path: %s\n", ctx->path);
  75         if (classname != NULL)
  76                 printf("Key Class: %s\n", classname);
  77         last_mod = nt_time_to_unix(last_change);
  78         printf("Time Last Modified: %s\n", ctime(&last_mod));
  79         printf("Number of subkeys: %d\n", num_subkeys);
  80         printf("Number of values: %d\n", num_values);
  81 
  82         if (max_valnamelen > 0)
  83                 printf("Maximum value name length: %d\n", max_valnamelen);
  84 
  85         if (max_valbufsize > 0)
  86                 printf("Maximum value data length: %d\n", max_valbufsize);
  87 
  88         if (max_subkeynamelen > 0)
  89                 printf("Maximum sub key name length: %d\n", max_subkeynamelen);
  90 
  91         error = reg_get_sec_desc(ctx, ctx->current, &sec_desc);
  92         if (!W_ERROR_IS_OK(error)) {
  93                 printf("Error getting security descriptor\n");
  94                 return error;
  95         }
  96         ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor,
  97                         "Security", sec_desc);
  98         talloc_free(sec_desc);
  99 
 100         return WERR_OK;
 101 }
 102 
 103 static WERROR cmd_predef(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 104 {
 105         struct registry_key *ret = NULL;
 106         if (argc < 2) {
 107                 fprintf(stderr, "Usage: predef predefined-key-name\n");
 108         } else if (!ctx) {
 109                 fprintf(stderr, "No full registry loaded, no predefined keys defined\n");
 110         } else {
 111                 WERROR error = reg_get_predefined_key_by_name(ctx->registry,
 112                                                               argv[1], &ret);
 113 
 114                 if (!W_ERROR_IS_OK(error)) {
 115                         fprintf(stderr, "Error opening predefined key %s: %s\n",
 116                                 argv[1], win_errstr(error));
 117                         return error;
 118                 }
 119 
 120                 ctx->path = strupper_talloc(ctx, argv[1]);
 121                 ctx->current = ret;
 122         }
 123 
 124         return WERR_OK;
 125 }
 126 
 127 static WERROR cmd_pwd(struct regshell_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 128                       int argc, char **argv)
 129 {
 130         printf("%s\n", ctx->path);
 131         return WERR_OK;
 132 }
 133 
 134 static WERROR cmd_set(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 135 {
 136         struct registry_value val;
 137         WERROR error;
 138 
 139         if (argc < 4) {
 140                 fprintf(stderr, "Usage: set value-name type value\n");
 141                 return WERR_INVALID_PARAM;
 142         }
 143 
 144         if (!reg_string_to_val(ctx, lp_iconv_convenience(cmdline_lp_ctx), 
 145                                argv[2], argv[3], &val.data_type,
 146                                &val.data)) {
 147                 fprintf(stderr, "Unable to interpret data\n");
 148                 return WERR_INVALID_PARAM;
 149         }
 150 
 151         error = reg_val_set(ctx->current, argv[1], val.data_type, val.data);
 152         if (!W_ERROR_IS_OK(error)) {
 153                 fprintf(stderr, "Error setting value: %s\n", win_errstr(error));
 154                 return error;
 155         }
 156 
 157         return WERR_OK;
 158 }
 159 
 160 static WERROR cmd_ck(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 161 {
 162         struct registry_key *nkey = NULL;
 163         WERROR error;
 164 
 165         if(argc == 2) {
 166                 error = reg_open_key(ctx->registry, ctx->current, argv[1],
 167                                      &nkey);
 168                 if(!W_ERROR_IS_OK(error)) {
 169                         DEBUG(0, ("Error opening specified key: %s\n",
 170                                 win_errstr(error)));
 171                         return error;
 172                 }
 173 
 174                 ctx->path = talloc_asprintf(ctx, "%s\\%s", ctx->path, argv[1]);
 175                 ctx->current = nkey;
 176         }
 177         printf("New path is: %s\n", ctx->path);
 178 
 179         return WERR_OK;
 180 }
 181 
 182 static WERROR cmd_print(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 183 {
 184         uint32_t value_type;
 185         DATA_BLOB value_data;
 186         WERROR error;
 187 
 188         if (argc != 2) {
 189                 fprintf(stderr, "Usage: print <valuename>\n");
 190                 return WERR_INVALID_PARAM;
 191         }
 192 
 193         error = reg_key_get_value_by_name(ctx, ctx->current, argv[1],
 194                                           &value_type, &value_data);
 195         if (!W_ERROR_IS_OK(error)) {
 196                 fprintf(stderr, "No such value '%s'\n", argv[1]);
 197                 return error;
 198         }
 199 
 200         printf("%s\n%s\n", str_regtype(value_type),
 201                    reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx), value_type, value_data));
 202 
 203         return WERR_OK;
 204 }
 205 
 206 static WERROR cmd_ls(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 207 {
 208         int i;
 209         WERROR error;
 210         uint32_t valuetype;
 211         DATA_BLOB valuedata;
 212         const char *name = NULL;
 213 
 214         for (i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(ctx,
 215                                                                       ctx->current,
 216                                                                       i,
 217                                                                       &name,
 218                                                                       NULL,
 219                                                                       NULL)); i++) {
 220                 printf("K %s\n", name);
 221         }
 222 
 223         if (!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
 224                 fprintf(stderr, "Error occured while browsing thru keys: %s\n",
 225                         win_errstr(error));
 226                 return error;
 227         }
 228 
 229         for (i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(ctx,
 230                 ctx->current, i, &name, &valuetype, &valuedata)); i++)
 231                 printf("V \"%s\" %s %s\n", name, str_regtype(valuetype),
 232                            reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx), valuetype, valuedata));
 233 
 234         return WERR_OK;
 235 }
 236 static WERROR cmd_mkkey(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 237 {
 238         struct registry_key *tmp;
 239         WERROR error;
 240 
 241         if(argc < 2) {
 242                 fprintf(stderr, "Usage: mkkey <keyname>\n");
 243                 return WERR_INVALID_PARAM;
 244         }
 245 
 246         error = reg_key_add_name(ctx, ctx->current, argv[1], 0, NULL, &tmp);
 247 
 248         if (!W_ERROR_IS_OK(error)) {
 249                 fprintf(stderr, "Error adding new subkey '%s': %s\n", argv[1],
 250                         win_errstr(error));
 251                 return error;
 252         }
 253 
 254         return WERR_OK;
 255 }
 256 
 257 static WERROR cmd_rmkey(struct regshell_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 258                         int argc, char **argv)
 259 {
 260         WERROR error;
 261 
 262         if(argc < 2) {
 263                 fprintf(stderr, "Usage: rmkey <name>\n");
 264                 return WERR_INVALID_PARAM;
 265         }
 266 
 267         error = reg_key_del(ctx->current, argv[1]);
 268         if(!W_ERROR_IS_OK(error)) {
 269                 fprintf(stderr, "Error deleting '%s'\n", argv[1]);
 270                 return error;
 271         } else {
 272                 fprintf(stderr, "Successfully deleted '%s'\n", argv[1]);
 273         }
 274 
 275         return WERR_OK;
 276 }
 277 
 278 static WERROR cmd_rmval(struct regshell_context *ctx, int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 279 {
 280         WERROR error;
 281 
 282         if(argc < 2) {
 283                 fprintf(stderr, "Usage: rmval <valuename>\n");
 284                 return WERR_INVALID_PARAM;
 285         }
 286 
 287         error = reg_del_value(ctx->current, argv[1]);
 288         if(!W_ERROR_IS_OK(error)) {
 289                 fprintf(stderr, "Error deleting value '%s'\n", argv[1]);
 290                 return error;
 291         } else {
 292                 fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]);
 293         }
 294 
 295         return WERR_OK;
 296 }
 297 
 298 _NORETURN_ static WERROR cmd_exit(struct regshell_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 299                                   int argc, char **argv)
 300 {
 301         exit(0);
 302         return WERR_OK;
 303 }
 304 
 305 static WERROR cmd_help(struct regshell_context *ctx, int, char **);
 306 
 307 static struct {
 308         const char *name;
 309         const char *alias;
 310         const char *help;
 311         WERROR (*handle)(struct regshell_context *ctx, int argc, char **argv);
 312 } regshell_cmds[] = {
 313         {"ck", "cd", "Change current key", cmd_ck },
 314         {"info", "i", "Show detailed information of a key", cmd_info },
 315         {"list", "ls", "List values/keys in current key", cmd_ls },
 316         {"print", "p", "Print value", cmd_print },
 317         {"mkkey", "mkdir", "Make new key", cmd_mkkey },
 318         {"rmval", "rm", "Remove value", cmd_rmval },
 319         {"rmkey", "rmdir", "Remove key", cmd_rmkey },
 320         {"pwd", "pwk", "Printing current key", cmd_pwd },
 321         {"set", "update", "Update value", cmd_set },
 322         {"help", "?", "Help", cmd_help },
 323         {"exit", "quit", "Exit", cmd_exit },
 324         {"predef", "predefined", "Go to predefined key", cmd_predef },
 325         {NULL }
 326 };
 327 
 328 static WERROR cmd_help(struct regshell_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 329                        int argc, char **argv)
 330 {
 331         int i;
 332         printf("Available commands:\n");
 333         for(i = 0; regshell_cmds[i].name; i++) {
 334                 printf("%s - %s\n", regshell_cmds[i].name,
 335                         regshell_cmds[i].help);
 336         }
 337         return WERR_OK;
 338 }
 339 
 340 static WERROR process_cmd(struct regshell_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 341                           char *line)
 342 {
 343         int argc;
 344         char **argv = NULL;
 345         int ret, i;
 346 
 347         if ((ret = poptParseArgvString(line, &argc, (const char ***) &argv)) != 0) {
 348                 fprintf(stderr, "regshell: %s\n", poptStrerror(ret));
 349                 return WERR_INVALID_PARAM;
 350         }
 351 
 352         for(i = 0; regshell_cmds[i].name; i++) {
 353                 if(!strcmp(regshell_cmds[i].name, argv[0]) ||
 354                    (regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) {
 355                         return regshell_cmds[i].handle(ctx, argc, argv);
 356                 }
 357         }
 358 
 359         fprintf(stderr, "No such command '%s'\n", argv[0]);
 360 
 361         return WERR_INVALID_PARAM;
 362 }
 363 
 364 #define MAX_COMPLETIONS 100
 365 
 366 static struct registry_key *current_key = NULL;
 367 
 368 static char **reg_complete_command(const char *text, int start, int end)
     /* [<][>][^][v][top][bottom][index][help] */
 369 {
 370         /* Complete command */
 371         char **matches;
 372         int i, len, samelen=0, count=1;
 373 
 374         matches = malloc_array_p(char *, MAX_COMPLETIONS);
 375         if (!matches) return NULL;
 376         matches[0] = NULL;
 377 
 378         len = strlen(text);
 379         for (i=0;regshell_cmds[i].handle && count < MAX_COMPLETIONS-1;i++) {
 380                 if (strncmp(text, regshell_cmds[i].name, len) == 0) {
 381                         matches[count] = strdup(regshell_cmds[i].name);
 382                         if (!matches[count])
 383                                 goto cleanup;
 384                         if (count == 1)
 385                                 samelen = strlen(matches[count]);
 386                         else
 387                                 while (strncmp(matches[count], matches[count-1], samelen) != 0)
 388                                         samelen--;
 389                         count++;
 390                 }
 391         }
 392 
 393         switch (count) {
 394         case 0: /* should never happen */
 395         case 1:
 396                 goto cleanup;
 397         case 2:
 398                 matches[0] = strdup(matches[1]);
 399                 break;
 400         default:
 401                 matches[0] = strndup(matches[1], samelen);
 402         }
 403         matches[count] = NULL;
 404         return matches;
 405 
 406 cleanup:
 407         count--;
 408         while (count >= 0) {
 409                 free(matches[count]);
 410                 count--;
 411         }
 412         free(matches);
 413         return NULL;
 414 }
 415 
 416 static char **reg_complete_key(const char *text, int start, int end)
     /* [<][>][^][v][top][bottom][index][help] */
 417 {
 418         struct registry_key *base;
 419         const char *subkeyname;
 420         int i, j = 1;
 421         int samelen = 0;
 422         int len;
 423         char **matches;
 424         const char *base_n = "";
 425         TALLOC_CTX *mem_ctx;
 426         WERROR status;
 427 
 428         matches = malloc_array_p(char *, MAX_COMPLETIONS);
 429         if (!matches) return NULL;
 430         matches[0] = NULL;
 431         mem_ctx = talloc_init("completion");
 432 
 433         base = current_key;
 434 
 435         len = strlen(text);
 436         for(i = 0; j < MAX_COMPLETIONS-1; i++) {
 437                 status = reg_key_get_subkey_by_index(mem_ctx, base, i,
 438                                              &subkeyname, NULL, NULL);
 439                 if(W_ERROR_IS_OK(status)) {
 440                         if(!strncmp(text, subkeyname, len)) {
 441                                 matches[j] = strdup(subkeyname);
 442                                 j++;
 443 
 444                                 if (j == 1)
 445                                         samelen = strlen(matches[j]);
 446                                 else
 447                                         while (strncmp(matches[j], matches[j-1], samelen) != 0)
 448                                                 samelen--;
 449                         }
 450                 } else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) {
 451                         break;
 452                 } else {
 453                         printf("Error creating completion list: %s\n",
 454                                 win_errstr(status));
 455                         talloc_free(mem_ctx);
 456                         return NULL;
 457                 }
 458         }
 459 
 460         if (j == 1) { /* No matches at all */
 461                 SAFE_FREE(matches);
 462                 talloc_free(mem_ctx);
 463                 return NULL;
 464         }
 465 
 466         if (j == 2) { /* Exact match */
 467                 asprintf(&matches[0], "%s%s", base_n, matches[1]);
 468         } else {
 469                 asprintf(&matches[0], "%s%s", base_n,
 470                                 talloc_strndup(mem_ctx, matches[1], samelen));
 471         }
 472         talloc_free(mem_ctx);
 473 
 474         matches[j] = NULL;
 475         return matches;
 476 }
 477 
 478 static char **reg_completion(const char *text, int start, int end)
     /* [<][>][^][v][top][bottom][index][help] */
 479 {
 480         smb_readline_ca_char(' ');
 481 
 482         if (start == 0) {
 483                 return reg_complete_command(text, start, end);
 484         } else {
 485                 return reg_complete_key(text, start, end);
 486         }
 487 }
 488 
 489 int main(int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 490 {
 491         int opt;
 492         const char *file = NULL;
 493         poptContext pc;
 494         const char *remote = NULL;
 495         struct regshell_context *ctx;
 496         struct tevent_context *ev_ctx;
 497         bool ret = true;
 498         struct poptOption long_options[] = {
 499                 POPT_AUTOHELP
 500                 {"file", 'F', POPT_ARG_STRING, &file, 0, "open hive file", NULL },
 501                 {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
 502                 POPT_COMMON_SAMBA
 503                 POPT_COMMON_CREDENTIALS
 504                 POPT_COMMON_VERSION
 505                 { NULL }
 506         };
 507 
 508         pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
 509 
 510         while((opt = poptGetNextOpt(pc)) != -1) {
 511         }
 512 
 513         ctx = talloc_zero(NULL, struct regshell_context);
 514 
 515         ev_ctx = s4_event_context_init(ctx);
 516 
 517         if (remote != NULL) {
 518                 ctx->registry = reg_common_open_remote(remote, ev_ctx,
 519                                          cmdline_lp_ctx, cmdline_credentials);
 520         } else if (file != NULL) {
 521                 ctx->current = reg_common_open_file(file, ev_ctx, cmdline_lp_ctx, cmdline_credentials);
 522                 if (ctx->current == NULL)
 523                         return 1;
 524                 ctx->registry = ctx->current->context;
 525                 ctx->path = talloc_strdup(ctx, "");
 526         } else {
 527                 ctx->registry = reg_common_open_local(cmdline_credentials, ev_ctx, cmdline_lp_ctx);
 528         }
 529 
 530         if (ctx->registry == NULL)
 531                 return 1;
 532 
 533         if (ctx->current == NULL) {
 534                 int i;
 535 
 536                 for (i = 0; (reg_predefined_keys[i].handle != 0) &&
 537                         (ctx->current == NULL); i++) {
 538                         WERROR err;
 539                         err = reg_get_predefined_key(ctx->registry,
 540                                                      reg_predefined_keys[i].handle,
 541                                                      &ctx->current);
 542                         if (W_ERROR_IS_OK(err)) {
 543                                 ctx->path = talloc_strdup(ctx,
 544                                                           reg_predefined_keys[i].name);
 545                                 break;
 546                         } else {
 547                                 ctx->current = NULL;
 548                         }
 549                 }
 550         }
 551 
 552         if (ctx->current == NULL) {
 553                 fprintf(stderr, "Unable to access any of the predefined keys\n");
 554                 return -1;
 555         }
 556 
 557         poptFreeContext(pc);
 558 
 559         while (true) {
 560                 char *line, *prompt;
 561 
 562                 asprintf(&prompt, "%s> ", ctx->path);
 563 
 564                 current_key = ctx->current;             /* No way to pass a void * pointer
 565                                                            via readline :-( */
 566                 line = smb_readline(prompt, NULL, reg_completion);
 567 
 568                 if (line == NULL) {
 569                         free(prompt);
 570                         break;
 571                 }
 572 
 573                 if (line[0] != '\n') {
 574                         ret = W_ERROR_IS_OK(process_cmd(ctx, line));
 575                 }
 576                 free(line);
 577                 free(prompt);
 578         }
 579         talloc_free(ctx);
 580 
 581         return (ret?0:1);
 582 }

/* [<][>][^][v][top][bottom][index][help] */