From 509a2bb97c5ccb13c4c2f885f3961f2880aceb91 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 19 Sep 2009 20:40:17 -0700 Subject: s4:provision split provision of DNS zone and self join keytab --- source4/scripting/python/samba/provision.py | 14 ++++++++++---- source4/setup/secrets_dc.ldif | 24 ------------------------ source4/setup/secrets_dns.ldif | 11 +++++++++++ source4/setup/secrets_self_join.ldif | 13 +++++++++++++ 4 files changed, 34 insertions(+), 28 deletions(-) delete mode 100644 source4/setup/secrets_dc.ldif create mode 100644 source4/setup/secrets_dns.ldif create mode 100644 source4/setup/secrets_self_join.ldif (limited to 'source4') diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index fe11b94d67..68a50b2e37 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -669,7 +669,14 @@ def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain, :param setup_path: Setup path function :param machinepass: Machine password """ - setup_ldb(secretsdb, setup_path("secrets_dc.ldif"), { + setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), { + "REALM": realm, + "DNSDOMAIN": dnsdomain, + "DNS_KEYTAB": dns_keytab_path, + "DNSPASS_B64": b64encode(dnspass), + }) + + setup_ldb(secretsdb, setup_path("secrets_self_join.ldif"), { "MACHINEPASS_B64": b64encode(machinepass), "DOMAIN": domain, "REALM": realm, @@ -677,9 +684,8 @@ def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain, "DOMAINSID": str(domainsid), "SECRETS_KEYTAB": keytab_path, "NETBIOSNAME": netbiosname, - "SAM_LDB": samdb_url, - "DNS_KEYTAB": dns_keytab_path, - "DNSPASS_B64": b64encode(dnspass), + "SALT_PRINCIPAL": "host/%s.%s@%s" % (netbiosname.lower(), dnsdomain.lower(), realm.upper()), + "KEY_VERSION_NUMBER": "1" }) diff --git a/source4/setup/secrets_dc.ldif b/source4/setup/secrets_dc.ldif deleted file mode 100644 index b8251eece5..0000000000 --- a/source4/setup/secrets_dc.ldif +++ /dev/null @@ -1,24 +0,0 @@ -dn: flatname=${DOMAIN},CN=Primary Domains -objectClass: top -objectClass: primaryDomain -objectClass: kerberosSecret -flatname: ${DOMAIN} -realm: ${REALM} -secret:: ${MACHINEPASS_B64} -secureChannelType: 6 -sAMAccountName: ${NETBIOSNAME}$ -msDS-KeyVersionNumber: 1 -objectSid: ${DOMAINSID} -privateKeytab: ${SECRETS_KEYTAB} - -#Update a keytab for the external DNS server to use -dn: servicePrincipalName=DNS/${DNSDOMAIN},CN=Principals -objectClass: top -objectClass: secret -objectClass: kerberosSecret -realm: ${REALM} -servicePrincipalName: DNS/${DNSDOMAIN} -msDS-KeyVersionNumber: 1 -privateKeytab: ${DNS_KEYTAB} -secret:: ${DNSPASS_B64} - diff --git a/source4/setup/secrets_dns.ldif b/source4/setup/secrets_dns.ldif new file mode 100644 index 0000000000..8a19733d19 --- /dev/null +++ b/source4/setup/secrets_dns.ldif @@ -0,0 +1,11 @@ +#Update a keytab for the external DNS server to use +dn: servicePrincipalName=DNS/${DNSDOMAIN},CN=Principals +objectClass: top +objectClass: secret +objectClass: kerberosSecret +realm: ${REALM} +servicePrincipalName: DNS/${DNSDOMAIN} +msDS-KeyVersionNumber: 1 +privateKeytab: ${DNS_KEYTAB} +secret:: ${DNSPASS_B64} + diff --git a/source4/setup/secrets_self_join.ldif b/source4/setup/secrets_self_join.ldif new file mode 100644 index 0000000000..22be0cab0b --- /dev/null +++ b/source4/setup/secrets_self_join.ldif @@ -0,0 +1,13 @@ +dn: flatname=${DOMAIN},CN=Primary Domains +objectClass: top +objectClass: primaryDomain +objectClass: kerberosSecret +flatname: ${DOMAIN} +realm: ${REALM} +secret:: ${MACHINEPASS_B64} +secureChannelType: 6 +sAMAccountName: ${NETBIOSNAME}$ +msDS-KeyVersionNumber: ${KEY_VERSION_NUMBER} +objectSid: ${DOMAINSID} +privateKeytab: ${SECRETS_KEYTAB} +saltPrincipal: ${SALT_PRINCIPAL} -- cgit From 1d4a16acd7e6c5bd664f2276d4d8e86efb36baaf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Sep 2009 15:38:29 -0700 Subject: s4:ldb print out which LDB the transaction is still active on. --- source4/lib/ldb/common/ldb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 613451a7c2..b75d837674 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -41,8 +41,8 @@ static int ldb_context_destructor(void *ptr) if (ldb->transaction_active) { ldb_debug(ldb, LDB_DEBUG_FATAL, - "A transaction is still active in ldb context [%p]", - ldb); + "A transaction is still active in ldb context [%p] on %s", + ldb, (const char *)ldb_get_opaque(ldb, "ldb_url")); } return 0; -- cgit From bfddb6816f50f629d29e476327a921212fd63a2d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Sep 2009 16:27:24 -0700 Subject: s4:provision Use code to store domain join in 'net join' as well This ensures we only have one codepath to store the secret, and therefore that we have a single choke point for setting the saltPrincipal, which we were previously skipping. Andrew Bartlett --- source4/libnet/libnet_join.c | 286 ++-------------------------- source4/libnet/libnet_vampire.c | 49 +++-- source4/librpc/ndr/py_security.c | 5 + source4/param/config.mk | 2 +- source4/param/provision.c | 131 ++++++++++++- source4/param/provision.h | 16 ++ source4/scripting/python/samba/provision.py | 103 +++++++--- 7 files changed, 283 insertions(+), 309 deletions(-) (limited to 'source4') diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index 86ad685c51..fc7de10506 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -33,6 +33,7 @@ #include "auth/credentials/credentials_krb5.h" #include "librpc/gen_ndr/ndr_samr_c.h" #include "param/param.h" +#include "param/provision.h" /* * complete a domain join, when joining to a AD domain: @@ -860,254 +861,6 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return status; } -NTSTATUS libnet_set_join_secrets(struct libnet_context *ctx, - TALLOC_CTX *mem_ctx, - struct libnet_set_join_secrets *r) -{ - TALLOC_CTX *tmp_mem; - int ret, rtn; - struct ldb_context *ldb; - struct ldb_dn *base_dn; - struct ldb_message **msgs, *msg; - const char *sct; - const char * const attrs[] = { - "whenChanged", - "secret", - "priorSecret", - "priorChanged", - "krb5Keytab", - "privateKeytab", - NULL - }; - - tmp_mem = talloc_new(mem_ctx); - if (!tmp_mem) { - return NT_STATUS_NO_MEMORY; - } - - /* Open the secrets database */ - ldb = secrets_db_connect(tmp_mem, ctx->event_ctx, ctx->lp_ctx); - if (!ldb) { - r->out.error_string - = talloc_asprintf(mem_ctx, - "Could not open secrets database"); - talloc_free(tmp_mem); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - /* - * now prepare the record for secrets.ldb - */ - sct = talloc_asprintf(tmp_mem, "%d", r->in.join_type); - if (!sct) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - msg = ldb_msg_new(tmp_mem); - if (!msg) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - base_dn = ldb_dn_new(tmp_mem, ldb, "cn=Primary Domains"); - if (!base_dn) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - msg->dn = ldb_dn_copy(tmp_mem, base_dn); - if ( ! ldb_dn_add_child_fmt(msg->dn, "flatname=%s", r->in.domain_name)) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "flatname", r->in.domain_name); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - if (r->in.realm) { - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "realm", r->in.realm); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain"); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "kerberosSecret"); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "secret", r->in.join_password); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "samAccountName", r->in.account_name); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "secureChannelType", sct); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - if (r->in.kvno) { - rtn = samdb_msg_add_uint(ldb, tmp_mem, msg, "msDS-KeyVersionNumber", - r->in.kvno); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - if (r->in.domain_sid) { - rtn = samdb_msg_add_dom_sid(ldb, tmp_mem, msg, "objectSid", - r->in.domain_sid); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - /* - * search for the secret record - * - remove the records we find - * - and fetch the old secret and store it under priorSecret - */ - ret = gendb_search(ldb, - tmp_mem, base_dn, - &msgs, attrs, - "(|" SECRETS_PRIMARY_DOMAIN_FILTER "(realm=%s))", - r->in.domain_name, r->in.realm); - if (ret == 0) { - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "privateKeytab", "secrets.keytab"); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } else if (ret == -1) { - r->out.error_string - = talloc_asprintf(mem_ctx, - "Search for domain: %s and realm: %s failed: %s", - r->in.domain_name, r->in.realm, ldb_errstring(ldb)); - talloc_free(tmp_mem); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } else { - const struct ldb_val *private_keytab; - const struct ldb_val *krb5_main_keytab; - const struct ldb_val *prior_secret; - const struct ldb_val *prior_modified_time; - int i; - - for (i = 0; i < ret; i++) { - ldb_delete(ldb, msgs[i]->dn); - } - - prior_secret = ldb_msg_find_ldb_val(msgs[0], "secret"); - if (prior_secret) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "priorSecret", prior_secret); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secret", r->in.join_password); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - prior_modified_time = ldb_msg_find_ldb_val(msgs[0], - "whenChanged"); - if (prior_modified_time) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "priorWhenChanged", - prior_modified_time); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "samAccountName", r->in.account_name); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secureChannelType", sct); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - /* We will want to keep the keytab names */ - private_keytab = ldb_msg_find_ldb_val(msgs[0], "privateKeytab"); - if (private_keytab) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "privateKeytab", private_keytab); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - krb5_main_keytab = ldb_msg_find_ldb_val(msgs[0], "krb5Keytab"); - if (krb5_main_keytab) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, - "krb5Keytab", krb5_main_keytab); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - } - - /* create the secret */ - ret = ldb_add(ldb, msg); - if (ret != 0) { - r->out.error_string = talloc_asprintf(mem_ctx, "Failed to create secret record %s", - ldb_dn_get_linearized(msg->dn)); - talloc_free(tmp_mem); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - return NT_STATUS_OK; -} - static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_Join *r) @@ -1115,11 +868,12 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, NTSTATUS status; TALLOC_CTX *tmp_mem; struct libnet_JoinDomain *r2; - struct libnet_set_join_secrets *r3; + struct provision_store_self_join_settings *set_secrets; uint32_t acct_type = 0; const char *account_name; const char *netbios_name; - + const char *error_string; + r->out.error_string = NULL; tmp_mem = talloc_new(mem_ctx); @@ -1179,26 +933,26 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, return status; } - r3 = talloc(tmp_mem, struct libnet_set_join_secrets); - if (!r3) { + set_secrets = talloc(tmp_mem, struct provision_store_self_join_settings); + if (!set_secrets) { r->out.error_string = NULL; talloc_free(tmp_mem); return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(r3); - r3->in.domain_name = r2->out.domain_name; - r3->in.realm = r2->out.realm; - r3->in.account_name = account_name; - r3->in.netbios_name = netbios_name; - r3->in.join_type = r->in.join_type; - r3->in.join_password = r2->out.join_password; - r3->in.kvno = r2->out.kvno; - r3->in.domain_sid = r2->out.domain_sid; + ZERO_STRUCTP(set_secrets); + set_secrets->domain_name = r2->out.domain_name; + set_secrets->realm = r2->out.realm; + set_secrets->account_name = account_name; + set_secrets->netbios_name = netbios_name; + set_secrets->secure_channel_type = r->in.join_type; + set_secrets->machine_password = r2->out.join_password; + set_secrets->key_version_number = r2->out.kvno; + set_secrets->domain_sid = r2->out.domain_sid; - status = libnet_set_join_secrets(ctx, r3, r3); + status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string); if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_steal(mem_ctx, r3->out.error_string); + r->out.error_string = talloc_steal(mem_ctx, error_string); talloc_free(tmp_mem); return status; } @@ -1206,11 +960,11 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, /* move all out parameter to the callers TALLOC_CTX */ r->out.error_string = NULL; r->out.join_password = r2->out.join_password; - talloc_steal(mem_ctx, r2->out.join_password); + talloc_reparent(r2, mem_ctx, r2->out.join_password); r->out.domain_sid = r2->out.domain_sid; - talloc_steal(mem_ctx, r2->out.domain_sid); + talloc_reparent(r2, mem_ctx, r2->out.domain_sid); r->out.domain_name = r2->out.domain_name; - talloc_steal(mem_ctx, r2->out.domain_name); + talloc_reparent(r2, mem_ctx, r2->out.domain_name); talloc_free(tmp_mem); return NT_STATUS_OK; } diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c index 327a64daea..19453a4d65 100644 --- a/source4/libnet/libnet_vampire.c +++ b/source4/libnet/libnet_vampire.c @@ -595,10 +595,11 @@ NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_Vampire *r) { struct libnet_JoinDomain *join; - struct libnet_set_join_secrets *set_secrets; + struct provision_store_self_join_settings *set_secrets; struct libnet_BecomeDC b; struct vampire_state *s; struct ldb_message *msg; + const char *error_string; int ldb_ret; uint32_t i; NTSTATUS status; @@ -709,40 +710,52 @@ NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, return NT_STATUS_INTERNAL_DB_ERROR; } - /* commit the transaction - this commits all the changes in - the ldb from the whole vampire. Note that this commit + /* prepare the transaction - this prepares to commit all the changes in + the ldb from the whole vampire. Note that this triggers the writing of the linked attribute backlinks. */ - if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) { - printf("Failed to commit vampire transaction\n"); + if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) { + printf("Failed to prepare_commit vampire transaction\n"); return NT_STATUS_INTERNAL_DB_ERROR; } - set_secrets = talloc_zero(s, struct libnet_set_join_secrets); + set_secrets = talloc(s, struct provision_store_self_join_settings); if (!set_secrets) { + r->out.error_string = NULL; + talloc_free(s); return NT_STATUS_NO_MEMORY; } - - set_secrets->in.domain_name = join->out.domain_name; - set_secrets->in.realm = join->out.realm; - set_secrets->in.account_name = account_name; - set_secrets->in.netbios_name = netbios_name; - set_secrets->in.join_type = SEC_CHAN_BDC; - set_secrets->in.join_password = join->out.join_password; - set_secrets->in.kvno = join->out.kvno; - set_secrets->in.domain_sid = join->out.domain_sid; - status = libnet_set_join_secrets(ctx, set_secrets, set_secrets); + ZERO_STRUCTP(set_secrets); + set_secrets->domain_name = join->out.domain_name; + set_secrets->realm = join->out.realm; + set_secrets->account_name = account_name; + set_secrets->netbios_name = netbios_name; + set_secrets->secure_channel_type = SEC_CHAN_BDC; + set_secrets->machine_password = join->out.join_password; + set_secrets->key_version_number = join->out.kvno; + set_secrets->domain_sid = join->out.domain_sid; + + status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string); if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_steal(mem_ctx, set_secrets->out.error_string); + r->out.error_string = talloc_steal(mem_ctx, error_string); talloc_free(s); return status; } r->out.domain_name = talloc_steal(r, join->out.domain_name); r->out.domain_sid = talloc_steal(r, join->out.domain_sid); - talloc_free(s); + /* commit the transaction now we know the secrets were written + * out properly + */ + if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) { + printf("Failed to commit vampire transaction\n"); + return NT_STATUS_INTERNAL_DB_ERROR; + } + + talloc_free(s); + return NT_STATUS_OK; } diff --git a/source4/librpc/ndr/py_security.c b/source4/librpc/ndr/py_security.c index 02dc059f05..1b185a51b5 100644 --- a/source4/librpc/ndr/py_security.c +++ b/source4/librpc/ndr/py_security.c @@ -23,6 +23,11 @@ #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif +PyObject *py_dom_sid_FromSid(struct dom_sid *sid) +{ + return py_talloc_reference(&dom_sid_Type, sid); +} + static void PyType_AddMethods(PyTypeObject *type, PyMethodDef *methods) { PyObject *dict; diff --git a/source4/param/config.mk b/source4/param/config.mk index 6e5290b64d..45eb836bb4 100644 --- a/source4/param/config.mk +++ b/source4/param/config.mk @@ -13,7 +13,7 @@ PUBLIC_HEADERS += param/param.h PC_FILES += $(paramsrcdir)/samba-hostconfig.pc [SUBSYSTEM::PROVISION] -PRIVATE_DEPENDENCIES = LIBPYTHON pyldb pyparam_util +PRIVATE_DEPENDENCIES = LIBPYTHON pyldb pyparam_util python_dcerpc_security PROVISION_OBJ_FILES = $(paramsrcdir)/provision.o $(param_OBJ_FILES) diff --git a/source4/param/provision.c b/source4/param/provision.c index bbc6837a90..355af794d8 100644 --- a/source4/param/provision.c +++ b/source4/param/provision.c @@ -2,7 +2,8 @@ Unix SMB/CIFS implementation. Samba utility functions Copyright (C) Jelmer Vernooij 2008 - + Copyright (C) Andrew Bartlett 2005 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or @@ -20,15 +21,21 @@ #include "includes.h" #include "auth/auth.h" #include "lib/ldb_wrap.h" +#include "ldb/include/ldb.h" +#include "ldb_errors.h" #include "libcli/raw/libcliraw.h" #include "librpc/ndr/libndr.h" #include "param/param.h" #include "param/provision.h" +#include "param/secrets.h" #include +#include "lib/talloc/pytalloc.h" +#include "librpc/rpc/pyrpc.h" #include "scripting/python/modules.h" #include "lib/ldb/pyldb.h" #include "param/pyparam.h" +#include "librpc/ndr/py_security.h" NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct provision_settings *settings, @@ -144,3 +151,125 @@ NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, return NT_STATUS_OK; } + +extern void initldb(void); +extern void initsecurity(void); + +NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, + struct tevent_context *event_ctx, + struct provision_store_self_join_settings *settings, + const char **error_string) +{ + int ret; + PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters, *py_sid; + struct ldb_context *ldb; + TALLOC_CTX *tmp_mem = talloc_new(mem_ctx); + if (!tmp_mem) { + return NT_STATUS_NO_MEMORY; + } + + /* Open the secrets database */ + ldb = secrets_db_connect(tmp_mem, event_ctx, lp_ctx); + if (!ldb) { + *error_string + = talloc_asprintf(mem_ctx, + "Could not open secrets database"); + talloc_free(tmp_mem); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + ret = ldb_transaction_start(ldb); + + if (ret != LDB_SUCCESS) { + *error_string + = talloc_asprintf(mem_ctx, + "Could not start transaction on secrets database: %s", ldb_errstring(ldb)); + talloc_free(tmp_mem); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + py_load_samba_modules(); + Py_Initialize(); + py_update_path("bin"); /* FIXME: Can't assume this is always the case */ + initldb(); + initsecurity(); + provision_mod = PyImport_Import(PyString_FromString("samba.provision")); + + if (provision_mod == NULL) { + PyErr_Print(); + *error_string + = talloc_asprintf(mem_ctx, "Unable to import provision Python module."); + talloc_free(tmp_mem); + return NT_STATUS_UNSUCCESSFUL; + } + + provision_dict = PyModule_GetDict(provision_mod); + + if (provision_dict == NULL) { + *error_string + = talloc_asprintf(mem_ctx, "Unable to get dictionary for provision module"); + talloc_free(tmp_mem); + return NT_STATUS_UNSUCCESSFUL; + } + + provision_fn = PyDict_GetItemString(provision_dict, "secretsdb_self_join"); + if (provision_fn == NULL) { + PyErr_Print(); + *error_string + = talloc_asprintf(mem_ctx, "Unable to get provision_become_dc function"); + talloc_free(tmp_mem); + return NT_STATUS_UNSUCCESSFUL; + } + + parameters = PyDict_New(); + + PyDict_SetItemString(parameters, "secretsdb", + PyLdb_FromLdbContext(ldb)); + PyDict_SetItemString(parameters, "domain", + PyString_FromString(settings->domain_name)); + PyDict_SetItemString(parameters, "domain", + PyString_FromString(settings->domain_name)); + PyDict_SetItemString(parameters, "realm", + PyString_FromString(settings->realm)); + PyDict_SetItemString(parameters, "machinepass", + PyString_FromString(settings->machine_password)); + PyDict_SetItemString(parameters, "netbiosname", + PyString_FromString(settings->netbios_name)); + + py_sid = py_dom_sid_FromSid(settings->domain_sid); + + PyDict_SetItemString(parameters, "domainsid", + py_sid); + + PyDict_SetItemString(parameters, "secure_channel_type", + PyInt_FromLong(settings->secure_channel_type)); + + PyDict_SetItemString(parameters, "key_version_number", + PyInt_FromLong(settings->key_version_number)); + + py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters); + + Py_DECREF(parameters); + + if (py_result == NULL) { + ldb_transaction_cancel(ldb); + talloc_free(tmp_mem); + + PyErr_Print(); + PyErr_Clear(); + return NT_STATUS_UNSUCCESSFUL; + } + + ret = ldb_transaction_commit(ldb); + if (ret != LDB_SUCCESS) { + *error_string + = talloc_asprintf(mem_ctx, + "Could not commit transaction on secrets database: %s", ldb_errstring(ldb)); + talloc_free(tmp_mem); + return NT_STATUS_INTERNAL_DB_ERROR; + } + + talloc_free(tmp_mem); + + return NT_STATUS_OK; +} diff --git a/source4/param/provision.h b/source4/param/provision.h index af9685d292..c3b3bb88d8 100644 --- a/source4/param/provision.h +++ b/source4/param/provision.h @@ -44,8 +44,24 @@ struct provision_result { struct loadparm_context *lp_ctx; }; +struct provision_store_self_join_settings { + const char *domain_name; + const char *realm; + const char *netbios_name; + const char *account_name; + enum netr_SchannelType secure_channel_type; + const char *machine_password; + int key_version_number; + struct dom_sid *domain_sid; +}; + NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct provision_settings *settings, struct provision_result *result); +NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, + struct tevent_context *ev_ctx, + struct provision_store_self_join_settings *settings, + const char **error_string); + #endif /* _PROVISION_H_ */ diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 68a50b2e37..8af24f21cf 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -48,11 +48,13 @@ from samba import DS_DOMAIN_FUNCTION_2000, DS_DC_FUNCTION_2008_R2 from samba.samdb import SamDB from samba.idmap import IDmapDB from samba.dcerpc import security +from samba.ndr import ndr_pack import urllib from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, timestring from ms_schema import read_ms_schema from ms_display_specifiers import read_ms_ldif from signal import SIGTERM +from dcerpc.misc import SEC_CHAN_BDC, SEC_CHAN_WKSTA __docformat__ = "restructuredText" @@ -318,7 +320,6 @@ def provision_paths_from_lp(lp, dnsdomain): """ paths = ProvisionPaths() paths.private_dir = lp.get("private dir") - paths.keytab = "secrets.keytab" paths.dns_keytab = "dns.keytab" paths.shareconf = os.path.join(paths.private_dir, "share.ldb") @@ -658,12 +659,75 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, samdb.transaction_commit() +def secretsdb_self_join(secretsdb, domain, + netbiosname, domainsid, machinepass, + realm=None, dnsdomain=None, + keytab_path=None, + key_version_number=1, + secure_channel_type=SEC_CHAN_WKSTA): + """Add domain join-specific bits to a secrets database. + + :param secretsdb: Ldb Handle to the secrets database + :param machinepass: Machine password + """ + attrs=["whenChanged", + "secret", + "priorSecret", + "priorChanged", + "krb5Keytab", + "privateKeytab"] + + + msg = ldb.Message(ldb.Dn(secretsdb, "flatname=%s,cn=Primary Domains" % domain)); + msg["secureChannelType"] = str(secure_channel_type) + msg["flatname"] = [domain] + msg["objectClass"] = ["top", "primaryDomain"] + if realm is not None: + if dnsdomain is None: + dnsdomain = realm.lower() + msg["objectClass"] = ["top", "primaryDomain", "kerberosSecret"] + msg["realm"] = realm + msg["saltPrincipal"] = "host/%s.%s@%s" % (netbiosname.lower(), dnsdomain.lower(), realm.upper()) + msg["msDS-KeyVersionNumber"] = [str(key_version_number)] + msg["privateKeytab"] = ["secrets.keytab"]; + + + msg["secret"] = [machinepass] + msg["samAccountName"] = ["%s$" % netbiosname] + msg["secureChannelType"] = [str(secure_channel_type)] + msg["objectSid"] = [ndr_pack(domainsid)] + + res = secretsdb.search(base="cn=Primary Domains", + attrs=attrs, + expression=("(&(|(flatname=%s)(realm=%s)(objectSid=%s))(objectclass=primaryDomain))" % (domain, realm, str(domainsid))), + scope=SCOPE_ONELEVEL) + + for del_msg in res: + if del_msg.dn is not msg.dn: + secretsdb.delete(del_msg.dn) + + res = secretsdb.search(base=msg.dn, attrs=attrs, scope=SCOPE_BASE) + + if len(res) == 1: + msg["priorSecret"] = res[0]["secret"] + msg["priorWhenChanged"] = res[0]["whenChanged"] + + if res["privateKeytab"] is not None: + msg["privateKeytab"] = res[0]["privateKeytab"] + if res["krb5Keytab"] is not None: + msg["krb5Keytab"] = res[0]["krb5Keytab"] -def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain, - netbiosname, domainsid, keytab_path, samdb_url, - dns_keytab_path, dnspass, machinepass): - """Add DC-specific bits to a secrets database. + for el in msg: + el.set_flags(ldb.FLAG_MOD_REPLACE) + secretsdb.modify(msg) + else: + secretsdb.add(msg) + + +def secretsdb_setup_dns(secretsdb, setup_path, realm, dnsdomain, + dns_keytab_path, dnspass): + """Add DNS specific bits to a secrets database. :param secretsdb: Ldb Handle to the secrets database :param setup_path: Setup path function @@ -676,18 +740,6 @@ def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain, "DNSPASS_B64": b64encode(dnspass), }) - setup_ldb(secretsdb, setup_path("secrets_self_join.ldif"), { - "MACHINEPASS_B64": b64encode(machinepass), - "DOMAIN": domain, - "REALM": realm, - "DNSDOMAIN": dnsdomain, - "DOMAINSID": str(domainsid), - "SECRETS_KEYTAB": keytab_path, - "NETBIOSNAME": netbiosname, - "SALT_PRINCIPAL": "host/%s.%s@%s" % (netbiosname.lower(), dnsdomain.lower(), realm.upper()), - "KEY_VERSION_NUMBER": "1" - }) - def setup_secretsdb(path, setup_path, session_info, credentials, lp): """Setup the secrets database. @@ -707,6 +759,7 @@ def setup_secretsdb(path, setup_path, session_info, credentials, lp): secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif")) secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials, lp=lp) + secrets_ldb.transaction_start() secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif")) if credentials is not None and credentials.authentication_requested(): @@ -1242,16 +1295,18 @@ def provision(setup_dir, message, session_info, # Only make a zone file on the first DC, it should be replicated with DNS replication if serverrole == "domain controller": - secrets_ldb = Ldb(paths.secrets, session_info=session_info, - credentials=credentials, lp=lp) - secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, + secretsdb_self_join(secrets_ldb, domain=domain, realm=names.realm, + dnsdomain=names.dnsdomain, netbiosname=names.netbiosname, domainsid=domainsid, - keytab_path=paths.keytab, samdb_url=paths.samdb, + machinepass=machinepass, + secure_channel_type=SEC_CHAN_BDC) + + secretsdb_setup_dns(secrets_ldb, setup_path, + realm=names.realm, dnsdomain=names.dnsdomain, dns_keytab_path=paths.dns_keytab, - dnspass=dnspass, machinepass=machinepass, - dnsdomain=names.dnsdomain) + dnspass=dnspass) domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID") assert isinstance(domainguid, str) @@ -1276,6 +1331,8 @@ def provision(setup_dir, message, session_info, realm=names.realm) message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf) + #Now commit the secrets.ldb to disk + secrets_ldb.transaction_commit() if provision_backend is not None: if ldap_backend_type == "fedora-ds": -- cgit From 9d9bd31bf9069f8e0ddf0cd49da49e96dbec8ea5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Sep 2009 20:28:42 -0700 Subject: s4:py_security Add missing header --- source4/librpc/ndr/py_security.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 source4/librpc/ndr/py_security.h (limited to 'source4') diff --git a/source4/librpc/ndr/py_security.h b/source4/librpc/ndr/py_security.h new file mode 100644 index 0000000000..9d200faf8e --- /dev/null +++ b/source4/librpc/ndr/py_security.h @@ -0,0 +1,23 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "libcli/security/security.h" + +/* a lone prototype for this function, because it's python */ +PyObject *py_dom_sid_FromSid(struct dom_sid *sid); -- cgit From 5656c22bea56773e33779d51fba912d2ae797134 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 21 Sep 2009 05:15:38 +0200 Subject: s4:dsdb/resolve_oids: check return values in recursion metze --- source4/dsdb/samdb/ldb_modules/resolve_oids.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/resolve_oids.c b/source4/dsdb/samdb/ldb_modules/resolve_oids.c index f4d9eba17a..c9733f99a1 100644 --- a/source4/dsdb/samdb/ldb_modules/resolve_oids.c +++ b/source4/dsdb/samdb/ldb_modules/resolve_oids.c @@ -98,19 +98,22 @@ static int resolve_oids_parse_tree_replace(struct ldb_context *ldb, const char *p1; const void *p2; struct ldb_val *valp = NULL; + int ret; switch (tree->operation) { case LDB_OP_AND: case LDB_OP_OR: for (i=0;iu.list.num_elements;i++) { - resolve_oids_parse_tree_replace(ldb, schema, + ret = resolve_oids_parse_tree_replace(ldb, schema, tree->u.list.elements[i]); + if (ret != LDB_SUCCESS) { + return ret; + } } return LDB_SUCCESS; case LDB_OP_NOT: - resolve_oids_parse_tree_replace(ldb, schema, + return resolve_oids_parse_tree_replace(ldb, schema, tree->u.isnot.child); - return LDB_SUCCESS; case LDB_OP_EQUALITY: case LDB_OP_GREATER: case LDB_OP_LESS: -- cgit From f917044ec032ad3a3cdc6030f5c63274d7327c2e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 21 Sep 2009 05:15:59 +0200 Subject: s4:dsdb/resolve_oids: add fast pathes for the common operations without oids metze --- source4/dsdb/samdb/ldb_modules/resolve_oids.c | 217 ++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/resolve_oids.c b/source4/dsdb/samdb/ldb_modules/resolve_oids.c index c9733f99a1..053c2ec55f 100644 --- a/source4/dsdb/samdb/ldb_modules/resolve_oids.c +++ b/source4/dsdb/samdb/ldb_modules/resolve_oids.c @@ -21,6 +21,199 @@ #include "ldb_module.h" #include "dsdb/samdb/samdb.h" +static int resolve_oids_need_value(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct dsdb_attribute *a, + const struct ldb_val *valp) +{ + const struct dsdb_attribute *va = NULL; + const struct dsdb_class *vo = NULL; + const void *p2; + char *str = NULL; + + if (a->syntax->oMSyntax != 6) { + return LDB_ERR_COMPARE_FALSE; + } + + if (valp) { + p2 = memchr(valp->data, '.', valp->length); + } else { + p2 = NULL; + } + + if (!p2) { + return LDB_ERR_COMPARE_FALSE; + } + + switch (a->attributeID_id) { + case DRSUAPI_ATTRIBUTE_objectClass: + case DRSUAPI_ATTRIBUTE_subClassOf: + case DRSUAPI_ATTRIBUTE_auxiliaryClass: + case DRSUAPI_ATTRIBUTE_systemPossSuperiors: + case DRSUAPI_ATTRIBUTE_possSuperiors: + str = talloc_strndup(ldb, (char *)valp->data, valp->length); + if (!str) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + vo = dsdb_class_by_governsID_oid(schema, str); + talloc_free(str); + if (!vo) { + return LDB_ERR_COMPARE_FALSE; + } + return LDB_ERR_COMPARE_TRUE; + case DRSUAPI_ATTRIBUTE_systemMustContain: + case DRSUAPI_ATTRIBUTE_systemMayContain: + case DRSUAPI_ATTRIBUTE_mustContain: + case DRSUAPI_ATTRIBUTE_mayContain: + str = talloc_strndup(ldb, (char *)valp->data, valp->length); + if (!str) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + va = dsdb_attribute_by_attributeID_oid(schema, str); + talloc_free(str); + if (!va) { + return LDB_ERR_COMPARE_FALSE; + } + return LDB_ERR_COMPARE_TRUE; + case DRSUAPI_ATTRIBUTE_governsID: + case DRSUAPI_ATTRIBUTE_attributeID: + case DRSUAPI_ATTRIBUTE_attributeSyntax: + return LDB_ERR_COMPARE_FALSE; + } + + return LDB_ERR_COMPARE_FALSE; +} + +static int resolve_oids_parse_tree_need(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct ldb_parse_tree *tree) +{ + int i; + const struct dsdb_attribute *a = NULL; + const char *attr; + const char *p1; + const void *p2; + const struct ldb_val *valp = NULL; + int ret; + + switch (tree->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;iu.list.num_elements;i++) { + ret = resolve_oids_parse_tree_need(ldb, schema, + tree->u.list.elements[i]); + if (ret != LDB_ERR_COMPARE_FALSE) { + return ret; + } + } + return LDB_ERR_COMPARE_FALSE; + case LDB_OP_NOT: + return resolve_oids_parse_tree_need(ldb, schema, + tree->u.isnot.child); + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + attr = tree->u.equality.attr; + valp = &tree->u.equality.value; + break; + case LDB_OP_SUBSTRING: + attr = tree->u.substring.attr; + break; + case LDB_OP_PRESENT: + attr = tree->u.present.attr; + break; + case LDB_OP_EXTENDED: + attr = tree->u.extended.attr; + valp = &tree->u.extended.value; + break; + default: + return LDB_ERR_COMPARE_FALSE; + } + + p1 = strchr(attr, '.'); + + if (valp) { + p2 = memchr(valp->data, '.', valp->length); + } else { + p2 = NULL; + } + + if (!p1 && !p2) { + return LDB_ERR_COMPARE_FALSE; + } + + if (p1) { + a = dsdb_attribute_by_attributeID_oid(schema, attr); + } else { + a = dsdb_attribute_by_lDAPDisplayName(schema, attr); + } + if (!a) { + return LDB_ERR_COMPARE_FALSE; + } + + if (!p2) { + return LDB_ERR_COMPARE_FALSE; + } + + if (a->syntax->oMSyntax != 6) { + return LDB_ERR_COMPARE_FALSE; + } + + return resolve_oids_need_value(ldb, schema, a, valp); +} + +static int resolve_oids_element_need(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct ldb_message_element *el) +{ + int i; + const struct dsdb_attribute *a = NULL; + const char *p1; + + p1 = strchr(el->name, '.'); + + if (p1) { + a = dsdb_attribute_by_attributeID_oid(schema, el->name); + } else { + a = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + } + if (!a) { + return LDB_ERR_COMPARE_FALSE; + } + + for (i=0; i < el->num_values; i++) { + int ret; + ret = resolve_oids_need_value(ldb, schema, a, + &el->values[i]); + if (ret != LDB_ERR_COMPARE_FALSE) { + return ret; + } + } + + return LDB_ERR_COMPARE_FALSE; +} + +static int resolve_oids_message_need(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct ldb_message *msg) +{ + int i; + + for (i=0; i < msg->num_elements; i++) { + int ret; + ret = resolve_oids_element_need(ldb, schema, + &msg->elements[i]); + if (ret != LDB_ERR_COMPARE_FALSE) { + return ret; + } + } + + return LDB_ERR_COMPARE_FALSE; +} + static int resolve_oids_replace_value(struct ldb_context *ldb, struct dsdb_schema *schema, const struct dsdb_attribute *a, @@ -278,6 +471,14 @@ static int resolve_oids_search(struct ldb_module *module, struct ldb_request *re return ldb_next_request(module, req); } + ret = resolve_oids_parse_tree_need(ldb, schema, + req->op.search.tree); + if (ret == LDB_ERR_COMPARE_FALSE) { + return ldb_next_request(module, req); + } else if (ret != LDB_ERR_COMPARE_TRUE) { + return ret; + } + ac = talloc(req, struct resolve_oids_context); if (ac == NULL) { ldb_oom(ldb); @@ -335,6 +536,14 @@ static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + ret = resolve_oids_message_need(ldb, schema, + req->op.add.message); + if (ret == LDB_ERR_COMPARE_FALSE) { + return ldb_next_request(module, req); + } else if (ret != LDB_ERR_COMPARE_TRUE) { + return ret; + } + ac = talloc(req, struct resolve_oids_context); if (ac == NULL) { ldb_oom(ldb); @@ -388,6 +597,14 @@ static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *re return ldb_next_request(module, req); } + ret = resolve_oids_message_need(ldb, schema, + req->op.mod.message); + if (ret == LDB_ERR_COMPARE_FALSE) { + return ldb_next_request(module, req); + } else if (ret != LDB_ERR_COMPARE_TRUE) { + return ret; + } + ac = talloc(req, struct resolve_oids_context); if (ac == NULL) { ldb_oom(ldb); -- cgit From 23ffccd5d7c9a88d479f82043ff1b6efe938cc6a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Sep 2009 21:32:16 -0700 Subject: s4:provision Make us Windows 2008 level by defualt again Also add a note to clarify that this should not be changed without discussion and consensus. We don't want this bouncing around. Paramater support to allow optional selection of Win2003 mode welcomed. Andrew Bartlett --- source4/scripting/python/samba/provision.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 8af24f21cf..b00f240257 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -44,7 +44,7 @@ from credentials import Credentials, DONT_USE_KERBEROS from auth import system_session, admin_session from samba import version, Ldb, substitute_var, valid_netbios_name from samba import check_all_substituted -from samba import DS_DOMAIN_FUNCTION_2000, DS_DC_FUNCTION_2008_R2 +from samba import DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2008, DS_DC_FUNCTION_2008, DS_DC_FUNCTION_2008_R2 from samba.samdb import SamDB from samba.idmap import IDmapDB from samba.dcerpc import security @@ -895,9 +895,10 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, :note: This will wipe the main SAM database file! """ - domainFunctionality = DS_DOMAIN_FUNCTION_2000 - forestFunctionality = DS_DOMAIN_FUNCTION_2000 - domainControllerFunctionality = DS_DC_FUNCTION_2008_R2 + # Do NOT change these default values without discussion with the team and reslease manager. + domainFunctionality = DS_DOMAIN_FUNCTION_2008 + forestFunctionality = DS_DOMAIN_FUNCTION_2008 + domainControllerFunctionality = DS_DC_FUNCTION_2008 # Also wipes the database setup_samdb_partitions(path, setup_path, message=message, lp=lp, -- cgit From f0c080a484ad71ea3ecc38919178986e354501db Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Mon, 21 Sep 2009 11:53:19 +0200 Subject: s4:scripts - Reintroduce "-H" parameter I removed it since on some scripts it was present, on others not - so I thought it wouldn't be really needed. This was a bad decision (pointed out by abartlet). So I reintroduce it on all scripts (to have consistent parameters). --- source4/setup/domainlevel | 9 +++++++-- source4/setup/enableaccount | 10 ++++++++-- source4/setup/newuser | 10 ++++++++-- source4/setup/pwsettings | 9 +++++++-- source4/setup/setexpiry | 10 ++++++++-- source4/setup/setpassword | 10 ++++++++-- 6 files changed, 46 insertions(+), 12 deletions(-) (limited to 'source4') diff --git a/source4/setup/domainlevel b/source4/setup/domainlevel index b49150ff2d..ceab735c8f 100755 --- a/source4/setup/domainlevel +++ b/source4/setup/domainlevel @@ -39,6 +39,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--quiet", help="Be quiet", action="store_true") parser.add_option("--forest", help="The forest function level (2000 | 2003 | 2008 | 2008_R2). We don't support the 2003 with mixed domains (NT4 DC support) level.", type=str) @@ -60,8 +61,12 @@ if len(args) == 0: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) domain_dn = SamDB.domain_dn(samdb) diff --git a/source4/setup/enableaccount b/source4/setup/enableaccount index 0ca5b39faa..f8f727c1ee 100755 --- a/source4/setup/enableaccount +++ b/source4/setup/enableaccount @@ -36,6 +36,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--filter", help="LDAP Filter to set password on", type=str) opts, args = parser.parse_args() @@ -54,6 +55,11 @@ if filter is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + samdb.enable_account(filter) diff --git a/source4/setup/newuser b/source4/setup/newuser index 10af55a458..ef65d36dfb 100755 --- a/source4/setup/newuser +++ b/source4/setup/newuser @@ -37,6 +37,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--unixname", help="Unix Username", type=str) parser.add_option("--must-change-at-next-login", help="Force password to be changed on next login", action="store_true") @@ -58,6 +59,11 @@ if opts.unixname is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + samdb.newuser(username, opts.unixname, password, force_password_change_at_next_login_req=opts.must_change_at_next_login) diff --git a/source4/setup/pwsettings b/source4/setup/pwsettings index 6a5e18ef59..0bb39d9757 100755 --- a/source4/setup/pwsettings +++ b/source4/setup/pwsettings @@ -39,6 +39,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--quiet", help="Be quiet", action="store_true") parser.add_option("--complexity", help="The password complexity (on | off | default). Default is 'on'", type=str) @@ -67,8 +68,12 @@ if len(args) == 0: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) domain_dn = SamDB.domain_dn(samdb) res = samdb.search(domain_dn, scope=ldb.SCOPE_BASE, diff --git a/source4/setup/setexpiry b/source4/setup/setexpiry index 1572555b8c..57c46f4dff 100755 --- a/source4/setup/setexpiry +++ b/source4/setup/setexpiry @@ -37,6 +37,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--filter", help="LDAP Filter to set password on", type=str) parser.add_option("--days", help="Days to expiry", type=int) parser.add_option("--noexpiry", help="Password does never expire", action="store_true") @@ -59,6 +60,11 @@ if filter is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + samdb.setexpiry(filter, days*24*3600, no_expiry_req=opts.noexpiry) diff --git a/source4/setup/setpassword b/source4/setup/setpassword index d8a2a1144a..c150f518ad 100755 --- a/source4/setup/setpassword +++ b/source4/setup/setpassword @@ -38,6 +38,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--filter", help="LDAP Filter to set password on", type=str) parser.add_option("--newpassword", help="Set password", type=str) parser.add_option("--must-change-at-next-login", help="Force password to be changed on next login", action="store_true") @@ -62,7 +63,12 @@ if filter is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + samdb.setpassword(filter, password, force_password_change_at_next_login=opts.must_change_at_next_login) -- cgit From 32f4afd617944153ce17ea9b4cfe23fb29fcbc68 Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Mon, 21 Sep 2009 11:59:07 +0200 Subject: s4:libnet_become_dc - bump down the level requested by abartlet --- source4/libnet/libnet_become_dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index c4e786c833..70dee9597b 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -2101,7 +2101,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s) vd[0] = data_blob_talloc(vd, NULL, 4); if (composite_nomem(vd[0].data, c)) return; - SIVAL(vd[0].data, 0, DS_DC_FUNCTION_2008_R2); + SIVAL(vd[0].data, 0, DS_DC_FUNCTION_2008); vs[0].blob = &vd[0]; -- cgit From 7373bb79d415ae1cc1336aea779e9c2a2ed028d4 Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Mon, 21 Sep 2009 13:53:47 +0200 Subject: s4:samdb/tools - That should fix now the last failures --- source4/scripting/python/samba/samdb.py | 4 ++-- source4/setup/setexpiry | 2 ++ source4/setup/setpassword | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index 239dd6a6ea..39cf1d6c40 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -202,8 +202,8 @@ userPassword:: %s self.transaction_start() try: res = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, - expression=filter, - attrs=["userAccountControl", "accountExpires"]) + expression=filter, + attrs=["userAccountControl", "accountExpires"]) assert(len(res) == 1) user_dn = res[0].dn diff --git a/source4/setup/setexpiry b/source4/setup/setexpiry index 57c46f4dff..2740326f2b 100755 --- a/source4/setup/setexpiry +++ b/source4/setup/setexpiry @@ -44,6 +44,8 @@ parser.add_option("--noexpiry", help="Password does never expire", action="store opts, args = parser.parse_args() +filter = opts.filter + if (len(args) == 0) and (filter is None): print "Either the username or '--filter' must be specified!" parser.print_usage() diff --git a/source4/setup/setpassword b/source4/setup/setpassword index c150f518ad..57772be7a7 100755 --- a/source4/setup/setpassword +++ b/source4/setup/setpassword @@ -70,5 +70,5 @@ else: samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) -samdb.setpassword(filter, password, force_password_change_at_next_login=opts.must_change_at_next_login) +samdb.setpassword(filter, password, force_password_change_at_next_login_req=opts.must_change_at_next_login) -- cgit From 63f280cfefdd0c0281a25c4068481dab226d0c3e Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Mon, 21 Sep 2009 17:20:49 +0200 Subject: s4:provision - Fix up ProvisioningError class as suggested by Jelmer --- source4/scripting/python/samba/provision.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index b00f240257..9a41709830 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -58,11 +58,6 @@ from dcerpc.misc import SEC_CHAN_BDC, SEC_CHAN_WKSTA __docformat__ = "restructuredText" - -class ProvisioningError(ValueError): - pass - - def find_setup_dir(): """Find the setup directory used by provision.""" dirname = os.path.dirname(__file__) @@ -81,6 +76,11 @@ def find_setup_dir(): DEFAULTSITE = "Default-First-Site-Name" +# Exception classes + +class ProvisioningError(Exception): + """A generic provision error.""" + class InvalidNetbiosName(Exception): """A specified name was not a valid NetBIOS name.""" def __init__(self, name): -- cgit From 8738b83a446ef667bc162b04affc17dbba7e58a8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Sep 2009 11:59:33 -0700 Subject: s4:provision Make our default salt match our server behaviour We need to look into salting algorithms further. Andrew Bartlett --- source4/scripting/python/samba/provision.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 9a41709830..af706d08dd 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -687,7 +687,7 @@ def secretsdb_self_join(secretsdb, domain, dnsdomain = realm.lower() msg["objectClass"] = ["top", "primaryDomain", "kerberosSecret"] msg["realm"] = realm - msg["saltPrincipal"] = "host/%s.%s@%s" % (netbiosname.lower(), dnsdomain.lower(), realm.upper()) + msg["saltPrincipal"] = "host/%s.%s@%s" % (netbiosname, dnsdomain.lower(), realm.upper()) msg["msDS-KeyVersionNumber"] = [str(key_version_number)] msg["privateKeytab"] = ["secrets.keytab"]; -- cgit From 1afc7c453c1d5f7e761e46cdc69900305a149820 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Sep 2009 12:28:38 -0700 Subject: s4:kerberos Fix the salt to match Windows 2008. The previous commit changed the wrong end - we must fix our server, not our client. Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/password_hash.c | 2 +- source4/scripting/python/samba/provision.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a04e52469d..a50e5b4a66 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -248,7 +248,7 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) char *name; char *saltbody; - name = talloc_strdup(io->ac, io->u.sAMAccountName); + name = strlower_talloc(io->ac, io->u.sAMAccountName); if (!name) { ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index af706d08dd..9a41709830 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -687,7 +687,7 @@ def secretsdb_self_join(secretsdb, domain, dnsdomain = realm.lower() msg["objectClass"] = ["top", "primaryDomain", "kerberosSecret"] msg["realm"] = realm - msg["saltPrincipal"] = "host/%s.%s@%s" % (netbiosname, dnsdomain.lower(), realm.upper()) + msg["saltPrincipal"] = "host/%s.%s@%s" % (netbiosname.lower(), dnsdomain.lower(), realm.upper()) msg["msDS-KeyVersionNumber"] = [str(key_version_number)] msg["privateKeytab"] = ["secrets.keytab"]; -- cgit