9725402c7ffdcc4b9770edcf6dbd027187c13dd0
[kai/samba-autobuild/.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 "includes.h"
45 #include "utils/net/net.h"
46 #include "lib/cmdline/popt_common.h"
47 #include "lib/ldb/include/ldb.h"
48 #include "librpc/rpc/dcerpc.h"
49 #include "param/param.h"
50 #include "lib/events/events.h"
51 #include "auth/credentials/credentials.h"
52 #include <Python.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         return PyInt_AsLong(ret);
98 }
99
100 static PyObject *py_commands(void)
101 {
102         PyObject *netcmd_module, *py_cmds;
103         netcmd_module = PyImport_ImportModule("samba.netcmd");
104         if (netcmd_module == NULL) {
105                 PyErr_Print();
106                 return NULL;
107         }       
108
109         py_cmds = PyObject_GetAttrString(netcmd_module, "commands");
110         if (py_cmds == NULL) {
111                 PyErr_Print();
112                 return NULL;
113         }
114
115         if (!PyDict_Check(py_cmds)) {
116                 d_printf("Python net commands is not a dictionary\n");
117                 return NULL;
118         }
119
120         return py_cmds;
121 }
122
123 /*
124   run a function from a function table. If not found then
125   call the specified usage function 
126 */
127 int net_run_function(struct net_context *ctx,
128                         int argc, const char **argv,
129                         const struct net_functable *functable, 
130                         int (*usage_fn)(struct net_context *ctx, int argc, const char **argv))
131 {
132         int i;
133         PyObject *py_cmds, *py_cmd;
134
135         if (argc == 0) {
136                 return usage_fn(ctx, argc, argv);
137
138         } else if (argc == 1 && strequal(argv[0], "help")) {
139                 return net_help(ctx, functable);
140         }
141
142         for (i=0; functable[i].name; i++) {
143                 if (strcasecmp_m(argv[0], functable[i].name) == 0)
144                         return functable[i].fn(ctx, argc-1, argv+1);
145         }
146
147         py_cmds = py_commands();
148         if (py_cmds == NULL) {
149                 return 1;
150         }
151
152         py_cmd = PyDict_GetItemString(py_cmds, argv[0]);
153         if (py_cmd != NULL) {
154                 return py_call_with_string_args(py_cmd, "_run", 
155                         argc-1, argv+1);
156         }
157
158         d_printf("No command: %s\n", argv[0]);
159         return usage_fn(ctx, argc, argv);
160 }
161
162 /*
163   run a usage function from a function table. If not found then fail
164 */
165 int net_run_usage(struct net_context *ctx,
166                         int argc, const char **argv,
167                         const struct net_functable *functable)
168 {
169         int i;
170         PyObject *py_cmds, *py_cmd;
171
172         for (i=0; functable[i].name; i++) {
173                 if (strcasecmp_m(argv[0], functable[i].name) == 0)
174                         if (functable[i].usage) {
175                                 return functable[i].usage(ctx, argc-1, argv+1);
176                         }
177         }
178
179         py_cmds = py_commands();
180         if (py_cmds == NULL) {
181                 return 1;
182         }
183
184         py_cmd = PyDict_GetItemString(py_cmds, argv[0]);
185         if (py_cmd != NULL) {
186                 return py_call_with_string_args(py_cmd, "usage", argc-1, 
187                                                 argv+1);
188         }
189
190         d_printf("No usage information for command: %s\n", argv[0]);
191
192         return 1;
193 }
194
195
196 /* main function table */
197 static const struct net_functable net_functable[] = {
198         {"password", "change password\n", net_password, net_password_usage},
199         {"time", "get remote server's time\n", net_time, net_time_usage},
200         {"join", "join a domain\n", net_join, net_join_usage},
201         {"samdump", "dump the sam of a domain\n", net_samdump, net_samdump_usage},
202         {"export", "dump the sam of this domain\n", net_export, net_export_usage},
203         {"vampire", "join and syncronise an AD domain onto the local server\n", net_vampire, net_vampire_usage},
204         {"samsync", "synchronise into the local ldb the sam of an NT4 domain\n", net_samsync_ldb, net_samsync_ldb_usage},
205         {"user", "manage user accounts\n", net_user, net_user_usage},
206         {"machinepw", "Get a machine password out of our SAM\n", net_machinepw, net_machinepw_usage},
207         {NULL, NULL, NULL, NULL}
208 };
209
210 static int net_help_builtin(const struct net_functable *ftable)
211 {
212         int i = 0;
213         const char *name = ftable[i].name;
214         const char *desc = ftable[i].desc;
215
216         while (name && desc) {
217                 if (strlen(name) > 7) {
218                         d_printf("\t%s\t%s", name, desc);
219                 } else {
220                         d_printf("\t%s\t\t%s", name, desc);
221                 }
222                 name = ftable[++i].name;
223                 desc = ftable[i].desc;
224         }
225         return 0;
226 }
227
228 static int net_help_python(void)
229 {
230         PyObject *py_cmds;
231         PyObject *key, *value;
232         Py_ssize_t pos = 0;
233
234         py_cmds = py_commands();
235         if (py_cmds == NULL) {
236                 return 1;
237         }
238
239         while (PyDict_Next(py_cmds, &pos, &key, &value)) {
240                 char *name, *desc;
241                 PyObject *py_desc;
242                 if (!PyString_Check(key)) {
243                         d_printf("Command name not a string\n");
244                         return 1;
245                 }
246                 name = PyString_AsString(key);
247                 py_desc = PyObject_GetAttrString(value, "description");
248                 if (py_desc == NULL) {
249                         PyErr_Print();
250                         return 1;
251                 }
252                 if (!PyString_Check(py_desc)) {
253                         d_printf("Command description for %s not a string\n", 
254                                 name);
255                         return 1;
256                 }
257                 desc = PyString_AsString(py_desc);
258                 if (strlen(name) > 7) {
259                         d_printf("\t%s\t%s\n", name, desc);
260                 } else {
261                         d_printf("\t%s\t\t%s\n", name, desc);
262                 }
263         }
264         return 0;
265 }
266
267 int net_help(struct net_context *ctx, const struct net_functable *ftable)
268 {
269         d_printf("Available commands:\n");
270         net_help_builtin(ftable);
271         net_help_python();
272         return 0;
273 }
274
275 static int net_usage(struct net_context *ctx, int argc, const char **argv)
276 {
277         d_printf("Usage:\n");
278         d_printf("net <command> [options]\n");
279         d_printf("Type 'net help' for all available commands\n");
280         return 0;
281 }
282
283 /****************************************************************************
284   main program
285 ****************************************************************************/
286 static int binary_net(int argc, const char **argv)
287 {
288         int opt,i;
289         int rc;
290         int argc_new;
291         const char **argv_new;
292         struct tevent_context *ev;
293         struct net_context *ctx = NULL;
294         poptContext pc;
295         struct poptOption long_options[] = {
296                 POPT_AUTOHELP
297                 POPT_COMMON_SAMBA
298                 POPT_COMMON_CONNECTION
299                 POPT_COMMON_CREDENTIALS
300                 POPT_COMMON_VERSION
301                 { NULL }
302         };
303
304         setlinebuf(stdout);
305
306         pc = poptGetContext("net", argc, (const char **) argv, long_options, 
307                             POPT_CONTEXT_KEEP_FIRST);
308
309         while((opt = poptGetNextOpt(pc)) != -1) {
310                 switch (opt) {
311                 default:
312                         d_printf("Invalid option %s: %s\n", 
313                                  poptBadOption(pc, 0), poptStrerror(opt));
314                         net_usage(ctx, argc, argv);
315                         exit(1);
316                 }
317         }
318
319         argv_new = (const char **)poptGetArgs(pc);
320
321         argc_new = argc;
322         for (i=0; i<argc; i++) {
323                 if (argv_new[i] == NULL) {
324                         argc_new = i;
325                         break;
326                 }
327         }
328
329         if (argc_new < 2) {
330                 return net_usage(ctx, argc, argv);
331         }
332
333         dcerpc_init(cmdline_lp_ctx);
334
335         ev = s4_event_context_init(NULL);
336         if (!ev) {
337                 d_printf("Failed to create an event context\n");
338                 exit(1);
339         }
340         ctx = talloc(ev, struct net_context);
341         if (!ctx) {
342                 d_printf("Failed to talloc a net_context\n");
343                 exit(1);
344         }
345
346         ZERO_STRUCTP(ctx);
347         ctx->lp_ctx = cmdline_lp_ctx;
348         ctx->credentials = cmdline_credentials;
349         ctx->event_ctx = ev;
350
351         py_load_samba_modules();
352         Py_Initialize();
353         py_update_path("bin"); /* FIXME: Can't assume this is always the case */
354
355         rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable,
356                               net_usage);
357
358         if (rc != 0) {
359                 DEBUG(0,("return code = %d\n", rc));
360         }
361
362         talloc_free(ev);
363         return rc;
364 }
365
366  int main(int argc, const char **argv)
367 {
368         return binary_net(argc, argv);
369 }