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