1/* 2 * Unix SMB/CIFS implementation. 3 * Shell around net rpc subcommands 4 * Copyright (C) Volker Lendecke 2006 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 22#include "includes.h" 23#include "utils/net.h" 24 25static NTSTATUS rpc_sh_info(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx, 26 struct rpc_pipe_client *pipe_hnd, 27 int argc, const char **argv) 28{ 29 return rpc_info_internals(ctx->domain_sid, ctx->domain_name, 30 ctx->cli, pipe_hnd, mem_ctx, 31 argc, argv); 32} 33 34static struct rpc_sh_ctx *this_ctx; 35 36static char **completion_fn(const char *text, int start, int end) 37{ 38 char **cmds = NULL; 39 int n_cmds = 0; 40 struct rpc_sh_cmd *c; 41 42 if (start != 0) { 43 return NULL; 44 } 45 46 ADD_TO_ARRAY(NULL, char *, SMB_STRDUP(text), &cmds, &n_cmds); 47 48 for (c = this_ctx->cmds; c->name != NULL; c++) { 49 BOOL match = (strncmp(text, c->name, strlen(text)) == 0); 50 51 if (match) { 52 ADD_TO_ARRAY(NULL, char *, SMB_STRDUP(c->name), 53 &cmds, &n_cmds); 54 } 55 } 56 57 if (n_cmds == 2) { 58 SAFE_FREE(cmds[0]); 59 cmds[0] = cmds[1]; 60 n_cmds -= 1; 61 } 62 63 ADD_TO_ARRAY(NULL, char *, NULL, &cmds, &n_cmds); 64 return cmds; 65} 66 67static NTSTATUS net_sh_run(struct rpc_sh_ctx *ctx, struct rpc_sh_cmd *cmd, 68 int argc, const char **argv) 69{ 70 TALLOC_CTX *mem_ctx; 71 struct rpc_pipe_client *pipe_hnd; 72 NTSTATUS status; 73 74 mem_ctx = talloc_new(ctx); 75 if (mem_ctx == NULL) { 76 d_fprintf(stderr, "talloc_new failed\n"); 77 return NT_STATUS_NO_MEMORY; 78 } 79 80 pipe_hnd = cli_rpc_pipe_open_noauth(ctx->cli, cmd->pipe_idx, &status); 81 if (pipe_hnd == NULL) { 82 d_fprintf(stderr, "Could not open pipe: %s\n", 83 nt_errstr(status)); 84 return status; 85 } 86 87 status = cmd->fn(mem_ctx, ctx, pipe_hnd, argc, argv); 88 89 cli_rpc_pipe_close(pipe_hnd); 90 91 talloc_destroy(mem_ctx); 92 93 return status; 94} 95 96static BOOL net_sh_process(struct rpc_sh_ctx *ctx, 97 int argc, const char **argv) 98{ 99 struct rpc_sh_cmd *c; 100 struct rpc_sh_ctx *new_ctx; 101 NTSTATUS status; 102 103 if (argc == 0) { 104 return True; 105 } 106 107 if (ctx == this_ctx) { 108 109 /* We've been called from the cmd line */ 110 if (strequal(argv[0], "..") && 111 (this_ctx->parent != NULL)) { 112 new_ctx = this_ctx->parent; 113 TALLOC_FREE(this_ctx); 114 this_ctx = new_ctx; 115 return True; 116 } 117 } 118 119 if (strequal(argv[0], "exit") || strequal(argv[0], "quit")) { 120 return False; 121 } 122 123 if (strequal(argv[0], "help") || strequal(argv[0], "?")) { 124 for (c = ctx->cmds; c->name != NULL; c++) { 125 if (ctx != this_ctx) { 126 d_printf("%s ", ctx->whoami); 127 } 128 d_printf("%-15s %s\n", c->name, c->help); 129 } 130 return True; 131 } 132 133 for (c = ctx->cmds; c->name != NULL; c++) { 134 if (strequal(c->name, argv[0])) { 135 break; 136 } 137 } 138 139 if (c->name == NULL) { 140 /* None found */ 141 d_fprintf(stderr, "%s: unknown cmd\n", argv[0]); 142 return True; 143 } 144 145 new_ctx = TALLOC_P(ctx, struct rpc_sh_ctx); 146 if (new_ctx == NULL) { 147 d_fprintf(stderr, "talloc failed\n"); 148 return False; 149 } 150 new_ctx->cli = ctx->cli; 151 new_ctx->whoami = talloc_asprintf(new_ctx, "%s %s", 152 ctx->whoami, c->name); 153 new_ctx->thiscmd = talloc_strdup(new_ctx, c->name); 154 155 if (c->sub != NULL) { 156 new_ctx->cmds = c->sub(new_ctx, ctx); 157 } else { 158 new_ctx->cmds = NULL; 159 } 160 161 new_ctx->parent = ctx; 162 new_ctx->domain_name = ctx->domain_name; 163 new_ctx->domain_sid = ctx->domain_sid; 164 165 argc -= 1; 166 argv += 1; 167 168 if (c->sub != NULL) { 169 if (argc == 0) { 170 this_ctx = new_ctx; 171 return True; 172 } 173 return net_sh_process(new_ctx, argc, argv); 174 } 175 176 status = net_sh_run(new_ctx, c, argc, argv); 177 178 if (!NT_STATUS_IS_OK(status)) { 179 d_fprintf(stderr, "%s failed: %s\n", new_ctx->whoami, 180 nt_errstr(status)); 181 } 182 183 return True; 184} 185 186static struct rpc_sh_cmd sh_cmds[6] = { 187 188 { "info", NULL, PI_SAMR, rpc_sh_info, 189 "Print information about the domain connected to" }, 190 191 { "rights", net_rpc_rights_cmds, 0, NULL, 192 "List/Grant/Revoke user rights" }, 193 194 { "share", net_rpc_share_cmds, 0, NULL, 195 "List/Add/Remove etc shares" }, 196 197 { "user", net_rpc_user_cmds, 0, NULL, 198 "List/Add/Remove user info" }, 199 200 { "account", net_rpc_acct_cmds, 0, NULL, 201 "Show/Change account policy settings" }, 202 203 { NULL, NULL, 0, NULL, NULL } 204}; 205 206int net_rpc_shell(int argc, const char **argv) 207{ 208 NTSTATUS status; 209 struct rpc_sh_ctx *ctx; 210 211 if (argc != 0) { 212 d_fprintf(stderr, "usage: net rpc shell\n"); 213 return -1; 214 } 215 216 ctx = TALLOC_P(NULL, struct rpc_sh_ctx); 217 if (ctx == NULL) { 218 d_fprintf(stderr, "talloc failed\n"); 219 return -1; 220 } 221 222 ctx->cli = net_make_ipc_connection(0); 223 if (ctx->cli == NULL) { 224 d_fprintf(stderr, "Could not open connection\n"); 225 return -1; 226 } 227 228 ctx->cmds = sh_cmds; 229 ctx->whoami = "net rpc"; 230 ctx->parent = NULL; 231 232 status = net_get_remote_domain_sid(ctx->cli, ctx, &ctx->domain_sid, 233 &ctx->domain_name); 234 if (!NT_STATUS_IS_OK(status)) { 235 return -1; 236 } 237 238 d_printf("Talking to domain %s (%s)\n", ctx->domain_name, 239 sid_string_static(ctx->domain_sid)); 240 241 this_ctx = ctx; 242 243 while(1) { 244 char *prompt; 245 char *line; 246 int ret; 247 248 asprintf(&prompt, "%s> ", this_ctx->whoami); 249 250 line = smb_readline(prompt, NULL, completion_fn); 251 SAFE_FREE(prompt); 252 253 if (line == NULL) { 254 break; 255 } 256 257 ret = poptParseArgvString(line, &argc, &argv); 258 if (ret == POPT_ERROR_NOARG) { 259 continue; 260 } 261 if (ret != 0) { 262 d_fprintf(stderr, "cmdline invalid: %s\n", 263 poptStrerror(ret)); 264 return False; 265 } 266 267 if ((line[0] != '\n') && 268 (!net_sh_process(this_ctx, argc, argv))) { 269 break; 270 } 271 } 272 273 cli_shutdown(ctx->cli); 274 275 TALLOC_FREE(ctx); 276 277 return 0; 278} 279