2d45a4bb54099efeb686d2aab1d73caf5f219258
[samba.git] / source4 / utils / net / net.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2001 Steve French  (sfrench@us.ibm.com)
5    Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
7    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
8    Copyright (C) 2004 Stefan Metzmacher (metze@samba.org)
9    Copyright (C) 2009 Jelmer Vernooij (jelmer@samba.org)
10
11    Largely rewritten by metze in August 2004
12
13    Originally written by Steve and Jim. Largely rewritten by tridge in
14    November 2001.
15
16    Reworked again by abartlet in December 2001
17
18    This program is free software; you can redistribute it and/or modify
19    it under the terms of the GNU General Public License as published by
20    the Free Software Foundation; either version 3 of the License, or
21    (at your option) any later version.
22    
23    This program is distributed in the hope that it will be useful,
24    but WITHOUT ANY WARRANTY; without even the implied warranty of
25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26    GNU General Public License for more details.
27    
28    You should have received a copy of the GNU General Public License
29    along with this program.  If not, see <http://www.gnu.org/licenses/>.
30 */
31  
32 /*****************************************************/
33 /*                                                   */
34 /*   Distributed SMB/CIFS Server Management Utility  */
35 /*                                                   */
36 /*   The intent was to make the syntax similar       */
37 /*   to the NET utility (first developed in DOS      */
38 /*   with additional interesting & useful functions  */
39 /*   added in later SMB server network operating     */
40 /*   systems).                                       */
41 /*                                                   */
42 /*****************************************************/
43
44 #include <Python.h>
45 #include "includes.h"
46 #include "utils/net/net.h"
47 #include "lib/cmdline/popt_common.h"
48 #include "lib/ldb/include/ldb.h"
49 #include "librpc/rpc/dcerpc.h"
50 #include "param/param.h"
51 #include "lib/events/events.h"
52 #include "auth/credentials/credentials.h"
53 #include "scripting/python/modules.h"
54
55 static PyObject *py_tuple_from_argv(int argc, const char *argv[])
56 {
57         PyObject *l;
58         Py_ssize_t i;
59
60         l = PyTuple_New(argc);
61         if (l == NULL) {
62                 return NULL;
63         }
64
65         for (i = 0; i < argc; i++) {
66                 PyTuple_SetItem(l, i, PyString_FromString(argv[i]));
67         }
68
69         return l;
70 }
71
72 static int py_call_with_string_args(PyObject *self, const char *method, int argc, const char *argv[])
73 {
74         PyObject *ret, *args, *py_method;
75
76         args = py_tuple_from_argv(argc, argv);
77         if (args == NULL) {
78                 PyErr_Print();
79                 return 1;
80         }
81
82         py_method = PyObject_GetAttrString(self, method);
83         if (py_method == NULL) {
84                 PyErr_Print();
85                 return 1;
86         }       
87
88         ret = PyObject_CallObject(py_method, args);
89
90         Py_DECREF(args);
91
92         if (ret == NULL) {
93                 PyErr_Print();
94                 return 1;
95         }
96
97         if (ret == Py_None) {
98                 return 0;
99         } else if (PyInt_Check(ret)) {
100                 return PyInt_AsLong(ret);
101         } else {
102                 fprintf(stderr, "Function return value type unexpected.\n");
103                 return -1;
104         }
105 }
106
107 static PyObject *py_commands(void)
108 {
109         PyObject *netcmd_module, *py_cmds;
110         netcmd_module = PyImport_ImportModule("samba.netcmd");
111         if (netcmd_module == NULL) {
112                 PyErr_Print();
113                 return NULL;
114         }       
115
116         py_cmds = PyObject_GetAttrString(netcmd_module, "commands");
117         if (py_cmds == NULL) {
118                 PyErr_Print();
119                 return NULL;
120         }
121
122         if (!PyDict_Check(py_cmds)) {
123                 d_printf("Python net commands is not a dictionary\n");
124                 return NULL;
125         }
126
127         return py_cmds;
128 }
129
130 /*
131   run a function from a function table. If not found then
132   call the specified usage function 
133 */
134 int net_run_function(struct net_context *ctx,
135                         int argc, const char **argv,
136                         const struct net_functable *functable, 
137                         int (*usage_fn)(struct net_context *ctx, int argc, const char **argv))
138 {
139         int i;
140
141         if (argc == 0) {
142                 return usage_fn(ctx, argc, argv);
143
144         } else if (argc == 1 && strequal(argv[0], "help")) {
145                 return net_help(ctx, functable);
146         }
147
148         for (i=0; functable[i].name; i++) {
149                 if (strcasecmp_m(argv[0], functable[i].name) == 0)
150                         return functable[i].fn(ctx, argc-1, argv+1);
151         }
152
153         d_printf("No command: %s\n", argv[0]);
154         return usage_fn(ctx, argc, argv);
155 }
156
157 /*
158   run a usage function from a function table. If not found then fail
159 */
160 int net_run_usage(struct net_context *ctx,
161                         int argc, const char **argv,
162                         const struct net_functable *functable)
163 {
164         int i;
165         PyObject *py_cmds, *py_cmd;
166
167         for (i=0; functable[i].name; i++) {
168                 if (strcasecmp_m(argv[0], functable[i].name) == 0)
169                         if (functable[i].usage) {
170                                 return functable[i].usage(ctx, argc-1, argv+1);
171                         }
172         }
173
174         py_cmds = py_commands();
175         if (py_cmds == NULL) {
176                 return 1;
177         }
178
179         py_cmd = PyDict_GetItemString(py_cmds, argv[0]);
180         if (py_cmd != NULL) {
181                 return py_call_with_string_args(py_cmd, "usage", argc-1, 
182                                                 argv+1);
183         }
184
185         d_printf("No usage information for command: %s\n", argv[0]);
186
187         return 1;
188 }
189
190
191 /* main function table */
192 static const struct net_functable net_functable[] = {
193         {"password", "change password\n", net_password, net_password_usage},
194         {"time", "get remote server's time\n", net_time, net_time_usage},
195         {"join", "join a domain\n", net_join, net_join_usage},
196         {"samdump", "dump the sam of a domain\n", net_samdump, net_samdump_usage},
197         {"export", "dump the sam of this domain\n", net_export, net_export_usage},
198         {"vampire", "join and syncronise an AD domain onto the local server\n", net_vampire, net_vampire_usage},
199         {"samsync", "synchronise into the local ldb the sam of an NT4 domain\n", net_samsync_ldb, net_samsync_ldb_usage},
200         {"user", "manage user accounts\n", net_user, net_user_usage},
201         {"machinepw", "Get a machine password out of our SAM\n", net_machinepw, net_machinepw_usage},
202         {NULL, NULL, NULL, NULL}
203 };
204
205 static int net_help_builtin(const struct net_functable *ftable)
206 {
207         int i = 0;
208         const char *name = ftable[i].name;
209         const char *desc = ftable[i].desc;
210
211         while (name && desc) {
212                 if (strlen(name) > 7) {
213                         d_printf("\t%s\t%s", name, desc);
214                 } else {
215                         d_printf("\t%s\t\t%s", name, desc);
216                 }
217                 name = ftable[++i].name;
218                 desc = ftable[i].desc;
219         }
220         return 0;
221 }
222
223 static int net_help_python(void)
224 {
225         PyObject *py_cmds;
226         PyObject *key, *value;
227         Py_ssize_t pos = 0;
228
229         py_cmds = py_commands();
230         if (py_cmds == NULL) {
231                 return 1;
232         }
233
234         while (PyDict_Next(py_cmds, &pos, &key, &value)) {
235                 char *name, *desc;
236                 PyObject *py_desc;
237                 if (!PyString_Check(key)) {
238                         d_printf("Command name not a string\n");
239                         return 1;
240                 }
241                 name = PyString_AsString(key);
242                 py_desc = PyObject_GetAttrString(value, "description");
243                 if (py_desc == NULL) {
244                         PyErr_Print();
245                         return 1;
246                 }
247                 if (!PyString_Check(py_desc)) {
248                         d_printf("Command description for %s not a string\n", 
249                                 name);
250                         return 1;
251                 }
252                 desc = PyString_AsString(py_desc);
253                 if (strlen(name) > 7) {
254                         d_printf("\t%s\t%s\n", name, desc);
255                 } else {
256                         d_printf("\t%s\t\t%s\n", name, desc);
257                 }
258         }
259         return 0;
260 }
261
262 int net_help(struct net_context *ctx, const struct net_functable *ftable)
263 {
264         d_printf("Available commands:\n");
265         net_help_builtin(ftable);
266         net_help_python();
267         return 0;
268 }
269
270 static int net_usage(struct net_context *ctx, int argc, const char **argv)
271 {
272         d_printf("Usage:\n");
273         d_printf("net <command> [options]\n");
274         d_printf("Type 'net help' for all available commands\n");
275         return 0;
276 }
277
278 /****************************************************************************
279   main program
280 ****************************************************************************/
281 static int binary_net(int argc, const char **argv)
282 {
283         int opt,i;
284         int rc;
285         int argc_new;
286         PyObject *py_cmds, *py_cmd;
287         const char **argv_new;
288         struct tevent_context *ev;
289         struct net_context *ctx = NULL;
290         poptContext pc;
291         struct poptOption long_options[] = {
292                 POPT_AUTOHELP
293                 POPT_COMMON_SAMBA
294                 POPT_COMMON_CONNECTION
295                 POPT_COMMON_CREDENTIALS
296                 POPT_COMMON_VERSION
297                 { NULL }
298         };
299
300         setlinebuf(stdout);
301
302         dcerpc_init(cmdline_lp_ctx);
303
304         ev = s4_event_context_init(NULL);
305         if (!ev) {
306                 d_printf("Failed to create an event context\n");
307                 exit(1);
308         }
309         py_load_samba_modules();
310         Py_Initialize();
311         PySys_SetArgv(argc, argv);
312         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
313
314         py_cmds = py_commands();
315         if (py_cmds == NULL) {
316                 return 1;
317         }
318
319         if (argc > 1) {
320                 py_cmd = PyDict_GetItemString(py_cmds, argv[1]);
321                 if (py_cmd != NULL) {
322                         rc = py_call_with_string_args(py_cmd, "_run",
323                                 argc-1, argv+1);
324                         talloc_free(ev);
325                         return rc;
326                 }
327         }
328
329         pc = poptGetContext("net", argc, (const char **) argv, long_options, 
330                             POPT_CONTEXT_KEEP_FIRST);
331
332         while((opt = poptGetNextOpt(pc)) != -1) {
333                 switch (opt) {
334                 default:
335                         d_printf("Invalid option %s: %s\n", 
336                                  poptBadOption(pc, 0), poptStrerror(opt));
337                         net_usage(ctx, argc, argv);
338                         exit(1);
339                 }
340         }
341
342         argv_new = (const char **)poptGetArgs(pc);
343
344         argc_new = argc;
345         for (i=0; i<argc; i++) {
346                 if (argv_new[i] == NULL) {
347                         argc_new = i;
348                         break;
349                 }
350         }
351
352         if (argc_new < 2) {
353                 return net_usage(ctx, argc, argv);
354         }
355
356
357         ctx = talloc(ev, struct net_context);
358         if (!ctx) {
359                 d_printf("Failed to talloc a net_context\n");
360                 exit(1);
361         }
362
363         ZERO_STRUCTP(ctx);
364         ctx->lp_ctx = cmdline_lp_ctx;
365         ctx->credentials = cmdline_credentials;
366         ctx->event_ctx = ev;
367
368
369
370         rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable,
371                               net_usage);
372
373         if (rc != 0) {
374                 DEBUG(0,("return code = %d\n", rc));
375         }
376
377         talloc_free(ev);
378         return rc;
379 }
380
381  int main(int argc, const char **argv)
382 {
383         return binary_net(argc, argv);
384 }