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