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