r19058: Implement "user cannot change password", and complete "user must change
[Samba.git] / source / python / py_common.c
blob14c3b83e547bacc4170cad3c1887fa8b7e37339e
1 /*
2 Python wrappers for DCERPC/SMB client routines.
4 Copyright (C) Tim Potter, 2002
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.
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.
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.
21 #include "python/py_common.h"
23 /* Return a tuple of (error code, error string) from a WERROR */
25 PyObject *py_werror_tuple(WERROR werror)
27 return Py_BuildValue("[is]", W_ERROR_V(werror),
28 dos_errstr(werror));
31 /* Return a tuple of (error code, error string) from a WERROR */
33 PyObject *py_ntstatus_tuple(NTSTATUS ntstatus)
35 return Py_BuildValue("[is]", NT_STATUS_V(ntstatus),
36 nt_errstr(ntstatus));
39 /* Initialise samba client routines */
41 static BOOL initialised;
43 void py_samba_init(void)
45 if (initialised)
46 return;
48 load_case_tables();
50 /* Load configuration file */
52 if (!lp_load(dyn_CONFIGFILE, True, False, False, True))
53 fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
55 /* Misc other stuff */
57 load_interfaces();
58 init_names();
60 initialised = True;
63 /* Debuglevel routines */
65 PyObject *get_debuglevel(PyObject *self, PyObject *args)
67 PyObject *debuglevel;
69 if (!PyArg_ParseTuple(args, ""))
70 return NULL;
72 debuglevel = PyInt_FromLong(DEBUGLEVEL);
74 return debuglevel;
77 PyObject *set_debuglevel(PyObject *self, PyObject *args)
79 int debuglevel;
81 if (!PyArg_ParseTuple(args, "i", &debuglevel))
82 return NULL;
84 DEBUGLEVEL = debuglevel;
86 Py_INCREF(Py_None);
87 return Py_None;
90 /* Initialise logging */
92 PyObject *py_setup_logging(PyObject *self, PyObject *args, PyObject *kw)
94 BOOL interactive = False;
95 char *logfilename = NULL;
96 static char *kwlist[] = {"interactive", "logfilename", NULL};
98 if (!PyArg_ParseTupleAndKeywords(
99 args, kw, "|is", kwlist, &interactive, &logfilename))
100 return NULL;
102 if (interactive && logfilename) {
103 PyErr_SetString(PyExc_RuntimeError,
104 "can't be interactive and set log file name");
105 return NULL;
108 if (interactive)
109 setup_logging("spoolss", True);
111 if (logfilename) {
112 lp_set_logfile(logfilename);
113 setup_logging(logfilename, False);
114 reopen_logs();
117 Py_INCREF(Py_None);
118 return Py_None;
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. */
128 BOOL py_parse_creds(PyObject *creds, char **username, char **domain,
129 char **password, char **errstr)
131 /* Initialise anonymous credentials */
133 *username = "";
134 *domain = "";
135 *password = "";
137 if (creds && PyDict_Size(creds) > 0) {
138 PyObject *username_obj, *password_obj, *domain_obj;
139 PyObject *key, *value;
140 int i;
142 /* Check for presence of required fields */
144 username_obj = PyDict_GetItemString(creds, "username");
145 domain_obj = PyDict_GetItemString(creds, "domain");
146 password_obj = PyDict_GetItemString(creds, "password");
148 if (!username_obj) {
149 *errstr = SMB_STRDUP("no username field in credential");
150 return False;
153 if (!domain_obj) {
154 *errstr = SMB_STRDUP("no domain field in credential");
155 return False;
158 if (!password_obj) {
159 *errstr = SMB_STRDUP("no password field in credential");
160 return False;
163 /* Check type of required fields */
165 if (!PyString_Check(username_obj)) {
166 *errstr = SMB_STRDUP("username field is not string type");
167 return False;
170 if (!PyString_Check(domain_obj)) {
171 *errstr = SMB_STRDUP("domain field is not string type");
172 return False;
175 if (!PyString_Check(password_obj)) {
176 *errstr = SMB_STRDUP("password field is not string type");
177 return False;
180 /* Look for any extra fields */
182 i = 0;
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;
195 /* Assign values */
197 *username = PyString_AsString(username_obj);
198 *domain = PyString_AsString(domain_obj);
199 *password = PyString_AsString(password_obj);
202 *errstr = NULL;
204 return True;
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(). */
212 struct cli_state *open_pipe_creds(char *server, PyObject *creds,
213 int pipe_idx, char **errstr)
215 char *username, *password, *domain;
216 struct cli_state *cli;
217 struct rpc_pipe_client *pipe_hnd;
218 NTSTATUS result;
220 /* Extract credentials from the python dictionary */
222 if (!py_parse_creds(creds, &username, &domain, &password, errstr))
223 return NULL;
225 /* Now try to connect */
227 result = cli_full_connection(
228 &cli, NULL, server, NULL, 0, "IPC$", "IPC",
229 username, domain, password, 0, Undefined, NULL);
231 if (!NT_STATUS_IS_OK(result)) {
232 *errstr = SMB_STRDUP("error connecting to IPC$ pipe");
233 return NULL;
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;
243 *errstr = NULL;
245 return cli;
248 /* Return true if a dictionary contains a "level" key with an integer
249 value. Set the value if so. */
251 BOOL get_level_value(PyObject *dict, uint32 *level)
253 PyObject *obj;
255 if (!(obj = PyDict_GetItemString(dict, "level")) ||
256 !PyInt_Check(obj))
257 return False;
259 if (level)
260 *level = PyInt_AsLong(obj);
262 return True;