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