This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[tprouty/samba.git] / source / python / py_common.c
1 /* 
2    Python wrappers for DCERPC/SMB client routines.
3
4    Copyright (C) Tim Potter, 2002
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 #include "includes.h"
22 #include "Python.h"
23
24 #include "python/py_common_proto.h"
25
26 /* Return a tuple of (error code, error string) from a WERROR */
27
28 PyObject *py_werror_tuple(WERROR werror)
29 {
30         return Py_BuildValue("[is]", W_ERROR_V(werror), 
31                              dos_errstr(werror));
32 }
33
34 /* Return a tuple of (error code, error string) from a WERROR */
35
36 PyObject *py_ntstatus_tuple(NTSTATUS ntstatus)
37 {
38         return Py_BuildValue("[is]", NT_STATUS_V(ntstatus), 
39                              nt_errstr(ntstatus));
40 }
41
42 /* Initialise samba client routines */
43
44 static BOOL initialised;
45
46 void py_samba_init(void)
47 {
48         if (initialised)
49                 return;
50
51         /* Load configuration file */
52
53         if (!lp_load(dyn_CONFIGFILE, True, False, False))
54                 fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
55
56         /* Misc other stuff */
57
58         load_interfaces();
59         init_names();
60
61         initialised = True;
62 }
63
64 /* Debuglevel routines */
65
66 PyObject *get_debuglevel(PyObject *self, PyObject *args)
67 {
68         PyObject *debuglevel;
69
70         if (!PyArg_ParseTuple(args, ""))
71                 return NULL;
72
73         debuglevel = PyInt_FromLong(DEBUGLEVEL);
74
75         return debuglevel;
76 }
77
78 PyObject *set_debuglevel(PyObject *self, PyObject *args)
79 {
80         int debuglevel;
81
82         if (!PyArg_ParseTuple(args, "i", &debuglevel))
83                 return NULL;
84
85         DEBUGLEVEL = debuglevel;
86
87         Py_INCREF(Py_None);
88         return Py_None;
89 }
90
91 /* Initialise logging */
92
93 PyObject *py_setup_logging(PyObject *self, PyObject *args, PyObject *kw)
94 {
95         BOOL interactive = False;
96         char *logfilename = NULL;
97         static char *kwlist[] = {"interactive", "logfilename", NULL};
98
99         if (!PyArg_ParseTupleAndKeywords(
100                     args, kw, "|is", kwlist, &interactive, &logfilename))
101                 return NULL;
102         
103         if (interactive && logfilename) {
104                 PyErr_SetString(PyExc_RuntimeError,
105                                 "can't be interactive and set log file name");
106                 return NULL;
107         }
108
109         if (interactive)
110                 setup_logging("spoolss", True);
111
112         if (logfilename) {
113                 lp_set_logfile(logfilename);
114                 setup_logging(logfilename, False);
115                 reopen_logs();
116         }
117
118         Py_INCREF(Py_None);
119         return Py_None;
120 }
121
122 /* Parse credentials from a python dictionary.  The dictionary can
123    only have the keys "username", "domain" and "password".  Return
124    True for valid credentials in which case the username, domain and
125    password are set to pointers to their values from the dicationary.
126    If returns False, the errstr is set to point at some mallocated
127    memory describing the error. */
128
129 BOOL py_parse_creds(PyObject *creds, char **username, char **domain, 
130                     char **password, char **errstr)
131 {
132         /* Initialise anonymous credentials */
133
134         *username = "";
135         *domain = "";
136         *password = "";
137
138         if (creds && PyDict_Size(creds) > 0) {
139                 PyObject *username_obj, *password_obj, *domain_obj;
140                 PyObject *key, *value;
141                 int i;
142
143                 /* Check for presence of required fields */
144
145                 username_obj = PyDict_GetItemString(creds, "username");
146                 domain_obj = PyDict_GetItemString(creds, "domain");
147                 password_obj = PyDict_GetItemString(creds, "password");
148
149                 if (!username_obj) {
150                         *errstr = strdup("no username field in credential");
151                         return False;
152                 }
153
154                 if (!domain_obj) {
155                         *errstr = strdup("no domain field in credential");
156                         return False;
157                 }
158
159                 if (!password_obj) {
160                         *errstr = strdup("no password field in credential");
161                         return False;
162                 }
163
164                 /* Check type of required fields */
165
166                 if (!PyString_Check(username_obj)) {
167                         *errstr = strdup("username field is not string type");
168                         return False;
169                 }
170
171                 if (!PyString_Check(domain_obj)) {
172                         *errstr = strdup("domain field is not string type");
173                         return False;
174                 }
175
176                 if (!PyString_Check(password_obj)) {
177                         *errstr = strdup("password field is not string type");
178                         return False;
179                 }
180
181                 /* Look for any extra fields */
182
183                 i = 0;
184
185                 while (PyDict_Next(creds, &i, &key, &value)) {
186                         if (strcmp(PyString_AsString(key), "domain") != 0 &&
187                             strcmp(PyString_AsString(key), "username") != 0 &&
188                             strcmp(PyString_AsString(key), "password") != 0) {
189                                 asprintf(errstr,
190                                          "creds contain extra field '%s'",
191                                          PyString_AsString(key));
192                                 return False;
193                         }
194                 }
195
196                 /* Assign values */
197
198                 *username = PyString_AsString(username_obj);
199                 *domain = PyString_AsString(domain_obj);
200                 *password = PyString_AsString(password_obj);
201         }
202
203         *errstr = NULL;
204
205         return True;
206 }
207
208 /* Return a cli_state to a RPC pipe on the given server.  Use the
209    credentials passed if not NULL.  If an error occurs errstr is set to a
210    string describing the error and NULL is returned.  If set, errstr must
211    be freed by calling free(). */
212
213 struct cli_state *open_pipe_creds(char *server, PyObject *creds, 
214                                   int pipe_idx, char **errstr)
215 {
216         char *username, *password, *domain;
217         struct cli_state *cli;
218         NTSTATUS result;
219         
220         /* Extract credentials from the python dictionary */
221
222         if (!py_parse_creds(creds, &username, &domain, &password, errstr))
223                 return NULL;
224
225         /* Now try to connect */
226
227         result = cli_full_connection(
228                 &cli, NULL, server, NULL, 0, "IPC$", "IPC",
229                 username, domain, password, 0, NULL);
230         
231         if (!NT_STATUS_IS_OK(result)) {
232                 *errstr = strdup("error connecting to IPC$ pipe");
233                 return NULL;
234         }
235
236         if (!cli_nt_session_open(cli, pipe_idx)) {
237                 cli_shutdown(cli);
238                 asprintf(errstr, "error opening pipe index %d", pipe_idx);
239                 return NULL;
240         }
241
242         *errstr = NULL;
243
244         return cli;
245 }
246
247 /* Return true if a dictionary contains a "level" key with an integer
248    value.  Set the value if so. */
249
250 BOOL get_level_value(PyObject *dict, uint32 *level)
251 {
252         PyObject *obj;
253
254         if (!(obj = PyDict_GetItemString(dict, "level")) ||
255             !PyInt_Check(obj))
256                 return False;
257
258         if (level)
259                 *level = PyInt_AsLong(obj);
260
261         return True;
262 }