1/* 2 Unix SMB/CIFS implementation. 3 Samba utility functions 4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2009 5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22#include "auth/auth.h" 23#include "lib/ldb_wrap.h" 24#include "ldb/include/ldb.h" 25#include "ldb_errors.h" 26#include "libcli/raw/libcliraw.h" 27#include "librpc/ndr/libndr.h" 28 29#include "param/param.h" 30#include "param/provision.h" 31#include "param/secrets.h" 32#include <Python.h> 33#include "lib/talloc/pytalloc.h" 34#include "librpc/rpc/pyrpc.h" 35#include "scripting/python/modules.h" 36#include "lib/ldb/pyldb.h" 37#include "param/pyparam.h" 38 39static PyObject *provision_module(void) 40{ 41 PyObject *name = PyString_FromString("samba.provision"); 42 if (name == NULL) 43 return NULL; 44 return PyImport_Import(name); 45} 46 47NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, 48 struct provision_settings *settings, 49 struct provision_result *result) 50{ 51 const char *configfile; 52 PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters; 53 54 DEBUG(0,("Provision for Become-DC test using python\n")); 55 56 py_load_samba_modules(); 57 Py_Initialize(); 58 py_update_path("bin"); /* FIXME: Can't assume this is always the case */ 59 60 provision_mod = provision_module(); 61 62 if (provision_mod == NULL) { 63 PyErr_Print(); 64 DEBUG(0, ("Unable to import provision Python module.\n")); 65 return NT_STATUS_UNSUCCESSFUL; 66 } 67 68 provision_dict = PyModule_GetDict(provision_mod); 69 70 if (provision_dict == NULL) { 71 DEBUG(0, ("Unable to get dictionary for provision module\n")); 72 return NT_STATUS_UNSUCCESSFUL; 73 } 74 75 provision_fn = PyDict_GetItemString(provision_dict, "provision_become_dc"); 76 if (provision_fn == NULL) { 77 PyErr_Print(); 78 DEBUG(0, ("Unable to get provision_become_dc function\n")); 79 return NT_STATUS_UNSUCCESSFUL; 80 } 81 82 DEBUG(0,("New Server in Site[%s]\n", 83 settings->site_name)); 84 85 DEBUG(0,("DSA Instance [%s]\n" 86 "\tinvocationId[%s]\n", 87 settings->ntds_dn_str, 88 settings->invocation_id == NULL?"None":GUID_string(mem_ctx, settings->invocation_id))); 89 90 DEBUG(0,("Pathes under targetdir[%s]\n", 91 settings->targetdir)); 92 parameters = PyDict_New(); 93 94 configfile = lp_configfile(lp_ctx); 95 if (configfile != NULL) { 96 PyDict_SetItemString(parameters, "smbconf", 97 PyString_FromString(configfile)); 98 } 99 100 PyDict_SetItemString(parameters, "rootdn", 101 PyString_FromString(settings->root_dn_str)); 102 if (settings->targetdir != NULL) 103 PyDict_SetItemString(parameters, "targetdir", 104 PyString_FromString(settings->targetdir)); 105 PyDict_SetItemString(parameters, "setup_dir", 106 PyString_FromString("setup")); 107 PyDict_SetItemString(parameters, "hostname", 108 PyString_FromString(settings->netbios_name)); 109 PyDict_SetItemString(parameters, "domain", 110 PyString_FromString(settings->domain)); 111 PyDict_SetItemString(parameters, "realm", 112 PyString_FromString(settings->realm)); 113 if (settings->root_dn_str) 114 PyDict_SetItemString(parameters, "rootdn", 115 PyString_FromString(settings->root_dn_str)); 116 117 if (settings->domain_dn_str) 118 PyDict_SetItemString(parameters, "domaindn", 119 PyString_FromString(settings->domain_dn_str)); 120 121 if (settings->schema_dn_str) 122 PyDict_SetItemString(parameters, "schemadn", 123 PyString_FromString(settings->schema_dn_str)); 124 125 if (settings->config_dn_str) 126 PyDict_SetItemString(parameters, "configdn", 127 PyString_FromString(settings->config_dn_str)); 128 129 if (settings->server_dn_str) 130 PyDict_SetItemString(parameters, "serverdn", 131 PyString_FromString(settings->server_dn_str)); 132 133 if (settings->site_name) 134 PyDict_SetItemString(parameters, "sitename", 135 PyString_FromString(settings->site_name)); 136 137 PyDict_SetItemString(parameters, "machinepass", 138 PyString_FromString(settings->machine_password)); 139 140 141 PyDict_SetItemString(parameters, "debuglevel", PyInt_FromLong(DEBUGLEVEL)); 142 143 py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters); 144 145 Py_DECREF(parameters); 146 147 if (py_result == NULL) { 148 PyErr_Print(); 149 PyErr_Clear(); 150 return NT_STATUS_UNSUCCESSFUL; 151 } 152 153 result->domaindn = talloc_strdup(mem_ctx, PyString_AsString(PyObject_GetAttrString(py_result, "domaindn"))); 154 155 /* FIXME paths */ 156 result->lp_ctx = lp_from_py_object(PyObject_GetAttrString(py_result, "lp")); 157 result->samdb = PyLdb_AsLdbContext(PyObject_GetAttrString(py_result, "samdb")); 158 159 return NT_STATUS_OK; 160} 161 162extern void initldb(void); 163 164static PyObject *py_dom_sid_FromSid(struct dom_sid *sid) 165{ 166 PyObject *mod_security, *dom_sid_Type; 167 168 mod_security = PyImport_ImportModule("samba.dcerpc.security"); 169 if (mod_security == NULL) 170 return NULL; 171 172 dom_sid_Type = PyObject_GetAttrString(mod_security, "dom_sid"); 173 if (dom_sid_Type == NULL) 174 return NULL; 175 176 return py_talloc_reference((PyTypeObject *)dom_sid_Type, sid); 177} 178 179NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, 180 struct tevent_context *event_ctx, 181 struct provision_store_self_join_settings *settings, 182 const char **error_string) 183{ 184 int ret; 185 PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters, *py_sid; 186 struct ldb_context *ldb; 187 TALLOC_CTX *tmp_mem = talloc_new(mem_ctx); 188 if (!tmp_mem) { 189 return NT_STATUS_NO_MEMORY; 190 } 191 192 /* Open the secrets database */ 193 ldb = secrets_db_connect(tmp_mem, event_ctx, lp_ctx); 194 if (!ldb) { 195 *error_string 196 = talloc_asprintf(mem_ctx, 197 "Could not open secrets database"); 198 talloc_free(tmp_mem); 199 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; 200 } 201 202 ret = ldb_transaction_start(ldb); 203 204 if (ret != LDB_SUCCESS) { 205 *error_string 206 = talloc_asprintf(mem_ctx, 207 "Could not start transaction on secrets database: %s", ldb_errstring(ldb)); 208 talloc_free(tmp_mem); 209 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; 210 } 211 212 py_load_samba_modules(); 213 Py_Initialize(); 214 py_update_path("bin"); /* FIXME: Can't assume this is always the case */ 215 initldb(); 216 provision_mod = provision_module(); 217 218 if (provision_mod == NULL) { 219 PyErr_Print(); 220 *error_string 221 = talloc_asprintf(mem_ctx, "Unable to import provision Python module."); 222 talloc_free(tmp_mem); 223 return NT_STATUS_UNSUCCESSFUL; 224 } 225 226 provision_dict = PyModule_GetDict(provision_mod); 227 228 if (provision_dict == NULL) { 229 *error_string 230 = talloc_asprintf(mem_ctx, "Unable to get dictionary for provision module"); 231 talloc_free(tmp_mem); 232 return NT_STATUS_UNSUCCESSFUL; 233 } 234 235 provision_fn = PyDict_GetItemString(provision_dict, "secretsdb_self_join"); 236 if (provision_fn == NULL) { 237 PyErr_Print(); 238 *error_string 239 = talloc_asprintf(mem_ctx, "Unable to get provision_become_dc function"); 240 talloc_free(tmp_mem); 241 return NT_STATUS_UNSUCCESSFUL; 242 } 243 244 parameters = PyDict_New(); 245 246 PyDict_SetItemString(parameters, "secretsdb", 247 PyLdb_FromLdbContext(ldb)); 248 PyDict_SetItemString(parameters, "domain", 249 PyString_FromString(settings->domain_name)); 250 PyDict_SetItemString(parameters, "domain", 251 PyString_FromString(settings->domain_name)); 252 PyDict_SetItemString(parameters, "realm", 253 PyString_FromString(settings->realm)); 254 PyDict_SetItemString(parameters, "machinepass", 255 PyString_FromString(settings->machine_password)); 256 PyDict_SetItemString(parameters, "netbiosname", 257 PyString_FromString(settings->netbios_name)); 258 259 py_sid = py_dom_sid_FromSid(settings->domain_sid); 260 if (py_sid == NULL) { 261 Py_DECREF(parameters); 262 goto failure; 263 } 264 265 PyDict_SetItemString(parameters, "domainsid", 266 py_sid); 267 268 PyDict_SetItemString(parameters, "secure_channel_type", 269 PyInt_FromLong(settings->secure_channel_type)); 270 271 PyDict_SetItemString(parameters, "key_version_number", 272 PyInt_FromLong(settings->key_version_number)); 273 274 py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters); 275 276 Py_DECREF(parameters); 277 278 if (py_result == NULL) { 279 goto failure; 280 } 281 282 ret = ldb_transaction_commit(ldb); 283 if (ret != LDB_SUCCESS) { 284 *error_string 285 = talloc_asprintf(mem_ctx, 286 "Could not commit transaction on secrets database: %s", ldb_errstring(ldb)); 287 talloc_free(tmp_mem); 288 return NT_STATUS_INTERNAL_DB_ERROR; 289 } 290 291 talloc_free(tmp_mem); 292 293 return NT_STATUS_OK; 294 295failure: 296 ldb_transaction_cancel(ldb); 297 talloc_free(tmp_mem); 298 299 PyErr_Print(); 300 PyErr_Clear(); 301 return NT_STATUS_UNSUCCESSFUL; 302} 303