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