The branch, master has been updated via e16a2a1fa941511a8eeefd05b397dd934a77c9f6 (commit) via 84dca625cab96f72123308d80a5aeed5fc42f0c5 (commit) via bc354fb1a6fd524629434c199e2ca260a8400bb4 (commit) via 271b5af92e9aada36adc648a6dd43a13c5aed340 (commit) via ba58edd0bc2d77c6ed1b6a76f33787da9031db5b (commit) via d6c44a704e9a138dba8398f45e9af2601826f659 (commit) from 48a07321479c14a6618bb21302d27fd9606efbdd (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit e16a2a1fa941511a8eeefd05b397dd934a77c9f6 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Jul 16 08:29:43 2009 +1000 s4:gensec Rework gensec_krb5 mutual authentication defaults When emulating Samba3 (which we do to ensure we don't break compatability), don't do mutual authentication by default, as it breaks the session key with AES and isn't what Samba3 does anyway. Andrew Bartlett commit 84dca625cab96f72123308d80a5aeed5fc42f0c5 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jul 14 13:22:38 2009 +1000 s4:heimdal The implied GSS_C_MUTUAL_FLAG depends on AP_OPTS_MUTUAL_REQUIRED We had previously assumed it was unconditional. Samba3 didn't mind very much, but Samba4's samba3-like client did, and the behaviour differed to Win2008 behaviour. Andrew Bartlett commit bc354fb1a6fd524629434c199e2ca260a8400bb4 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jul 14 10:19:16 2009 +1000 s4:gensec Allow mutual auth to be turned off in 'fake_gssapi_krb5' This allows the older 'like Samba3' GENSEC krb5 implementation to work against Windows 2008. I'm using this to track down interop issues in this area. Andrew Bartlett commit 271b5af92e9aada36adc648a6dd43a13c5aed340 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jul 14 08:15:50 2009 +1000 s4:dsdb Handle dc/domain/forest functional levels properly Rather than have the functional levels scattered in 4 different, unconnected locations, the provision script now sets it, and the rootdse module maintains it's copy only as a cached view onto the original values. We also use the functional level to determine if we should store AES Kerberos keys. Andrew Bartlett commit ba58edd0bc2d77c6ed1b6a76f33787da9031db5b Author: Andrew Bartlett <abart...@samba.org> Date: Tue Jul 14 08:00:09 2009 +1000 Add a way to set an opaque integer onto a samdb This will allow us to set some more flags into ldb during the provision. commit d6c44a704e9a138dba8398f45e9af2601826f659 Author: Timur I. Bakeyev <ti...@freebsd.org> Date: Sun Jul 12 23:36:08 2009 +0000 Add ad-schema/*.txt and utils to the installmisc.sh Install other useful scripts from the setup/ directory, not only provisioning ones. Also install setup/ad-schema/*.txt files to the SETUPDIR. These are necessary for 'provision' to work properly. ----------------------------------------------------------------------- Summary of changes: source4/auth/gensec/gensec_krb5.c | 68 ++++++---- source4/dsdb/samdb/ldb_modules/password_hash.c | 7 +- source4/dsdb/samdb/ldb_modules/rootdse.c | 140 +++++++++++++++++++- .../heimdal/lib/gssapi/krb5/accept_sec_context.c | 5 +- source4/script/installmisc.sh | 10 +- source4/scripting/python/pyglue.c | 65 +++++++++ source4/scripting/python/samba/__init__.py | 5 + source4/scripting/python/samba/provision.py | 24 +++- source4/scripting/python/samba/samdb.py | 8 + source4/setup/provision_basedn_modify.ldif | 4 +- source4/setup/provision_configuration.ldif | 2 +- source4/setup/provision_rootdse_add.ldif | 3 - source4/setup/provision_self_join.ldif | 4 +- 13 files changed, 293 insertions(+), 52 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index 09bdec5..f4ef36a 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -57,6 +57,7 @@ struct gensec_krb5_state { krb5_keyblock *keyblock; krb5_ticket *ticket; bool gssapi; + krb5_flags ap_req_options; }; static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state) @@ -88,7 +89,7 @@ static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state) return 0; } -static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security) +static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security, bool gssapi) { krb5_error_code ret; struct gensec_krb5_state *gensec_krb5_state; @@ -114,7 +115,7 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security) gensec_krb5_state->keyblock = NULL; gensec_krb5_state->session_key = data_blob(NULL, 0); gensec_krb5_state->pac = data_blob(NULL, 0); - gensec_krb5_state->gssapi = false; + gensec_krb5_state->gssapi = gssapi; talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy); @@ -186,12 +187,12 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security) return NT_STATUS_OK; } -static NTSTATUS gensec_krb5_server_start(struct gensec_security *gensec_security) +static NTSTATUS gensec_krb5_common_server_start(struct gensec_security *gensec_security, bool gssapi) { NTSTATUS nt_status; struct gensec_krb5_state *gensec_krb5_state; - nt_status = gensec_krb5_start(gensec_security); + nt_status = gensec_krb5_start(gensec_security, gssapi); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } @@ -202,26 +203,23 @@ static NTSTATUS gensec_krb5_server_start(struct gensec_security *gensec_security return NT_STATUS_OK; } -static NTSTATUS gensec_fake_gssapi_krb5_server_start(struct gensec_security *gensec_security) +static NTSTATUS gensec_krb5_server_start(struct gensec_security *gensec_security) { - NTSTATUS nt_status = gensec_krb5_server_start(gensec_security); + return gensec_krb5_common_server_start(gensec_security, false); +} - if (NT_STATUS_IS_OK(nt_status)) { - struct gensec_krb5_state *gensec_krb5_state; - gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data; - gensec_krb5_state->gssapi = true; - } - return nt_status; +static NTSTATUS gensec_fake_gssapi_krb5_server_start(struct gensec_security *gensec_security) +{ + return gensec_krb5_common_server_start(gensec_security, true); } -static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security) +static NTSTATUS gensec_krb5_common_client_start(struct gensec_security *gensec_security, bool gssapi) { struct gensec_krb5_state *gensec_krb5_state; krb5_error_code ret; NTSTATUS nt_status; struct ccache_container *ccache_container; const char *hostname; - krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED; const char *principal; krb5_data in_data; @@ -240,13 +238,26 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security return NT_STATUS_INVALID_PARAMETER; } - nt_status = gensec_krb5_start(gensec_security); + nt_status = gensec_krb5_start(gensec_security, gssapi); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data; gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START; + gensec_krb5_state->ap_req_options = AP_OPTS_USE_SUBKEY; + + if (gensec_krb5_state->gssapi) { + /* The Fake GSSAPI modal emulates Samba3, which does not do mutual authentication */ + if (gensec_setting_bool(gensec_security->settings, "gensec_fake_gssapi_krb5", "mutual", false)) { + gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; + } + } else { + /* The wrapping for KPASSWD (a user of the raw KRB5 API) should be mutually authenticated */ + if (gensec_setting_bool(gensec_security->settings, "gensec_krb5", "mutual", true)) { + gensec_krb5_state->ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; + } + } principal = gensec_get_target_principal(gensec_security); @@ -274,7 +285,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security if (ret == 0) { ret = krb5_mk_req_exact(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context, - ap_req_options, + gensec_krb5_state->ap_req_options, target_principal, &in_data, ccache_container->ccache, &gensec_krb5_state->enc_ticket); @@ -284,7 +295,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security } else { ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context, - ap_req_options, + gensec_krb5_state->ap_req_options, gensec_get_target_service(gensec_security), hostname, &in_data, ccache_container->ccache, @@ -328,16 +339,14 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security } } -static NTSTATUS gensec_fake_gssapi_krb5_client_start(struct gensec_security *gensec_security) +static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security) { - NTSTATUS nt_status = gensec_krb5_client_start(gensec_security); + return gensec_krb5_common_client_start(gensec_security, false); +} - if (NT_STATUS_IS_OK(nt_status)) { - struct gensec_krb5_state *gensec_krb5_state; - gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data; - gensec_krb5_state->gssapi = true; - } - return nt_status; +static NTSTATUS gensec_fake_gssapi_krb5_client_start(struct gensec_security *gensec_security) +{ + return gensec_krb5_common_client_start(gensec_security, true); } /** @@ -392,8 +401,13 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, } else { *out = data_blob_talloc(out_mem_ctx, gensec_krb5_state->enc_ticket.data, gensec_krb5_state->enc_ticket.length); } - gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_MUTUAL_AUTH; - nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED; + if (gensec_krb5_state->ap_req_options & AP_OPTS_MUTUAL_REQUIRED) { + gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_MUTUAL_AUTH; + nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED; + } else { + gensec_krb5_state->state_position = GENSEC_KRB5_DONE; + nt_status = NT_STATUS_OK; + } return nt_status; } diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a28ca1d..ef641ac 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1026,6 +1026,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) uint8_t zero16[16]; bool do_newer_keys = false; bool do_cleartext = false; + int *domainFunctionality; ZERO_STRUCT(zero16); ZERO_STRUCT(names); @@ -1064,10 +1065,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) _old_scb.sub.signature, SUPPLEMENTAL_CREDENTIALS_SIGNATURE); } } + /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */ + domainFunctionality = talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int); - /* TODO: do the correct check for this, it maybe depends on the functional level? */ - do_newer_keys = lp_parm_bool(ldb_get_opaque(ldb, "loadparm"), - NULL, "password_hash", "create_aes_key", false); + do_newer_keys = *domainFunctionality && (*domainFunctionality >= DS_BEHAVIOR_WIN2008); if (io->domain->store_cleartext && (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 7080fb6..59ea51d 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -59,6 +59,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data); char **server_sasl; const struct dsdb_schema *schema; + int *val; ldb = ldb_module_get_ctx(module); schema = dsdb_get_schema(ldb); @@ -77,7 +78,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms } } - if (do_attribute(attrs, "supportedControl")) { + if (priv && do_attribute(attrs, "supportedControl")) { int i; for (i = 0; i < priv->num_controls; i++) { char *control = talloc_strdup(msg, priv->controls[i]); @@ -91,7 +92,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms } } - if (do_attribute(attrs, "namingContexts")) { + if (priv && do_attribute(attrs, "namingContexts")) { int i; for (i = 0; i < priv->num_partitions; i++) { struct ldb_dn *dn = priv->partitions[i]; @@ -201,13 +202,37 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms } } - if (schema && do_attribute_explicit(attrs, "vendorVersion")) { + if (do_attribute_explicit(attrs, "vendorVersion")) { if (ldb_msg_add_fmt(msg, "vendorVersion", "%s", SAMBA_VERSION_STRING) != 0) { goto failed; } } + if (priv && do_attribute(attrs, "domainFunctionality") + && (val = talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int))) { + if (ldb_msg_add_fmt(msg, "domainFunctionality", + "%d", *val) != 0) { + goto failed; + } + } + + if (priv && do_attribute(attrs, "forestFunctionality") + && (val = talloc_get_type(ldb_get_opaque(ldb, "forestFunctionality"), int))) { + if (ldb_msg_add_fmt(msg, "forestFunctionality", + "%d", *val) != 0) { + goto failed; + } + } + + if (priv && do_attribute(attrs, "domainControllerFunctionality") + && (val = talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), int))) { + if (ldb_msg_add_fmt(msg, "domainControllerFunctionality", + "%d", *val) != 0) { + goto failed; + } + } + /* TODO: lots more dynamic attributes should be added here */ return LDB_SUCCESS; @@ -394,12 +419,17 @@ static int rootdse_request(struct ldb_module *module, struct ldb_request *req) static int rootdse_init(struct ldb_module *module) { + int ret; struct ldb_context *ldb; + struct ldb_result *res; struct private_data *data; + const char *attrs[] = { "msDS-Behavior-Version", NULL }; + const char *ds_attrs[] = { "dsServiceName", NULL }; + TALLOC_CTX *mem_ctx; ldb = ldb_module_get_ctx(module); - data = talloc(module, struct private_data); + data = talloc_zero(module, struct private_data); if (data == NULL) { return -1; } @@ -412,7 +442,107 @@ static int rootdse_init(struct ldb_module *module) ldb_set_default_dns(ldb); - return ldb_next_init(module); + ret = ldb_next_init(module); + + if (ret) { + return ret; + } + + mem_ctx = talloc_new(data); + if (!mem_ctx) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Now that the partitions are set up, do a search for: + - domainControllerFunctionality + - domainFunctionality + - forestFunctionality + + Then stuff these values into an opaque + */ + ret = ldb_search(ldb, mem_ctx, &res, + ldb_get_default_basedn(ldb), + LDB_SCOPE_BASE, attrs, NULL); + if (ret == LDB_SUCCESS && res->count == 1) { + int domain_behaviour_version + = ldb_msg_find_attr_as_int(res->msgs[0], + "msDS-Behavior-Version", -1); + if (domain_behaviour_version != -1) { + int *val = talloc(ldb, int); + if (!val) { + ldb_oom(ldb); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + *val = domain_behaviour_version; + ret = ldb_set_opaque(ldb, "domainFunctionality", val); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + } + } + + ret = ldb_search(ldb, mem_ctx, &res, + samdb_partitions_dn(ldb, mem_ctx), + LDB_SCOPE_BASE, attrs, NULL); + if (ret == LDB_SUCCESS && res->count == 1) { + int forest_behaviour_version + = ldb_msg_find_attr_as_int(res->msgs[0], + "msDS-Behavior-Version", -1); + if (forest_behaviour_version != -1) { + int *val = talloc(ldb, int); + if (!val) { + ldb_oom(ldb); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + *val = forest_behaviour_version; + ret = ldb_set_opaque(ldb, "forestFunctionality", val); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + } + } + + ret = ldb_search(ldb, mem_ctx, &res, + ldb_dn_new(mem_ctx, ldb, ""), + LDB_SCOPE_BASE, ds_attrs, NULL); + if (ret == LDB_SUCCESS && res->count == 1) { + struct ldb_dn *ds_dn + = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], + "dsServiceName"); + if (ds_dn) { + ret = ldb_search(ldb, mem_ctx, &res, ds_dn, + LDB_SCOPE_BASE, attrs, NULL); + if (ret == LDB_SUCCESS && res->count == 1) { + int domain_controller_behaviour_version + = ldb_msg_find_attr_as_int(res->msgs[0], + "msDS-Behavior-Version", -1); + if (domain_controller_behaviour_version != -1) { + int *val = talloc(ldb, int); + if (!val) { + ldb_oom(ldb); + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + *val = domain_controller_behaviour_version; + ret = ldb_set_opaque(ldb, + "domainControllerFunctionality", val); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + } + } + } + } + + talloc_free(mem_ctx); + + return LDB_SUCCESS; } static int rootdse_modify(struct ldb_module *module, struct ldb_request *req) diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c index e094485..8ead2bd 100644 --- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -522,7 +522,10 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status, * Samba style get some flags (but not DCE-STYLE) */ ctx->flags = - GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + if (ap_options & AP_OPTS_MUTUAL_REQUIRED) { + ctx->flags |= GSS_C_MUTUAL_FLAG; + } } } diff --git a/source4/script/installmisc.sh b/source4/script/installmisc.sh index 2bd34b1..0666ae1 100755 --- a/source4/script/installmisc.sh +++ b/source4/script/installmisc.sh @@ -8,11 +8,15 @@ cd $SRCDIR || exit 1 echo "Installing setup templates" mkdir -p $SETUPDIR || exit 1 +mkdir -p $SETUPDIR/ad-schema || exit 1 +cp setup/ad-schema/*.txt $SETUPDIR/ad-schema || exit 1 +for p in enableaccount newuser provision provision-backend setexpiry setpassword +do + chmod 0555 setup/$p + cp setup/$p $SETUPDIR || exit 1 +done cp setup/schema-map-* $SETUPDIR || exit 1 cp setup/DB_CONFIG $SETUPDIR || exit 1 -cp setup/provision-backend $SETUPDIR || exit 1 -cp setup/provision $SETUPDIR || exit 1 -cp setup/newuser $SETUPDIR || exit 1 cp setup/*.inf $SETUPDIR || exit 1 cp setup/*.ldif $SETUPDIR || exit 1 cp setup/*.reg $SETUPDIR || exit 1 diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c index 5816d96..c6b731c 100644 --- a/source4/scripting/python/pyglue.c +++ b/source4/scripting/python/pyglue.c @@ -204,6 +204,63 @@ static PyObject *py_dsdb_set_ntds_invocation_id(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args) +{ + PyObject *py_ldb; + int value; + int *old_val, *new_val; + char *py_opaque_name, *opaque_name_talloc; + struct ldb_context *ldb; + TALLOC_CTX *tmp_ctx; + + if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value)) + return NULL; + + PyErr_LDB_OR_RAISE(py_ldb, ldb); + + /* see if we have a cached copy */ + old_val = (int *)ldb_get_opaque(ldb, + py_opaque_name); + + if (old_val) { + *old_val = value; + Py_RETURN_NONE; + } + + tmp_ctx = talloc_new(ldb); + if (tmp_ctx == NULL) { + goto failed; + } + + new_val = talloc(tmp_ctx, int); + if (!new_val) { + goto failed; + } + + opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name); + if (!opaque_name_talloc) { + goto failed; + } + + *new_val = value; + + /* cache the domain_sid in the ldb */ + if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) { + goto failed; + } + + talloc_steal(ldb, new_val); + talloc_steal(ldb, opaque_name_talloc); + talloc_free(tmp_ctx); + + Py_RETURN_NONE; + +failed: + talloc_free(tmp_ctx); + PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n"); + return NULL; +} + static PyObject *py_dsdb_set_global_schema(PyObject *self, PyObject *args) { PyObject *py_ldb; @@ -284,6 +341,8 @@ static PyMethodDef py_misc_methods[] = { "Register Samba-specific LDB modules and schemas." }, { "dsdb_set_ntds_invocation_id", (PyCFunction)py_dsdb_set_ntds_invocation_id, METH_VARARGS, NULL }, + { "dsdb_set_opaque_integer", (PyCFunction)py_dsdb_set_opaque_integer, METH_VARARGS, + NULL }, -- Samba Shared Repository