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_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 65PyObject *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 77PyObject *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 92PyObject *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 128BOOL 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 212struct 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 251BOOL 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} 264