From 538f62edb2cc4c17204620d8a9b3075c7453422b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 4 Sep 2014 12:55:53 +0200 Subject: [PATCH 002/249] selftest: Fix selftest where pid is used uninitialized. On my system this gets evaluated to 0 so in the end we detect samba to be running cause $childpid is set to 0. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10793 Signed-off-by: Andreas Schneider Reviewed-by: Stefan Metzmacher Autobuild-User(master): Andreas Schneider Autobuild-Date(master): Thu Sep 4 17:09:17 CEST 2014 on sn-devel-104 (cherry picked from commit 6d2f56dbaf84203b351f33179cc3feaf557e0683) Signed-off-by: Andreas Schneider Autobuild-User(v4-1-test): Karolin Seeger Autobuild-Date(v4-1-test): Mon Sep 8 23:19:29 CEST 2014 on sn-devel-104 --- selftest/target/Samba.pm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index ab3851f..b0817fd 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -188,7 +188,12 @@ sub get_interface($) sub cleanup_child($$) { my ($pid, $name) = @_; - my $childpid = waitpid($pid, WNOHANG); + my $childpid = -1; + + if (defined($pid)) { + $childpid = waitpid($pid, WNOHANG); + } + if ($childpid == 0) { } elsif ($childpid < 0) { printf STDERR "%s child process %d isn't here any more\n", -- 1.9.3 From a14c0878c232dcf674008444f80dc0e5d8aada09 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 12:33:25 +0200 Subject: [PATCH 003/249] auth/credentials: remove pointless talloc_reference() from cli_credentials_get_unparsed_name() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 953502925863377b5e566edff4ac68c63e8d151f) --- auth/credentials/credentials.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index e636123..e597809 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -669,7 +669,7 @@ _PUBLIC_ const char *cli_credentials_get_unparsed_name(struct cli_credentials *c const char *name; if (bind_dn) { - name = talloc_reference(mem_ctx, bind_dn); + name = talloc_strdup(mem_ctx, bind_dn); } else { cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain); if (domain && domain[0]) { -- 1.9.3 From a9bbf2e55d56b9d2cec944ee32a127fc72e6ce6a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 12:33:25 +0200 Subject: [PATCH 004/249] auth/credentials: remove pointless talloc_reference() from cli_credentials_get_principal_and_obtained() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit b8f09226458dc13cf901f481ede89d8a6bb94ba7) --- auth/credentials/credentials.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index e597809..7a4b081 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -267,7 +267,7 @@ _PUBLIC_ const char *cli_credentials_get_principal_and_obtained(struct cli_crede } } *obtained = cred->principal_obtained; - return talloc_reference(mem_ctx, cred->principal); + return talloc_strdup(mem_ctx, cred->principal); } /** -- 1.9.3 From 5df785eba8389be9129984c6c5a1e59487685938 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 12:52:17 +0200 Subject: [PATCH 005/249] auth/credentials: add cli_credentials_[set_]callback_data* Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 6ff6778bdc60f1cd4d52cba83bd47d3398fe5a20) --- auth/credentials/credentials.c | 11 +++++++++++ auth/credentials/credentials.h | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index 7a4b081..e6a4710 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -114,6 +114,17 @@ _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) return cred; } +_PUBLIC_ void cli_credentials_set_callback_data(struct cli_credentials *cred, + void *callback_data) +{ + cred->priv_data = callback_data; +} + +_PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred) +{ + return cred->priv_data; +} + /** * Create a new anonymous credential * @param mem_ctx TALLOC_CTX parent for credentials structure diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index dbc014f..0f498ad 100644 --- a/auth/credentials/credentials.h +++ b/auth/credentials/credentials.h @@ -332,6 +332,14 @@ bool cli_credentials_set_realm_callback(struct cli_credentials *cred, bool cli_credentials_set_workstation_callback(struct cli_credentials *cred, const char *(*workstation_cb) (struct cli_credentials *)); +void cli_credentials_set_callback_data(struct cli_credentials *cred, + void *callback_data); +void *_cli_credentials_callback_data(struct cli_credentials *cred); +#define cli_credentials_callback_data(_cred, _type) \ + talloc_get_type_abort(_cli_credentials_callback_data(_cred), _type) +#define cli_credentials_callback_data_void(_cred) \ + _cli_credentials_callback_data(_cred) + /** * Return attached NETLOGON credentials */ -- 1.9.3 From 8fd0244ac8fe4998a0931bc9d51b9dfbb182a2e1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 13:21:14 +0200 Subject: [PATCH 006/249] auth/credentials: add cli_credentials_shallow_copy() This is useful for testing. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit b3cd44d50cff99fa77611679d68d2d57434fefa4) --- auth/credentials/credentials.c | 15 +++++++++++++++ auth/credentials/credentials.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index e6a4710..c1c6993 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -125,6 +125,21 @@ _PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred) return cred->priv_data; } +_PUBLIC_ struct cli_credentials *cli_credentials_shallow_copy(TALLOC_CTX *mem_ctx, + struct cli_credentials *src) +{ + struct cli_credentials *dst; + + dst = talloc(mem_ctx, struct cli_credentials); + if (dst == NULL) { + return NULL; + } + + *dst = *src; + + return dst; +} + /** * Create a new anonymous credential * @param mem_ctx TALLOC_CTX parent for credentials structure diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index 0f498ad..1377bfa 100644 --- a/auth/credentials/credentials.h +++ b/auth/credentials/credentials.h @@ -340,6 +340,9 @@ void *_cli_credentials_callback_data(struct cli_credentials *cred); #define cli_credentials_callback_data_void(_cred) \ _cli_credentials_callback_data(_cred) +struct cli_credentials *cli_credentials_shallow_copy(TALLOC_CTX *mem_ctx, + struct cli_credentials *src); + /** * Return attached NETLOGON credentials */ -- 1.9.3 From 52e4028da5db90ce3ee410997ea3464374fec46b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 13:20:13 +0200 Subject: [PATCH 007/249] s3:ntlm_auth: remove pointless credentials->priv_data = NULL; Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit cfeeb3ce3de5d1df07299fb83327ae258da0bf8d) --- source3/utils/ntlm_auth.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index b3bbaa4..a5e0cd2 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -228,7 +228,6 @@ static const char *get_password(struct cli_credentials *credentials) /* Ask for a password */ x_fprintf(x_stdout, "PW\n"); - credentials->priv_data = NULL; manage_squid_request(NUM_HELPER_MODES /* bogus */, NULL, NULL, manage_gensec_get_pw_request, (void **)&password); talloc_steal(credentials, password); -- 1.9.3 From bdfb13b91ce8961caeb98b01a75893895e8d484a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 13:22:10 +0200 Subject: [PATCH 008/249] s4:torture/shell: simplify cli_credentials_set_password() call All we want is to avoid a possible callback... Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 36b3c9506c1ac5549a38140e7ffd57644290069f) --- source4/torture/shell.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source4/torture/shell.c b/source4/torture/shell.c index d6cc94c..aa85da3 100644 --- a/source4/torture/shell.c +++ b/source4/torture/shell.c @@ -110,10 +110,7 @@ void torture_shell(struct torture_context *tctx) * stops the credentials system prompting when we use the "auth" * command to display the current auth parameters. */ - if (cmdline_credentials->password_obtained != CRED_SPECIFIED) { - cli_credentials_set_password(cmdline_credentials, "", - CRED_SPECIFIED); - } + cli_credentials_set_password(cmdline_credentials, "", CRED_GUESS_ENV); while (1) { cline = smb_readline("torture> ", NULL, NULL); -- 1.9.3 From 91c0d6a26823f3057357c6b31bf1f686e5ed0f5e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 13:23:08 +0200 Subject: [PATCH 009/249] s4:torture/gentest: make use of cli_credentials_get_username() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit d36fcaa5f3c4d1ad54d767f4a7c5fa6c8d69c00e) --- source4/torture/gentest.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c index 91b60e2..586a25b 100644 --- a/source4/torture/gentest.c +++ b/source4/torture/gentest.c @@ -221,7 +221,8 @@ static bool connect_servers(struct tevent_context *ev, printf("Connecting to \\\\%s\\%s as %s - instance %d\n", servers[i].server_name, servers[i].share_name, - servers[i].credentials->username, j); + cli_credentials_get_username(servers[i].credentials), + j); cli_credentials_set_workstation(servers[i].credentials, "gentest", CRED_SPECIFIED); -- 1.9.3 From 9687534ac54b732f73c3f4758055a278eaa0cbb2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 13:23:41 +0200 Subject: [PATCH 010/249] s4:torture/rpc: make use of cli_credentials_set_netlogon_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit d47bf469b8a9064f4f7033918b1fe519adfa0c26) --- source4/torture/rpc/schannel.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index e0862d2..8203749 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -604,9 +604,9 @@ bool torture_rpc_schannel2(struct torture_context *torture) torture_assert(torture, join_ctx != NULL, "Failed to join domain with acct_flags=ACB_WSTRUST"); - credentials2 = (struct cli_credentials *)talloc_memdup(torture, credentials1, sizeof(*credentials1)); - credentials1->netlogon_creds = NULL; - credentials2->netlogon_creds = NULL; + credentials2 = cli_credentials_shallow_copy(torture, credentials1); + cli_credentials_set_netlogon_creds(credentials1, NULL); + cli_credentials_set_netlogon_creds(credentials2, NULL); status = dcerpc_parse_binding(torture, binding, &b); torture_assert_ntstatus_ok(torture, status, "Bad binding string"); @@ -624,8 +624,8 @@ bool torture_rpc_schannel2(struct torture_context *torture) credentials2, torture->ev, torture->lp_ctx); torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel"); - credentials1->netlogon_creds = NULL; - credentials2->netlogon_creds = NULL; + cli_credentials_set_netlogon_creds(credentials1, NULL); + cli_credentials_set_netlogon_creds(credentials2, NULL); torture_comment(torture, "Testing logon on pipe1\n"); if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL)) @@ -827,16 +827,12 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) s->nprocs = torture_setting_int(torture, "nprocs", 4); s->conns = talloc_zero_array(s, struct torture_schannel_bench_conn, s->nprocs); - s->user1_creds = (struct cli_credentials *)talloc_memdup(s, - cmdline_credentials, - sizeof(*s->user1_creds)); + s->user1_creds = cli_credentials_shallow_copy(s, cmdline_credentials); tmp = torture_setting_string(s->tctx, "extra_user1", NULL); if (tmp) { cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED); } - s->user2_creds = (struct cli_credentials *)talloc_memdup(s, - cmdline_credentials, - sizeof(*s->user1_creds)); + s->user2_creds = cli_credentials_shallow_copy(s, cmdline_credentials); tmp = torture_setting_string(s->tctx, "extra_user2", NULL); if (tmp) { cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED); @@ -855,15 +851,16 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) cli_credentials_set_kerberos_state(s->wks_creds2, CRED_DONT_USE_KERBEROS); for (i=0; i < s->nprocs; i++) { - s->conns[i].s = s; - s->conns[i].index = i; - s->conns[i].wks_creds = (struct cli_credentials *)talloc_memdup( - s->conns, s->wks_creds1,sizeof(*s->wks_creds1)); + struct cli_credentials *wks = s->wks_creds1; + if ((i % 2) && (torture_setting_bool(torture, "multijoin", false))) { - memcpy(s->conns[i].wks_creds, s->wks_creds2, - talloc_get_size(s->conns[i].wks_creds)); + wks = s->wks_creds2; } - s->conns[i].wks_creds->netlogon_creds = NULL; + + s->conns[i].s = s; + s->conns[i].index = i; + s->conns[i].wks_creds = cli_credentials_shallow_copy(s->conns, wks); + cli_credentials_set_netlogon_creds(s->conns[i].wks_creds, NULL); } status = dcerpc_parse_binding(s, binding, &s->b); @@ -962,8 +959,7 @@ bool torture_rpc_schannel_bench1(struct torture_context *torture) /* Just as a test, connect with the new creds */ - talloc_free(s->wks_creds1->netlogon_creds); - s->wks_creds1->netlogon_creds = NULL; + cli_credentials_set_netlogon_creds(s->wks_creds1, NULL); status = dcerpc_pipe_connect_b(s, &net_pipe, s->b, &ndr_table_netlogon, -- 1.9.3 From de6c67e98d94d003f36fef5472b8133c578b3c01 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 13:24:21 +0200 Subject: [PATCH 011/249] s4:ntlm_auth: make use of cli_credentials_[set_]callback_data* Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit bbd63dd8a17468d3e332969a30c06e2b2f1540fc) --- source4/utils/ntlm_auth.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index c363c9d..136e238 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -299,10 +299,11 @@ static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mod static const char *get_password(struct cli_credentials *credentials) { char *password = NULL; - + void *cb = cli_credentials_callback_data_void(credentials); + /* Ask for a password */ - mux_printf((unsigned int)(uintptr_t)credentials->priv_data, "PW\n"); - credentials->priv_data = NULL; + mux_printf((unsigned int)(uintptr_t)cb, "PW\n"); + cli_credentials_set_callback_data(credentials, NULL); manage_squid_request(cmdline_lp_ctx, NUM_HELPER_MODES /* bogus */, manage_gensec_get_pw_request, (void **)&password); return password; @@ -505,8 +506,9 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, if (state->set_password) { cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED); } else { + void *cb = (void*)(uintptr_t)mux_id; + cli_credentials_set_callback_data(creds, cb); cli_credentials_set_password_callback(creds, get_password); - creds->priv_data = (void*)(uintptr_t)mux_id; } if (opt_workstation) { cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED); -- 1.9.3 From 80c611a2b424e4e4a7e6de7ed6b9368bff0d9afb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 12:41:40 +0200 Subject: [PATCH 012/249] auth/credentials: keep cli_credentials private Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 9325bd9cb6bb942ea989f4e32799c76ea8af3d3e) --- auth/credentials/credentials.c | 1 + auth/credentials/credentials.h | 101 +++------------------------- auth/credentials/credentials_internal.h | 114 ++++++++++++++++++++++++++++++++ auth/credentials/credentials_krb5.c | 1 + auth/credentials/credentials_ntlm.c | 1 + auth/credentials/credentials_secrets.c | 1 + 6 files changed, 126 insertions(+), 93 deletions(-) create mode 100644 auth/credentials/credentials_internal.h diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index c1c6993..f334465 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -24,6 +24,7 @@ #include "includes.h" #include "librpc/gen_ndr/samr.h" /* for struct samrPassword */ #include "auth/credentials/credentials.h" +#include "auth/credentials/credentials_internal.h" #include "libcli/auth/libcli_auth.h" #include "tevent.h" #include "param/param.h" diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index 1377bfa..cb09dc3 100644 --- a/auth/credentials/credentials.h +++ b/auth/credentials/credentials.h @@ -25,9 +25,17 @@ #include "../lib/util/data_blob.h" #include "librpc/gen_ndr/misc.h" +struct cli_credentials; struct ccache_container; struct tevent_context; struct netlogon_creds_CredentialState; +struct ldb_context; +struct ldb_message; +struct loadparm_context; +struct ccache_container; +struct gssapi_creds_container; +struct smb_krb5_context; +struct keytab_container; /* In order of priority */ enum credentials_obtained { @@ -57,99 +65,6 @@ enum credentials_krb_forwardable { #define CLI_CRED_NTLM_AUTH 0x08 #define CLI_CRED_CLEAR_AUTH 0x10 /* TODO: Push cleartext auth with this flag */ -struct cli_credentials { - enum credentials_obtained workstation_obtained; - enum credentials_obtained username_obtained; - enum credentials_obtained password_obtained; - enum credentials_obtained domain_obtained; - enum credentials_obtained realm_obtained; - enum credentials_obtained ccache_obtained; - enum credentials_obtained client_gss_creds_obtained; - enum credentials_obtained principal_obtained; - enum credentials_obtained keytab_obtained; - enum credentials_obtained server_gss_creds_obtained; - - /* Threshold values (essentially a MAX() over a number of the - * above) for the ccache and GSS credentials, to ensure we - * regenerate/pick correctly */ - - enum credentials_obtained ccache_threshold; - enum credentials_obtained client_gss_creds_threshold; - - const char *workstation; - const char *username; - const char *password; - const char *old_password; - const char *domain; - const char *realm; - const char *principal; - char *salt_principal; - char *impersonate_principal; - char *self_service; - char *target_service; - - const char *bind_dn; - - /* Allows authentication from a keytab or similar */ - struct samr_Password *nt_hash; - - /* Allows NTLM pass-though authentication */ - DATA_BLOB lm_response; - DATA_BLOB nt_response; - - struct ccache_container *ccache; - struct gssapi_creds_container *client_gss_creds; - struct keytab_container *keytab; - struct gssapi_creds_container *server_gss_creds; - - const char *(*workstation_cb) (struct cli_credentials *); - const char *(*password_cb) (struct cli_credentials *); - const char *(*username_cb) (struct cli_credentials *); - const char *(*domain_cb) (struct cli_credentials *); - const char *(*realm_cb) (struct cli_credentials *); - const char *(*principal_cb) (struct cli_credentials *); - - /* Private handle for the callback routines to use */ - void *priv_data; - - struct netlogon_creds_CredentialState *netlogon_creds; - enum netr_SchannelType secure_channel_type; - int kvno; - time_t password_last_changed_time; - - struct smb_krb5_context *smb_krb5_context; - - /* We are flagged to get machine account details from the - * secrets.ldb when we are asked for a username or password */ - bool machine_account_pending; - struct loadparm_context *machine_account_pending_lp_ctx; - - /* Is this a machine account? */ - bool machine_account; - - /* Should we be trying to use kerberos? */ - enum credentials_use_kerberos use_kerberos; - - /* Should we get a forwardable ticket? */ - enum credentials_krb_forwardable krb_forwardable; - - /* gensec features which should be used for connections */ - uint32_t gensec_features; - - /* Number of retries left before bailing out */ - int tries; - - /* Whether any callback is currently running */ - bool callback_running; -}; - -struct ldb_context; -struct ldb_message; -struct loadparm_context; -struct ccache_container; - -struct gssapi_creds_container; - const char *cli_credentials_get_workstation(struct cli_credentials *cred); bool cli_credentials_set_workstation(struct cli_credentials *cred, const char *val, diff --git a/auth/credentials/credentials_internal.h b/auth/credentials/credentials_internal.h new file mode 100644 index 0000000..5a3655b --- /dev/null +++ b/auth/credentials/credentials_internal.h @@ -0,0 +1,114 @@ +/* + samba -- Unix SMB/CIFS implementation. + + Client credentials structure + + Copyright (C) Jelmer Vernooij 2004-2006 + 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 + (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 . +*/ +#ifndef __CREDENTIALS_INTERNAL_H__ +#define __CREDENTIALS_INTERNAL_H__ + +#include "../lib/util/data_blob.h" +#include "librpc/gen_ndr/misc.h" + +struct cli_credentials { + enum credentials_obtained workstation_obtained; + enum credentials_obtained username_obtained; + enum credentials_obtained password_obtained; + enum credentials_obtained domain_obtained; + enum credentials_obtained realm_obtained; + enum credentials_obtained ccache_obtained; + enum credentials_obtained client_gss_creds_obtained; + enum credentials_obtained principal_obtained; + enum credentials_obtained keytab_obtained; + enum credentials_obtained server_gss_creds_obtained; + + /* Threshold values (essentially a MAX() over a number of the + * above) for the ccache and GSS credentials, to ensure we + * regenerate/pick correctly */ + + enum credentials_obtained ccache_threshold; + enum credentials_obtained client_gss_creds_threshold; + + const char *workstation; + const char *username; + const char *password; + const char *old_password; + const char *domain; + const char *realm; + const char *principal; + char *salt_principal; + char *impersonate_principal; + char *self_service; + char *target_service; + + const char *bind_dn; + + /* Allows authentication from a keytab or similar */ + struct samr_Password *nt_hash; + + /* Allows NTLM pass-though authentication */ + DATA_BLOB lm_response; + DATA_BLOB nt_response; + + struct ccache_container *ccache; + struct gssapi_creds_container *client_gss_creds; + struct keytab_container *keytab; + struct gssapi_creds_container *server_gss_creds; + + const char *(*workstation_cb) (struct cli_credentials *); + const char *(*password_cb) (struct cli_credentials *); + const char *(*username_cb) (struct cli_credentials *); + const char *(*domain_cb) (struct cli_credentials *); + const char *(*realm_cb) (struct cli_credentials *); + const char *(*principal_cb) (struct cli_credentials *); + + /* Private handle for the callback routines to use */ + void *priv_data; + + struct netlogon_creds_CredentialState *netlogon_creds; + enum netr_SchannelType secure_channel_type; + int kvno; + time_t password_last_changed_time; + + struct smb_krb5_context *smb_krb5_context; + + /* We are flagged to get machine account details from the + * secrets.ldb when we are asked for a username or password */ + bool machine_account_pending; + struct loadparm_context *machine_account_pending_lp_ctx; + + /* Is this a machine account? */ + bool machine_account; + + /* Should we be trying to use kerberos? */ + enum credentials_use_kerberos use_kerberos; + + /* Should we get a forwardable ticket? */ + enum credentials_krb_forwardable krb_forwardable; + + /* gensec features which should be used for connections */ + uint32_t gensec_features; + + /* Number of retries left before bailing out */ + int tries; + + /* Whether any callback is currently running */ + bool callback_running; +}; + +#endif /* __CREDENTIALS_INTERNAL_H__ */ diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index ec6a695..489a959 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -26,6 +26,7 @@ #include "system/gssapi.h" #include "auth/kerberos/kerberos.h" #include "auth/credentials/credentials.h" +#include "auth/credentials/credentials_internal.h" #include "auth/credentials/credentials_proto.h" #include "auth/credentials/credentials_krb5.h" #include "auth/kerberos/kerberos_credentials.h" diff --git a/auth/credentials/credentials_ntlm.c b/auth/credentials/credentials_ntlm.c index 8f143bf..8c6be39 100644 --- a/auth/credentials/credentials_ntlm.c +++ b/auth/credentials/credentials_ntlm.c @@ -26,6 +26,7 @@ #include "../lib/crypto/crypto.h" #include "libcli/auth/libcli_auth.h" #include "auth/credentials/credentials.h" +#include "auth/credentials/credentials_internal.h" _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, int *flags, diff --git a/auth/credentials/credentials_secrets.c b/auth/credentials/credentials_secrets.c index 27ee607..678d167 100644 --- a/auth/credentials/credentials_secrets.c +++ b/auth/credentials/credentials_secrets.c @@ -28,6 +28,7 @@ #include "param/secrets.h" #include "system/filesys.h" #include "auth/credentials/credentials.h" +#include "auth/credentials/credentials_internal.h" #include "auth/credentials/credentials_proto.h" #include "auth/credentials/credentials_krb5.h" #include "auth/kerberos/kerberos_util.h" -- 1.9.3 From 96ea01159cfee1e384dbd5966c7eb512d495e322 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 13:39:17 +0200 Subject: [PATCH 013/249] auth/credentials: get the old password from secrets.tdb Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 26a7420c1c4307023b22676cd85d95010ecbf603) --- auth/credentials/credentials_secrets.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/auth/credentials/credentials_secrets.c b/auth/credentials/credentials_secrets.c index 678d167..6c1cded 100644 --- a/auth/credentials/credentials_secrets.c +++ b/auth/credentials/credentials_secrets.c @@ -238,6 +238,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr bool secrets_tdb_password_more_recent; time_t secrets_tdb_lct = 0; char *secrets_tdb_password = NULL; + char *secrets_tdb_old_password = NULL; char *keystr; char *keystr_upper = NULL; char *secrets_tdb; @@ -285,6 +286,15 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr if (NT_STATUS_IS_OK(status)) { secrets_tdb_password = (char *)dbuf.dptr; } + keystr = talloc_asprintf(tmp_ctx, "%s/%s", + SECRETS_MACHINE_PASSWORD_PREV, + domain); + keystr_upper = strupper_talloc(tmp_ctx, keystr); + status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), + &dbuf); + if (NT_STATUS_IS_OK(status)) { + secrets_tdb_old_password = (char *)dbuf.dptr; + } } filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, @@ -308,6 +318,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr if (secrets_tdb_password_more_recent) { char *machine_account = talloc_asprintf(tmp_ctx, "%s$", lpcfg_netbios_name(lp_ctx)); cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED); + cli_credentials_set_old_password(cred, secrets_tdb_old_password, CRED_SPECIFIED); cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); } else if (!NT_STATUS_IS_OK(status)) { -- 1.9.3 From 74f5c14921f53b95b64dbcbf0352a89d50b20af1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 14:25:54 +0200 Subject: [PATCH 014/249] auth/credentials: simplify password_tries state Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 8ea36a8e58d499aa7bf342b365ca00cb39f295b6) --- auth/credentials/credentials.c | 19 ++++++++++++++----- auth/credentials/credentials_internal.h | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index f334465..4ac5356 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -104,7 +104,7 @@ _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx) cred->machine_account = false; - cred->tries = 3; + cred->password_tries = 0; cred->callback_running = false; @@ -397,6 +397,7 @@ _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred, enum credentials_obtained obtained) { if (obtained >= cred->password_obtained) { + cred->password_tries = 0; cred->password = talloc_strdup(cred, val); if (cred->password) { /* Don't print the actual password in talloc memory dumps */ @@ -418,6 +419,7 @@ _PUBLIC_ bool cli_credentials_set_password_callback(struct cli_credentials *cred const char *(*password_cb) (struct cli_credentials *)) { if (cred->password_obtained < CRED_CALLBACK) { + cred->password_tries = 3; cred->password_cb = password_cb; cred->password_obtained = CRED_CALLBACK; cli_credentials_invalidate_ccache(cred, cred->password_obtained); @@ -897,12 +899,19 @@ _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred) if (cred->password_obtained != CRED_CALLBACK_RESULT) { return false; } - - cred->password_obtained = CRED_CALLBACK; - cred->tries--; + if (cred->password_tries == 0) { + return false; + } + + cred->password_tries--; - return (cred->tries > 0); + if (cred->password_tries == 0) { + return false; + } + + cred->password_obtained = CRED_CALLBACK; + return true; } _PUBLIC_ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, diff --git a/auth/credentials/credentials_internal.h b/auth/credentials/credentials_internal.h index 5a3655b..f2f79b9 100644 --- a/auth/credentials/credentials_internal.h +++ b/auth/credentials/credentials_internal.h @@ -105,7 +105,7 @@ struct cli_credentials { uint32_t gensec_features; /* Number of retries left before bailing out */ - int tries; + uint32_t password_tries; /* Whether any callback is currently running */ bool callback_running; -- 1.9.3 From 8d2c51caeecebc0b7d16fb7cf7b7fe2f2b5d8edd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 31 Jul 2013 14:32:36 +0200 Subject: [PATCH 015/249] auth/credentials: use CRED_CALLBACK_RESULT after a callback We only do this if it's still CRED_CALLBACK after the callback, this allowes the callback to overwrite it. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Mon Aug 5 09:36:05 CEST 2013 on sn-devel-104 (cherry picked from commit b699d404bb5d4385a757b5aa5d0e792cf9d5de59) --- auth/credentials/credentials.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index 4ac5356..be497bc 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -206,8 +206,10 @@ _PUBLIC_ const char *cli_credentials_get_username(struct cli_credentials *cred) cred->callback_running = true; cred->username = cred->username_cb(cred); cred->callback_running = false; - cred->username_obtained = CRED_SPECIFIED; - cli_credentials_invalidate_ccache(cred, cred->username_obtained); + if (cred->username_obtained == CRED_CALLBACK) { + cred->username_obtained = CRED_CALLBACK_RESULT; + cli_credentials_invalidate_ccache(cred, cred->username_obtained); + } } return cred->username; @@ -275,8 +277,10 @@ _PUBLIC_ const char *cli_credentials_get_principal_and_obtained(struct cli_crede cred->callback_running = true; cred->principal = cred->principal_cb(cred); cred->callback_running = false; - cred->principal_obtained = CRED_SPECIFIED; - cli_credentials_invalidate_ccache(cred, cred->principal_obtained); + if (cred->principal_obtained == CRED_CALLBACK) { + cred->principal_obtained = CRED_CALLBACK_RESULT; + cli_credentials_invalidate_ccache(cred, cred->principal_obtained); + } } if (cred->principal_obtained < cred->username_obtained @@ -382,8 +386,10 @@ _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred) cred->callback_running = true; cred->password = cred->password_cb(cred); cred->callback_running = false; - cred->password_obtained = CRED_CALLBACK_RESULT; - cli_credentials_invalidate_ccache(cred, cred->password_obtained); + if (cred->password_obtained == CRED_CALLBACK) { + cred->password_obtained = CRED_CALLBACK_RESULT; + cli_credentials_invalidate_ccache(cred, cred->password_obtained); + } } return cred->password; @@ -502,8 +508,10 @@ _PUBLIC_ const char *cli_credentials_get_domain(struct cli_credentials *cred) cred->callback_running = true; cred->domain = cred->domain_cb(cred); cred->callback_running = false; - cred->domain_obtained = CRED_SPECIFIED; - cli_credentials_invalidate_ccache(cred, cred->domain_obtained); + if (cred->domain_obtained == CRED_CALLBACK) { + cred->domain_obtained = CRED_CALLBACK_RESULT; + cli_credentials_invalidate_ccache(cred, cred->domain_obtained); + } } return cred->domain; @@ -561,8 +569,10 @@ _PUBLIC_ const char *cli_credentials_get_realm(struct cli_credentials *cred) cred->callback_running = true; cred->realm = cred->realm_cb(cred); cred->callback_running = false; - cred->realm_obtained = CRED_SPECIFIED; - cli_credentials_invalidate_ccache(cred, cred->realm_obtained); + if (cred->realm_obtained == CRED_CALLBACK) { + cred->realm_obtained = CRED_CALLBACK_RESULT; + cli_credentials_invalidate_ccache(cred, cred->realm_obtained); + } } return cred->realm; @@ -612,7 +622,9 @@ _PUBLIC_ const char *cli_credentials_get_workstation(struct cli_credentials *cre cred->callback_running = true; cred->workstation = cred->workstation_cb(cred); cred->callback_running = false; - cred->workstation_obtained = CRED_SPECIFIED; + if (cred->workstation_obtained == CRED_CALLBACK) { + cred->workstation_obtained = CRED_CALLBACK_RESULT; + } } return cred->workstation; -- 1.9.3 From a498324b38326a874616b0bab1e5a9cd29b664ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 17 May 2013 16:02:59 +0200 Subject: [PATCH 016/249] s3-net: pass down ndr_interface_table to connect_dst_pipe(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 93e92faca9c99cd91878c2f48fb244233b16aa0f) --- source3/utils/net_proto.h | 2 +- source3/utils/net_rpc.c | 4 ++-- source3/utils/net_rpc_printer.c | 10 +++++----- source3/utils/net_util.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index 3f99e14..03fb312 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -416,7 +416,7 @@ NTSTATUS connect_to_ipc_anonymous(struct net_context *c, const char *server_name); NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, - const struct ndr_syntax_id *interface); + const struct ndr_interface_table *table); int net_use_krb_machine_account(struct net_context *c); int net_use_machine_account(struct net_context *c); bool net_find_server(struct net_context *c, diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index c5c4d6c..4503f59 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -3654,7 +3654,7 @@ static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c, /* connect destination PI_SRVSVC */ nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe, - &ndr_table_srvsvc.syntax_id); + &ndr_table_srvsvc); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; @@ -4140,7 +4140,7 @@ static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c, /* connect destination PI_SRVSVC */ nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe, - &ndr_table_srvsvc.syntax_id); + &ndr_table_srvsvc); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; diff --git a/source3/utils/net_rpc_printer.c b/source3/utils/net_rpc_printer.c index ba34de1..1e42e6f 100644 --- a/source3/utils/net_rpc_printer.c +++ b/source3/utils/net_rpc_printer.c @@ -1578,7 +1578,7 @@ NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c, /* connect destination PI_SPOOLSS */ nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, - &ndr_table_spoolss.syntax_id); + &ndr_table_spoolss); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } @@ -1730,7 +1730,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c, /* connect destination PI_SPOOLSS */ nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, - &ndr_table_spoolss.syntax_id); + &ndr_table_spoolss); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } @@ -1907,7 +1907,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c, DEBUG(3,("copying printer-drivers\n")); nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, - &ndr_table_spoolss.syntax_id); + &ndr_table_spoolss); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } @@ -2126,7 +2126,7 @@ NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c, /* connect destination PI_SPOOLSS */ nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, - &ndr_table_spoolss.syntax_id); + &ndr_table_spoolss); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } @@ -2301,7 +2301,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c, /* connect destination PI_SPOOLSS */ nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst, - &ndr_table_spoolss.syntax_id); + &ndr_table_spoolss); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c index 9c4a77e..a4282ec 100644 --- a/source3/utils/net_util.c +++ b/source3/utils/net_util.c @@ -231,7 +231,7 @@ NTSTATUS connect_to_ipc_anonymous(struct net_context *c, **/ NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, - const struct ndr_syntax_id *interface) + const struct ndr_interface_table *table) { NTSTATUS nt_status; char *server_name = SMB_STRDUP("127.0.0.1"); @@ -256,7 +256,7 @@ NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, return nt_status; } - nt_status = cli_rpc_pipe_open_noauth(cli_tmp, interface, + nt_status = cli_rpc_pipe_open_noauth(cli_tmp, &table->syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("couldn't not initialize pipe\n")); -- 1.9.3 From d5273069a42d7234daaf3dd043d0a6e455348385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 17 May 2013 16:24:42 +0200 Subject: [PATCH 017/249] s3-rpc_cli: remove prototype of nonexisting cli_rpc_pipe_open_krb5(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit a1368ca6ef8ab4f158c8b303ad058835f1bbf441) --- source3/rpc_client/cli_pipe.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index bf785fb..34ae542 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -131,15 +131,6 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, const char *domain, struct rpc_pipe_client **presult); -NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli, - const struct ndr_syntax_id *interface, - enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, - const char *service_princ, - const char *username, - const char *password, - struct rpc_pipe_client **presult); - NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, DATA_BLOB *session_key); -- 1.9.3 From 1a6c1ddb44aac3f201bbe2cabab10e409ffd042b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 17 May 2013 16:08:16 +0200 Subject: [PATCH 018/249] s3-libnetapi: pass down ndr_interface_table to libnetapi_get_binding_handle(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit fa37bbd9d06865d265bf554a3c49920f956f2185) --- source3/lib/netapi/cm.c | 4 ++-- source3/lib/netapi/file.c | 6 +++--- source3/lib/netapi/getdc.c | 6 +++--- source3/lib/netapi/netapi_private.h | 3 ++- source3/lib/netapi/netlogon.c | 4 ++-- source3/lib/netapi/serverinfo.c | 6 +++--- source3/lib/netapi/share.c | 10 +++++----- source3/lib/netapi/shutdown.c | 4 ++-- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index da3d2e1..c3ae19f 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -269,7 +269,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, const char *server_name, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct dcerpc_binding_handle **binding_handle) { struct rpc_pipe_client *pipe_cli; @@ -277,7 +277,7 @@ WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, *binding_handle = NULL; - result = libnetapi_open_pipe(ctx, server_name, interface, &pipe_cli); + result = libnetapi_open_pipe(ctx, server_name, &table->syntax_id, &pipe_cli); if (!W_ERROR_IS_OK(result)) { return result; } diff --git a/source3/lib/netapi/file.c b/source3/lib/netapi/file.c index 1e406d2..551f9ff 100644 --- a/source3/lib/netapi/file.c +++ b/source3/lib/netapi/file.c @@ -36,7 +36,7 @@ WERROR NetFileClose_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -130,7 +130,7 @@ WERROR NetFileGetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -201,7 +201,7 @@ WERROR NetFileEnum_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/getdc.c b/source3/lib/netapi/getdc.c index 3b26d46..ae976f1 100644 --- a/source3/lib/netapi/getdc.c +++ b/source3/lib/netapi/getdc.c @@ -47,7 +47,7 @@ WERROR NetGetDCName_r(struct libnetapi_ctx *ctx, void *buffer; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_netlogon.syntax_id, + &ndr_table_netlogon, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -101,7 +101,7 @@ WERROR NetGetAnyDCName_r(struct libnetapi_ctx *ctx, void *buffer; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_netlogon.syntax_id, + &ndr_table_netlogon, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -173,7 +173,7 @@ WERROR DsGetDcName_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_netlogon.syntax_id, + &ndr_table_netlogon, &b); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/netapi_private.h b/source3/lib/netapi/netapi_private.h index 349287b..62aa7ef 100644 --- a/source3/lib/netapi/netapi_private.h +++ b/source3/lib/netapi/netapi_private.h @@ -30,6 +30,7 @@ return fn ## _r(ctx, r); struct dcerpc_binding_handle; +struct ndr_interface_table; struct libnetapi_private_ctx { struct { @@ -64,7 +65,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, struct rpc_pipe_client **presult); WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, const char *server_name, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct dcerpc_binding_handle **binding_handle); WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx, struct rpc_pipe_client *pipe_cli, diff --git a/source3/lib/netapi/netlogon.c b/source3/lib/netapi/netlogon.c index a046fb7..136cb48 100644 --- a/source3/lib/netapi/netlogon.c +++ b/source3/lib/netapi/netlogon.c @@ -133,7 +133,7 @@ WERROR I_NetLogonControl_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_netlogon.syntax_id, + &ndr_table_netlogon, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -190,7 +190,7 @@ WERROR I_NetLogonControl2_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_netlogon.syntax_id, + &ndr_table_netlogon, &b); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c index 046b693..b2a84d1 100644 --- a/source3/lib/netapi/serverinfo.c +++ b/source3/lib/netapi/serverinfo.c @@ -503,7 +503,7 @@ WERROR NetServerGetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -616,7 +616,7 @@ WERROR NetServerSetInfo_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -658,7 +658,7 @@ WERROR NetRemoteTOD_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/share.c b/source3/lib/netapi/share.c index d12fa1c..090e1a9 100644 --- a/source3/lib/netapi/share.c +++ b/source3/lib/netapi/share.c @@ -200,7 +200,7 @@ WERROR NetShareAdd_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -258,7 +258,7 @@ WERROR NetShareDel_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -321,7 +321,7 @@ WERROR NetShareEnum_r(struct libnetapi_ctx *ctx, ZERO_STRUCT(info_ctr); werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -428,7 +428,7 @@ WERROR NetShareGetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -502,7 +502,7 @@ WERROR NetShareSetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, &b); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/shutdown.c b/source3/lib/netapi/shutdown.c index 78bc2fc..9e1e8e1 100644 --- a/source3/lib/netapi/shutdown.c +++ b/source3/lib/netapi/shutdown.c @@ -38,7 +38,7 @@ WERROR NetShutdownInit_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_initshutdown.syntax_id, + &ndr_table_initshutdown, &b); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -82,7 +82,7 @@ WERROR NetShutdownAbort_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_get_binding_handle(ctx, r->in.server_name, - &ndr_table_initshutdown.syntax_id, + &ndr_table_initshutdown, &b); if (!W_ERROR_IS_OK(werr)) { goto done; -- 1.9.3 From e25e7bfe15bdb89a9680708c27b50e14a8a86ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 17 May 2013 16:10:13 +0200 Subject: [PATCH 019/249] s3-libnetapi: pass down ndr_interface_table to libnetapi_open_pipe(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 77f7f2a976e5b95f3bd9f542b92926adee4f5fa6) --- source3/lib/netapi/cm.c | 8 ++++---- source3/lib/netapi/group.c | 18 +++++++++--------- source3/lib/netapi/joindomain.c | 10 +++++----- source3/lib/netapi/localgroup.c | 14 +++++++------- source3/lib/netapi/netapi_private.h | 2 +- source3/lib/netapi/user.c | 22 +++++++++++----------- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index c3ae19f..dd1f1e3 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -234,7 +234,7 @@ static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx, WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, const char *server_name, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result = NULL; @@ -251,10 +251,10 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, return werr; } - status = pipe_cm_open(ctx, ipc, interface, &result); + status = pipe_cm_open(ctx, ipc, &table->syntax_id, &result); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", - get_pipe_name_from_syntax(talloc_tos(), interface), + get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), get_friendly_nt_error_msg(status)); return WERR_DEST_NOT_FOUND; } @@ -277,7 +277,7 @@ WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, *binding_handle = NULL; - result = libnetapi_open_pipe(ctx, server_name, &table->syntax_id, &pipe_cli); + result = libnetapi_open_pipe(ctx, server_name, table, &pipe_cli); if (!W_ERROR_IS_OK(result)) { return result; } diff --git a/source3/lib/netapi/group.c b/source3/lib/netapi/group.c index b806fc4..6d9b248 100644 --- a/source3/lib/netapi/group.c +++ b/source3/lib/netapi/group.c @@ -76,7 +76,7 @@ WERROR NetGroupAdd_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -272,7 +272,7 @@ WERROR NetGroupDel_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -492,7 +492,7 @@ WERROR NetGroupSetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -770,7 +770,7 @@ WERROR NetGroupGetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -918,7 +918,7 @@ WERROR NetGroupAddUser_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1078,7 +1078,7 @@ WERROR NetGroupDelUser_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1397,7 +1397,7 @@ WERROR NetGroupEnum_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1544,7 +1544,7 @@ WERROR NetGroupGetUsers_r(struct libnetapi_ctx *ctx, werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1736,7 +1736,7 @@ WERROR NetGroupSetUsers_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c index b6fb57a..d8e624f 100644 --- a/source3/lib/netapi/joindomain.c +++ b/source3/lib/netapi/joindomain.c @@ -116,7 +116,7 @@ WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx, DATA_BLOB session_key; werr = libnetapi_open_pipe(ctx, r->in.server, - &ndr_table_wkssvc.syntax_id, + &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -257,7 +257,7 @@ WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx, DATA_BLOB session_key; werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_wkssvc.syntax_id, + &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -313,7 +313,7 @@ WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx, struct dcerpc_binding_handle *b; werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_wkssvc.syntax_id, + &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -455,7 +455,7 @@ WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx, DATA_BLOB session_key; werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_wkssvc.syntax_id, + &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -508,7 +508,7 @@ WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx, DATA_BLOB session_key; werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_wkssvc.syntax_id, + &ndr_table_wkssvc, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/localgroup.c b/source3/lib/netapi/localgroup.c index 17cab68..241970d 100644 --- a/source3/lib/netapi/localgroup.c +++ b/source3/lib/netapi/localgroup.c @@ -185,7 +185,7 @@ WERROR NetLocalGroupAdd_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -319,7 +319,7 @@ WERROR NetLocalGroupDel_r(struct libnetapi_ctx *ctx, ZERO_STRUCT(alias_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -499,7 +499,7 @@ WERROR NetLocalGroupGetInfo_r(struct libnetapi_ctx *ctx, ZERO_STRUCT(alias_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -678,7 +678,7 @@ WERROR NetLocalGroupSetInfo_r(struct libnetapi_ctx *ctx, ZERO_STRUCT(alias_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -828,7 +828,7 @@ WERROR NetLocalGroupEnum_r(struct libnetapi_ctx *ctx, ZERO_STRUCT(alias_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1141,7 +1141,7 @@ static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx, if (r->in.level == 3) { werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, &lsa_pipe); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1160,7 +1160,7 @@ static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; diff --git a/source3/lib/netapi/netapi_private.h b/source3/lib/netapi/netapi_private.h index 62aa7ef..897cf3d 100644 --- a/source3/lib/netapi/netapi_private.h +++ b/source3/lib/netapi/netapi_private.h @@ -61,7 +61,7 @@ NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx, char **debugl WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx); WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, const char *server_name, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult); WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx, const char *server_name, diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c index a971e2d..4a39f69 100644 --- a/source3/lib/netapi/user.c +++ b/source3/lib/netapi/user.c @@ -400,7 +400,7 @@ WERROR NetUserAdd_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -552,7 +552,7 @@ WERROR NetUserDel_r(struct libnetapi_ctx *ctx, ZERO_STRUCT(user_handle); werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { @@ -1322,7 +1322,7 @@ WERROR NetUserEnum_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1630,7 +1630,7 @@ WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1764,7 +1764,7 @@ WERROR NetUserGetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -1936,7 +1936,7 @@ WERROR NetUserSetInfo_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -2395,7 +2395,7 @@ WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -2880,7 +2880,7 @@ WERROR NetUserModalsSet_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -3015,7 +3015,7 @@ WERROR NetUserGetGroups_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -3206,7 +3206,7 @@ WERROR NetUserSetGroups_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; @@ -3547,7 +3547,7 @@ WERROR NetUserGetLocalGroups_r(struct libnetapi_ctx *ctx, } werr = libnetapi_open_pipe(ctx, r->in.server_name, - &ndr_table_samr.syntax_id, + &ndr_table_samr, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; -- 1.9.3 From 4157ba43258373cd995b2ee74dcd4d65782dc2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 17 May 2013 16:13:26 +0200 Subject: [PATCH 020/249] s3-libnetapi: pass down ndr_interface_table to pipe_cm() and friends. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 0ce2178f2ffeaee324c7e8fef7c87727def7bd77) --- source3/lib/netapi/cm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index dd1f1e3..8551521 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -161,7 +161,7 @@ WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx) ********************************************************************/ static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct client_pipe_connection *p; @@ -177,7 +177,7 @@ static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, if (strequal(ipc_remote_name, p->pipe->desthost) && ndr_syntax_id_equal(&p->pipe->abstract_syntax, - interface)) { + &table->syntax_id)) { *presult = p->pipe; return NT_STATUS_OK; } @@ -191,7 +191,7 @@ static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc, static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, struct client_ipc_connection *ipc, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct client_pipe_connection *p; @@ -202,7 +202,7 @@ static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - status = cli_rpc_pipe_open_noauth(ipc->cli, interface, &p->pipe); + status = cli_rpc_pipe_open_noauth(ipc->cli, &table->syntax_id, &p->pipe); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(p); return status; @@ -219,14 +219,14 @@ static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx, struct client_ipc_connection *ipc, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { - if (NT_STATUS_IS_OK(pipe_cm_find(ipc, interface, presult))) { + if (NT_STATUS_IS_OK(pipe_cm_find(ipc, table, presult))) { return NT_STATUS_OK; } - return pipe_cm_connect(ctx, ipc, interface, presult); + return pipe_cm_connect(ctx, ipc, table, presult); } /******************************************************************** @@ -251,7 +251,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, return werr; } - status = pipe_cm_open(ctx, ipc, &table->syntax_id, &result); + status = pipe_cm_open(ctx, ipc, table, &result); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), -- 1.9.3 From ec8ba2a371ce4c4cc14d04e852034dcd92862542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 17 May 2013 16:16:59 +0200 Subject: [PATCH 021/249] s3-rpc_cli: pass down ndr_interface_table to rpc_pipe_open_ncalrpc(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 9b4fb5b074b035eaef98c4a463c9d68006ed52da) --- source3/librpc/rpc/dcerpc_ep.c | 2 +- source3/rpc_client/cli_pipe.c | 4 ++-- source3/rpc_client/cli_pipe.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/librpc/rpc/dcerpc_ep.c b/source3/librpc/rpc/dcerpc_ep.c index bb080c5..410caa7 100644 --- a/source3/librpc/rpc/dcerpc_ep.c +++ b/source3/librpc/rpc/dcerpc_ep.c @@ -365,7 +365,7 @@ static NTSTATUS ep_register(TALLOC_CTX *mem_ctx, status = rpc_pipe_open_ncalrpc(tmp_ctx, ncalrpc_sock, - &ndr_table_epmapper.syntax_id, + &ndr_table_epmapper, &cli); if (!NT_STATUS_IS_OK(status)) { goto done; diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 385ae25..427b628 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2682,7 +2682,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, Create a rpc pipe client struct, connecting to a unix domain socket ********************************************************************/ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result; @@ -2696,7 +2696,7 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, return NT_STATUS_NO_MEMORY; } - result->abstract_syntax = *abstract_syntax; + result->abstract_syntax = table->syntax_id; result->transfer_syntax = ndr_transfer_syntax_ndr; result->desthost = get_myname(result); diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 34ae542..3415db0 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -71,7 +71,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, struct rpc_pipe_client **presult); NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult); struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c); -- 1.9.3 From 816b7983c2342ea500e7467f2ab6c04dff89308f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 17 May 2013 16:44:05 +0200 Subject: [PATCH 022/249] s3-rpc_cli: pass down ndr_interface_table to rpc_pipe_open_interface(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 6886cff0a7e97864e9094af936cbef08a3c8f6f4) --- source3/printing/nt_printing_migrate_internal.c | 2 +- source3/printing/printspoolss.c | 4 +-- source3/rpc_server/rpc_ncacn_np.c | 8 +++--- source3/rpc_server/rpc_ncacn_np.h | 2 +- source3/smbd/lanman.c | 34 ++++++++++++------------- source3/smbd/reply.c | 2 +- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/source3/printing/nt_printing_migrate_internal.c b/source3/printing/nt_printing_migrate_internal.c index 200db07f..6bc7ea2 100644 --- a/source3/printing/nt_printing_migrate_internal.c +++ b/source3/printing/nt_printing_migrate_internal.c @@ -211,7 +211,7 @@ bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx) } status = rpc_pipe_open_interface(tmp_ctx, - &ndr_table_winreg.syntax_id, + &ndr_table_winreg, session_info, NULL, msg_ctx, diff --git a/source3/printing/printspoolss.c b/source3/printing/printspoolss.c index fc1e9c1..0507e83 100644 --- a/source3/printing/printspoolss.c +++ b/source3/printing/printspoolss.c @@ -154,7 +154,7 @@ NTSTATUS print_spool_open(files_struct *fsp, * a job id */ status = rpc_pipe_open_interface(fsp->conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, fsp->conn->session_info, fsp->conn->sconn->remote_address, fsp->conn->sconn->msg_ctx, @@ -343,7 +343,7 @@ void print_spool_terminate(struct connection_struct *conn, rap_jobid_delete(print_file->svcname, print_file->jobid); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c index b4602a9..7389b3e 100644 --- a/source3/rpc_server/rpc_ncacn_np.c +++ b/source3/rpc_server/rpc_ncacn_np.c @@ -758,7 +758,7 @@ done: */ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax, + const struct ndr_interface_table *table, const struct auth_session_info *session_info, const struct tsocket_address *remote_address, struct messaging_context *msg_ctx, @@ -783,7 +783,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - pipe_name = get_pipe_name_from_syntax(tmp_ctx, syntax); + pipe_name = get_pipe_name_from_syntax(tmp_ctx, &table->syntax_id); if (pipe_name == NULL) { status = NT_STATUS_INVALID_PARAMETER; goto done; @@ -800,7 +800,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, switch (pipe_mode) { case RPC_SERVICE_MODE_EMBEDDED: status = rpc_pipe_open_internal(tmp_ctx, - syntax, session_info, + &table->syntax_id, session_info, remote_address, msg_ctx, &cli); if (!NT_STATUS_IS_OK(status)) { @@ -813,7 +813,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, * to spoolssd. */ status = rpc_pipe_open_external(tmp_ctx, - pipe_name, syntax, + pipe_name, &table->syntax_id, session_info, &cli); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/rpc_server/rpc_ncacn_np.h b/source3/rpc_server/rpc_ncacn_np.h index 586d61b..67cd8a1 100644 --- a/source3/rpc_server/rpc_ncacn_np.h +++ b/source3/rpc_server/rpc_ncacn_np.h @@ -50,7 +50,7 @@ NTSTATUS rpcint_binding_handle(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx, struct dcerpc_binding_handle **binding_handle); NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax, + const struct ndr_interface_table *table, const struct auth_session_info *session_info, const struct tsocket_address *remote_address, struct messaging_context *msg_ctx, diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d0dae36..3c488ec 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -832,7 +832,7 @@ static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn, } status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -1029,7 +1029,7 @@ static bool api_DosPrintQEnum(struct smbd_server_connection *sconn, } status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -2256,7 +2256,7 @@ static bool api_RNetShareAdd(struct smbd_server_connection *sconn, return false; } - status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -2368,7 +2368,7 @@ static bool api_RNetGroupEnum(struct smbd_server_connection *sconn, } status = rpc_pipe_open_interface( - talloc_tos(), &ndr_table_samr.syntax_id, + talloc_tos(), &ndr_table_samr, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, &samr_pipe); if (!NT_STATUS_IS_OK(status)) { @@ -2574,7 +2574,7 @@ static bool api_NetUserGetGroups(struct smbd_server_connection *sconn, endp = *rdata + *rdata_len; status = rpc_pipe_open_interface( - talloc_tos(), &ndr_table_samr.syntax_id, + talloc_tos(), &ndr_table_samr, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, &samr_pipe); if (!NT_STATUS_IS_OK(status)) { @@ -2774,7 +2774,7 @@ static bool api_RNetUserEnum(struct smbd_server_connection *sconn, endp = *rdata + *rdata_len; status = rpc_pipe_open_interface( - talloc_tos(), &ndr_table_samr.syntax_id, + talloc_tos(), &ndr_table_samr, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, &samr_pipe); if (!NT_STATUS_IS_OK(status)) { @@ -3037,7 +3037,7 @@ static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn, memcpy(password.data, data, 516); memcpy(hash.hash, data+516, 16); - status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -3134,7 +3134,7 @@ static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn, ZERO_STRUCT(handle); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -3262,7 +3262,7 @@ static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn, ZERO_STRUCT(handle); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -3444,7 +3444,7 @@ static bool api_PrintJobInfo(struct smbd_server_connection *sconn, ZERO_STRUCT(handle); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -3621,7 +3621,7 @@ static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn, p = *rdata; p2 = p + struct_len; - status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -4052,7 +4052,7 @@ static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn, ZERO_STRUCT(domain_handle); ZERO_STRUCT(user_handle); - status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id, + status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -4581,7 +4581,7 @@ static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn, ZERO_STRUCT(handle); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -4723,7 +4723,7 @@ static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn, ZERO_STRUCT(handle); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -4923,7 +4923,7 @@ static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn, ZERO_STRUCT(handle); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -5055,7 +5055,7 @@ static bool api_WPrintDestEnum(struct smbd_server_connection *sconn, queuecnt = 0; status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, @@ -5366,7 +5366,7 @@ static bool api_RNetSessionEnum(struct smbd_server_connection *sconn, } status = rpc_pipe_open_interface(conn, - &ndr_table_srvsvc.syntax_id, + &ndr_table_srvsvc, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 3f5b950..eace557 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5637,7 +5637,7 @@ void reply_printqueue(struct smb_request *req) ZERO_STRUCT(handle); status = rpc_pipe_open_interface(conn, - &ndr_table_spoolss.syntax_id, + &ndr_table_spoolss, conn->session_info, conn->sconn->remote_address, conn->sconn->msg_ctx, -- 1.9.3 From 3dc2d438f0b440f34b7cdd9eeac429a15f679460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:03:23 +0200 Subject: [PATCH 023/249] s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_schannel(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit f6d61b571d79ebf1df58513ec728057d00b95f3e) --- source3/auth/auth_domain.c | 2 +- source3/rpc_client/cli_pipe.h | 2 +- source3/rpc_client/cli_pipe_schannel.c | 4 ++-- source3/rpcclient/rpcclient.c | 2 +- source3/utils/net_rpc.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 286c75c..a375f11 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -115,7 +115,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, if (lp_client_schannel()) { /* We also setup the creds chain in the open_schannel call. */ result = cli_rpc_pipe_open_schannel( - *cli, &ndr_table_netlogon.syntax_id, NCACN_NP, + *cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); } else { result = cli_rpc_pipe_open_noauth( diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 3415db0..d17322a 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -125,7 +125,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index c275720..8bc01a5 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -169,7 +169,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, ****************************************************************************/ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, @@ -190,7 +190,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, + cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, &result); /* Now we've bound using the session key we can close the netlog pipe. */ diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index d204d7f..6b6478e 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -734,7 +734,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, break; case DCERPC_AUTH_TYPE_SCHANNEL: ntresult = cli_rpc_pipe_open_schannel( - cli, &cmd_entry->table->syntax_id, + cli, cmd_entry->table, default_transport, pipe_default_auth_level, get_cmdline_auth_info_domain(auth_info), diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 4503f59..dab9fcd 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -191,7 +191,7 @@ int run_rpc_command(struct net_context *c, &ndr_table_netlogon.syntax_id))) { /* Always try and create an schannel netlogon pipe. */ nt_status = cli_rpc_pipe_open_schannel( - cli, &table->syntax_id, NCACN_NP, + cli, table, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain_name, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { -- 1.9.3 From 428596faf89f424c83edb86d45c5a1322e3fb6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:08:33 +0200 Subject: [PATCH 024/249] s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_ntlmssp_auth_schannel(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 7f169474fc86479abe09a5716b8029c6febcfaa9) --- source3/rpc_client/cli_pipe.h | 2 +- source3/rpc_client/cli_pipe_schannel.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index d17322a..7026692 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -116,7 +116,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index 8bc01a5..261a768 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -128,7 +128,7 @@ static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli, ****************************************************************************/ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, @@ -151,7 +151,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, interface, transport, auth_level, domain, &netlogon_pipe->dc, + cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, &result); /* Now we've bound using the session key we can close the netlog pipe. */ -- 1.9.3 From cda31f4e490942ffc89513f000fa147f535a2713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:17:24 +0200 Subject: [PATCH 025/249] s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_schannel_with_key(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 3dc3a6c8483a8de22b483ecf164c81232d4a8d65) --- source3/libnet/libnet_join.c | 2 +- source3/rpc_client/cli_pipe.c | 6 +++--- source3/rpc_client/cli_pipe.h | 2 +- source3/rpc_client/cli_pipe_schannel.c | 4 ++-- source3/utils/net_rpc_join.c | 4 ++-- source3/winbindd/winbindd_cm.c | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 1418385..9f47f3b 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1287,7 +1287,7 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, } status = cli_rpc_pipe_open_schannel_with_key( - cli, &ndr_table_netlogon.syntax_id, NCACN_NP, + cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 427b628..34cef32 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3022,7 +3022,7 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, ****************************************************************************/ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, @@ -3033,7 +3033,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct pipe_auth_data *auth; NTSTATUS status; - status = cli_rpc_pipe_open(cli, transport, interface, &result); + status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3070,7 +3070,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " "for domain %s and bound using schannel.\n", - get_pipe_name_from_syntax(talloc_tos(), interface), + get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), result->desthost, domain)); *presult = result; diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 7026692..65bfbc8 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -108,7 +108,7 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index 261a768..784e63f 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -151,7 +151,7 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, + cli, table, transport, auth_level, domain, &netlogon_pipe->dc, &result); /* Now we've bound using the session key we can close the netlog pipe. */ @@ -190,7 +190,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, &table->syntax_id, transport, auth_level, domain, &netlogon_pipe->dc, + cli, table, transport, auth_level, domain, &netlogon_pipe->dc, &result); /* Now we've bound using the session key we can close the netlog pipe. */ diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 56799cd..4b43769 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -137,7 +137,7 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, } ntret = cli_rpc_pipe_open_schannel_with_key( - cli, &ndr_table_netlogon.syntax_id, NCACN_NP, + cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe->dc, &pipe_hnd); @@ -497,7 +497,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) struct rpc_pipe_client *netlogon_schannel_pipe; status = cli_rpc_pipe_open_schannel_with_key( - cli, &ndr_table_netlogon.syntax_id, NCACN_NP, + cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc, &netlogon_schannel_pipe); diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 61917db..f17fc68 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2415,7 +2415,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto anonymous; } status = cli_rpc_pipe_open_schannel_with_key - (conn->cli, &ndr_table_samr.syntax_id, NCACN_NP, + (conn->cli, &ndr_table_samr, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &p_creds, &conn->samr_pipe); @@ -2547,7 +2547,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, } status = cli_rpc_pipe_open_schannel_with_key(conn->cli, - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, NCACN_IP_TCP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, @@ -2646,7 +2646,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, goto anonymous; } result = cli_rpc_pipe_open_schannel_with_key - (conn->cli, &ndr_table_lsarpc.syntax_id, NCACN_NP, + (conn->cli, &ndr_table_lsarpc, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &p_creds, &conn->lsa_pipe); @@ -2831,7 +2831,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, */ result = cli_rpc_pipe_open_schannel_with_key( - conn->cli, &ndr_table_netlogon.syntax_id, NCACN_NP, + conn->cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc, &conn->netlogon_pipe); -- 1.9.3 From 9b569e91cd22806eedae76d3fb60cdbd7548e4c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:29:28 +0200 Subject: [PATCH 026/249] s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_noauth(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 9813fe2b04a5b4abaa95ea1d893b3803edbede4d) --- source3/auth/auth_domain.c | 2 +- source3/client/client.c | 2 +- source3/lib/netapi/cm.c | 2 +- source3/libnet/libnet_join.c | 8 ++++---- source3/libsmb/libsmb_dir.c | 2 +- source3/libsmb/libsmb_server.c | 2 +- source3/libsmb/passchange.c | 4 ++-- source3/libsmb/trustdom_cache.c | 2 +- source3/libsmb/trusts_util.c | 2 +- source3/rpc_client/cli_pipe.c | 4 ++-- source3/rpc_client/cli_pipe.h | 2 +- source3/rpc_client/cli_pipe_schannel.c | 2 +- source3/rpc_server/spoolss/srv_spoolss_nt.c | 2 +- source3/rpcclient/cmd_spoolss.c | 2 +- source3/rpcclient/cmd_test.c | 4 ++-- source3/rpcclient/rpcclient.c | 2 +- source3/torture/test_async_echo.c | 2 +- source3/utils/net_ads.c | 2 +- source3/utils/net_rpc.c | 20 ++++++++++---------- source3/utils/net_rpc_join.c | 6 +++--- source3/utils/net_rpc_shell.c | 2 +- source3/utils/net_rpc_trust.c | 2 +- source3/utils/net_util.c | 8 ++++---- source3/utils/netlookup.c | 2 +- source3/utils/smbcacls.c | 7 +++---- source3/utils/smbcquotas.c | 2 +- source3/utils/smbtree.c | 2 +- source3/winbindd/winbindd_cm.c | 10 +++++----- 28 files changed, 54 insertions(+), 55 deletions(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index a375f11..54ee5a1 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -119,7 +119,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); } else { result = cli_rpc_pipe_open_noauth( - *cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe); + *cli, &ndr_table_netlogon, &netlogon_pipe); } if (!NT_STATUS_IS_OK(result)) { diff --git a/source3/client/client.c b/source3/client/client.c index ab46cb8..dafc5f0 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -4227,7 +4227,7 @@ static bool browse_host_rpc(bool sort) int i; struct dcerpc_binding_handle *b; - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index 8551521..1cfdccf 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -202,7 +202,7 @@ static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - status = cli_rpc_pipe_open_noauth(ipc->cli, &table->syntax_id, &p->pipe); + status = cli_rpc_pipe_open_noauth(ipc->cli, table, &p->pipe); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(p); return status; diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 9f47f3b..324c8f3 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -749,7 +749,7 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx, goto done; } - status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Error connecting to LSA pipe. Error was %s\n", @@ -819,7 +819,7 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, fstring trust_passwd; NTSTATUS status; - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { return status; @@ -908,7 +908,7 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, /* Open the domain */ - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Error connecting to SAM pipe. Error was %s\n", @@ -1377,7 +1377,7 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx, /* Open the domain */ - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Error connecting to SAM pipe. Error was %s\n", diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 87e10d8..3a07f11 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -277,7 +277,7 @@ net_share_enum_rpc(struct cli_state *cli, struct dcerpc_binding_handle *b; /* Open the server service pipe */ - nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c index d4254da..dff0062 100644 --- a/source3/libsmb/libsmb_server.c +++ b/source3/libsmb/libsmb_server.c @@ -802,7 +802,7 @@ SMBC_attr_server(TALLOC_CTX *ctx, ipc_srv->cli = ipc_cli; nt_status = cli_rpc_pipe_open_noauth( - ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); + ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("cli_nt_session_open fail!\n")); errno = ENOTSUP; diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index 3933833..9736ada 100644 --- a/source3/libsmb/passchange.c +++ b/source3/libsmb/passchange.c @@ -169,7 +169,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam * way. */ result = cli_rpc_pipe_open_noauth( - cli, &ndr_table_samr.syntax_id, &pipe_hnd); + cli, &ndr_table_samr, &pipe_hnd); } if (!NT_STATUS_IS_OK(result)) { @@ -230,7 +230,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam result = NT_STATUS_UNSUCCESSFUL; /* OK, this is ugly, but... try an anonymous pipe. */ - result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, + result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, &pipe_hnd); if ( NT_STATUS_IS_OK(result) && diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c index 8789d30..dadc751 100644 --- a/source3/libsmb/trustdom_cache.c +++ b/source3/libsmb/trustdom_cache.c @@ -289,7 +289,7 @@ static bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, /* open the LSARPC_PIPE */ - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &lsa_pipe); if (!NT_STATUS_IS_OK(status)) { goto done; diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 0d039bc..6156ba0 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -182,7 +182,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m /* Shouldn't we open this with schannel ? JRA. */ nt_status = cli_rpc_pipe_open_noauth( - cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe); + cli, &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", dc_name, nt_errstr(nt_status))); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 34cef32..1137abd 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2948,11 +2948,11 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, ****************************************************************************/ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP, - interface, presult); + &table->syntax_id, presult); } /**************************************************************************** diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 65bfbc8..9aae61a 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -77,7 +77,7 @@ NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c); NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index 784e63f..bc672ef 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -217,7 +217,7 @@ NTSTATUS get_schannel_session_key(struct cli_state *cli, struct rpc_pipe_client *netlogon_pipe = NULL; NTSTATUS status; - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 335647b..c12cd05 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -2504,7 +2504,7 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, * Now start the NT Domain stuff :-). */ - ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe); + ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss, pp_pipe); if (!NT_STATUS_IS_OK(ret)) { DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n", remote_machine, nt_errstr(ret))); diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index 5c499d4..fb011f8 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -3453,7 +3453,7 @@ static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli, if ( !NT_STATUS_IS_OK(nt_status) ) return WERR_GENERAL_FAILURE; - nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id, + nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss, &cli2); if (!NT_STATUS_IS_OK(nt_status)) { printf("failed to open spoolss pipe on server %s (%s)\n", diff --git a/source3/rpcclient/cmd_test.c b/source3/rpcclient/cmd_test.c index 591ae8c..367dc71 100644 --- a/source3/rpcclient/cmd_test.c +++ b/source3/rpcclient/cmd_test.c @@ -36,14 +36,14 @@ static NTSTATUS cmd_testme(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, d_printf("testme\n"); status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli), - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, &lsa_pipe); if (!NT_STATUS_IS_OK(status)) { goto done; } status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli), - &ndr_table_samr.syntax_id, + &ndr_table_samr, &samr_pipe); if (!NT_STATUS_IS_OK(status)) { goto done; diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 6b6478e..e3b35bb 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -167,7 +167,7 @@ static void fetch_machine_sid(struct cli_state *cli) goto error; } - result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &lsapipe); if (!NT_STATUS_IS_OK(result)) { fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) ); diff --git a/source3/torture/test_async_echo.c b/source3/torture/test_async_echo.c index 6df95dd..f21daa4 100644 --- a/source3/torture/test_async_echo.c +++ b/source3/torture/test_async_echo.c @@ -82,7 +82,7 @@ bool run_async_echo(int dummy) printf("torture_open_connection failed\n"); goto fail; } - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_rpcecho.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_rpcecho, &p); if (!NT_STATUS_IS_OK(status)) { printf("Could not open echo pipe: %s\n", nt_errstr(status)); diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 5699943..89eebf3 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -1957,7 +1957,7 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char * SAFE_FREE(srv_cn_escaped); SAFE_FREE(printername_escaped); - nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss.syntax_id, &pipe_hnd); + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"), servername); diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index dab9fcd..69ff14d 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -82,7 +82,7 @@ NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, union lsa_PolicyInformation *info = NULL; struct dcerpc_binding_handle *b; - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &lsa_pipe); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Could not initialise lsa pipe\n")); @@ -212,7 +212,7 @@ int run_rpc_command(struct net_context *c, c->opt_password, &pipe_hnd); } else { nt_status = cli_rpc_pipe_open_noauth( - cli, &table->syntax_id, + cli, table, &pipe_hnd); } if (!NT_STATUS_IS_OK(nt_status)) { @@ -348,7 +348,7 @@ static NTSTATUS rpc_oldjoin_internals(struct net_context *c, NTSTATUS result; enum netr_SchannelType sec_channel_type; - result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, + result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, &pipe_hnd); if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. " @@ -1966,7 +1966,7 @@ static NTSTATUS get_sid_from_name(struct cli_state *cli, NTSTATUS status, result; struct dcerpc_binding_handle *b; - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { goto done; @@ -2980,7 +2980,7 @@ static NTSTATUS rpc_list_alias_members(struct net_context *c, } result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd), - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, &lsa_pipe); if (!NT_STATUS_IS_OK(result)) { d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"), @@ -6232,7 +6232,7 @@ static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c, /* Try netr_GetDcName */ - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, &netr); if (!NT_STATUS_IS_OK(status)) { return status; @@ -6379,7 +6379,7 @@ static int rpc_trustdom_establish(struct net_context *c, int argc, * Call LsaOpenPolicy and LsaQueryInfo */ - nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) )); @@ -6656,7 +6656,7 @@ static int rpc_trustdom_vampire(struct net_context *c, int argc, return -1; }; - nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", @@ -6834,7 +6834,7 @@ static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv) return -1; }; - nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", @@ -6950,7 +6950,7 @@ static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv) /* * Open \PIPE\samr and get needed policy handles */ - nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status))); diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 4b43769..aabbe54 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -245,7 +245,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) /* Fetch domain sid */ - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n", @@ -280,7 +280,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) } /* Create domain user */ - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n", @@ -456,7 +456,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) /* Now check the whole process from top-to-bottom */ - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", diff --git a/source3/utils/net_rpc_shell.c b/source3/utils/net_rpc_shell.c index 6086066..120cfa6 100644 --- a/source3/utils/net_rpc_shell.c +++ b/source3/utils/net_rpc_shell.c @@ -85,7 +85,7 @@ static NTSTATUS net_sh_run(struct net_context *c, return NT_STATUS_NO_MEMORY; } - status = cli_rpc_pipe_open_noauth(ctx->cli, &cmd->table->syntax_id, + status = cli_rpc_pipe_open_noauth(ctx->cli, cmd->table, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Could not open pipe: %s\n"), diff --git a/source3/utils/net_rpc_trust.c b/source3/utils/net_rpc_trust.c index 9060700..5e58103 100644 --- a/source3/utils/net_rpc_trust.c +++ b/source3/utils/net_rpc_trust.c @@ -210,7 +210,7 @@ static NTSTATUS connect_and_get_info(TALLOC_CTX *mem_ctx, return status; } - status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id, pipe_hnd); + status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc, pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n", nt_errstr(status))); diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c index a4282ec..13a0ef1 100644 --- a/source3/utils/net_util.c +++ b/source3/utils/net_util.c @@ -45,7 +45,7 @@ NTSTATUS net_rpc_lookup_name(struct net_context *c, ZERO_STRUCT(pol); - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &lsa_pipe); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Could not initialise lsa pipe\n")); @@ -256,7 +256,7 @@ NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, return nt_status; } - nt_status = cli_rpc_pipe_open_noauth(cli_tmp, &table->syntax_id, + nt_status = cli_rpc_pipe_open_noauth(cli_tmp, table, &pipe_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("couldn't not initialize pipe\n")); @@ -571,7 +571,7 @@ static NTSTATUS net_scan_dc_noad(struct net_context *c, ZERO_STRUCTP(dc_info); ZERO_STRUCT(pol); - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { return status; @@ -634,7 +634,7 @@ NTSTATUS net_scan_dc(struct net_context *c, ZERO_STRUCTP(dc_info); - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_dssetup.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_dssetup, &dssetup_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("net_scan_dc: failed to open dssetup pipe with %s, " diff --git a/source3/utils/netlookup.c b/source3/utils/netlookup.c index b66c34e..56d3bfe 100644 --- a/source3/utils/netlookup.c +++ b/source3/utils/netlookup.c @@ -122,7 +122,7 @@ static struct con_struct *create_cs(struct net_context *c, } nt_status = cli_rpc_pipe_open_noauth(cs->cli, - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, &cs->lsapipe); if (!NT_STATUS_IS_OK(nt_status)) { diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 23a1192..f092839 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -96,7 +96,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli, goto tcon_fail; } - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &p); if (!NT_STATUS_IS_OK(status)) { goto fail; @@ -146,7 +146,7 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli, goto tcon_fail; } - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &p); if (!NT_STATUS_IS_OK(status)) { goto fail; @@ -187,14 +187,13 @@ static NTSTATUS cli_lsa_lookup_domain_sid(struct cli_state *cli, struct policy_handle handle; NTSTATUS status, result; TALLOC_CTX *frame = talloc_stackframe(); - const struct ndr_syntax_id *lsarpc_syntax = &ndr_table_lsarpc.syntax_id; status = cli_tree_connect(cli, "IPC$", "?????", "", 0); if (!NT_STATUS_IS_OK(status)) { goto done; } - status = cli_rpc_pipe_open_noauth(cli, lsarpc_syntax, &rpc_pipe); + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc, &rpc_pipe); if (!NT_STATUS_IS_OK(status)) { goto tdis; } diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c index bf1f95c..2791b93 100644 --- a/source3/utils/smbcquotas.c +++ b/source3/utils/smbcquotas.c @@ -58,7 +58,7 @@ static bool cli_open_policy_hnd(void) NTSTATUS ret; cli_ipc = connect_one("IPC$"); ret = cli_rpc_pipe_open_noauth(cli_ipc, - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, &global_pipe_hnd); if (!NT_STATUS_IS_OK(ret)) { return False; diff --git a/source3/utils/smbtree.c b/source3/utils/smbtree.c index 40b1f09..5c07b12 100644 --- a/source3/utils/smbtree.c +++ b/source3/utils/smbtree.c @@ -177,7 +177,7 @@ static bool get_rpc_shares(struct cli_state *cli, return False; } - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, + status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index f17fc68..facef64 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2078,7 +2078,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name )); status = cli_rpc_pipe_open_noauth(domain->conn.cli, - &ndr_table_dssetup.syntax_id, + &ndr_table_dssetup, &cli); if (!NT_STATUS_IS_OK(status)) { @@ -2129,7 +2129,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain ) no_dssetup: status = cli_rpc_pipe_open_noauth(domain->conn.cli, - &ndr_table_lsarpc.syntax_id, &cli); + &ndr_table_lsarpc, &cli); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to " @@ -2447,7 +2447,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, anonymous: /* Finally fall back to anonymous. */ - status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr.syntax_id, + status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr, &conn->samr_pipe); if (!NT_STATUS_IS_OK(status)) { @@ -2674,7 +2674,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, anonymous: result = cli_rpc_pipe_open_noauth(conn->cli, - &ndr_table_lsarpc.syntax_id, + &ndr_table_lsarpc, &conn->lsa_pipe); if (!NT_STATUS_IS_OK(result)) { result = NT_STATUS_PIPE_NOT_AVAILABLE; @@ -2765,7 +2765,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, TALLOC_FREE(conn->netlogon_pipe); result = cli_rpc_pipe_open_noauth(conn->cli, - &ndr_table_netlogon.syntax_id, + &ndr_table_netlogon, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { return result; -- 1.9.3 From fce35e003f655b3564ee4df5ebfe7f3e6ff6d188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:33:03 +0200 Subject: [PATCH 027/249] s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open_noauth_transport(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 9aa99c3cfb0ff7a290dd4df472a4ff30d0efcb76) --- source3/rpc_client/cli_pipe.c | 13 +++++++------ source3/rpc_client/cli_pipe.h | 2 +- source3/rpcclient/rpcclient.c | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 1137abd..4523ab7 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2865,14 +2865,14 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, enum dcerpc_transport_t transport, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result; struct pipe_auth_data *auth; NTSTATUS status; - status = cli_rpc_pipe_open(cli, transport, interface, &result); + status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2921,7 +2921,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, status = rpc_pipe_bind(result, auth); if (!NT_STATUS_IS_OK(status)) { int lvl = 0; - if (ndr_syntax_id_equal(interface, + if (ndr_syntax_id_equal(&table->syntax_id, &ndr_table_dssetup.syntax_id)) { /* non AD domains just don't have this pipe, avoid * level 0 statement in that case - gd */ @@ -2929,7 +2929,8 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, } DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe " "%s failed with error %s\n", - get_pipe_name_from_syntax(talloc_tos(), interface), + get_pipe_name_from_syntax(talloc_tos(), + &table->syntax_id), nt_errstr(status) )); TALLOC_FREE(result); return status; @@ -2937,7 +2938,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine " "%s and bound anonymously.\n", - get_pipe_name_from_syntax(talloc_tos(), interface), + get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), result->desthost)); *presult = result; @@ -2952,7 +2953,7 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, struct rpc_pipe_client **presult) { return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP, - &table->syntax_id, presult); + table, presult); } /**************************************************************************** diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 9aae61a..f37f8a9 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -82,7 +82,7 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, enum dcerpc_transport_t transport, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index e3b35bb..c23ff2d 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -690,7 +690,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, case DCERPC_AUTH_TYPE_NONE: ntresult = cli_rpc_pipe_open_noauth_transport( cli, default_transport, - &cmd_entry->table->syntax_id, + cmd_entry->table, &cmd_entry->rpc_pipe); break; case DCERPC_AUTH_TYPE_SPNEGO: -- 1.9.3 From 0d85042853b635486912688102253b2f358b5056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:38:01 +0200 Subject: [PATCH 028/249] s3-rpc_cli: pass down ndr_interface_table to cli_rpc_pipe_open(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 34cc4b409558f229fba24f59e81ef9100a851d24) --- source3/rpc_client/cli_pipe.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 4523ab7..4dc7345 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2843,7 +2843,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, enum dcerpc_transport_t transport, - const struct ndr_syntax_id *interface, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { switch (transport) { @@ -2851,9 +2851,9 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, return rpc_pipe_open_tcp(NULL, smbXcli_conn_remote_name(cli->conn), smbXcli_conn_remote_sockaddr(cli->conn), - interface, presult); + &table->syntax_id, presult); case NCACN_NP: - return rpc_pipe_open_np(cli, interface, presult); + return rpc_pipe_open_np(cli, &table->syntax_id, presult); default: return NT_STATUS_NOT_IMPLEMENTED; } @@ -2872,7 +2872,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, struct pipe_auth_data *auth; NTSTATUS status; - status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); + status = cli_rpc_pipe_open(cli, transport, table, &result); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -2977,7 +2977,7 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, NTSTATUS status; - status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); + status = cli_rpc_pipe_open(cli, transport, table, &result); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3034,7 +3034,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct pipe_auth_data *auth; NTSTATUS status; - status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); + status = cli_rpc_pipe_open(cli, transport, table, &result); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -3104,7 +3104,7 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, return NT_STATUS_INVALID_PARAMETER; } - status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); + status = cli_rpc_pipe_open(cli, transport, table, &result); if (!NT_STATUS_IS_OK(status)) { return status; } -- 1.9.3 From d5e312185a7adc8429f8caba29a9808ab7954a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:40:45 +0200 Subject: [PATCH 029/249] s3-rpc_cli: pass down ndr_interface_table to rpc_pipe_open_np(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 8cd3a060514ddcc178c938100edfb0b177c00c8c) --- source3/rpc_client/cli_pipe.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 4dc7345..0347d76 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2775,7 +2775,7 @@ static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_r ****************************************************************************/ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result; @@ -2793,7 +2793,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, return NT_STATUS_NO_MEMORY; } - result->abstract_syntax = *abstract_syntax; + result->abstract_syntax = table->syntax_id; result->transfer_syntax = ndr_transfer_syntax_ndr; result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn)); result->srv_name_slash = talloc_asprintf_strupper_m( @@ -2807,7 +2807,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, return NT_STATUS_NO_MEMORY; } - status = rpc_transport_np_init(result, cli, abstract_syntax, + status = rpc_transport_np_init(result, cli, &table->syntax_id, &result->transport); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(result); @@ -2853,7 +2853,7 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, smbXcli_conn_remote_sockaddr(cli->conn), &table->syntax_id, presult); case NCACN_NP: - return rpc_pipe_open_np(cli, &table->syntax_id, presult); + return rpc_pipe_open_np(cli, table, presult); default: return NT_STATUS_NOT_IMPLEMENTED; } -- 1.9.3 From f1fa7838cb933fd0d390a56d823272f8528eb63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:44:00 +0200 Subject: [PATCH 030/249] s3-rpc_cli: pass down ndr_interface_table to rpc_pipe_open_tcp(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 5c5cff0a722a0925ae75ea7aa11ede0d82d5b92d) --- source3/rpc_client/cli_pipe.c | 8 ++++---- source3/rpc_client/cli_pipe.h | 2 +- source3/torture/rpc_open_tcp.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 0347d76..46adf69 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2663,19 +2663,19 @@ done: */ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, const struct sockaddr_storage *addr, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { NTSTATUS status; uint16_t port = 0; - status = rpc_pipe_get_tcp_port(host, addr, abstract_syntax, &port); + status = rpc_pipe_get_tcp_port(host, addr, &table->syntax_id, &port); if (!NT_STATUS_IS_OK(status)) { return status; } return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port, - abstract_syntax, presult); + &table->syntax_id, presult); } /******************************************************************** @@ -2851,7 +2851,7 @@ static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli, return rpc_pipe_open_tcp(NULL, smbXcli_conn_remote_name(cli->conn), smbXcli_conn_remote_sockaddr(cli->conn), - &table->syntax_id, presult); + table, presult); case NCACN_NP: return rpc_pipe_open_np(cli, table, presult); default: diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index f37f8a9..6fcc587 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -67,7 +67,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, const struct sockaddr_storage *ss_addr, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult); NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path, diff --git a/source3/torture/rpc_open_tcp.c b/source3/torture/rpc_open_tcp.c index d29f4cf..cd27b5f 100644 --- a/source3/torture/rpc_open_tcp.c +++ b/source3/torture/rpc_open_tcp.c @@ -95,7 +95,7 @@ int main(int argc, const char **argv) } status = rpc_pipe_open_tcp(mem_ctx, argv[2], NULL, - &((*table)->syntax_id), + *table, &rpc_pipe); if (!NT_STATUS_IS_OK(status)) { d_printf("ERROR calling rpc_pipe_open_tcp(): %s\n", -- 1.9.3 From 67c01c15af1bbb98916e75f7cad61edcc13c2e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:46:07 +0200 Subject: [PATCH 031/249] s3-rpc_cli: pass down ndr_interface_table to rpc_pipe_get_tcp_port(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 0ff8c2d508949f732716e24047694cecf38597df) --- source3/rpc_client/cli_pipe.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 46adf69..15e77db 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2518,7 +2518,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, */ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, const struct sockaddr_storage *addr, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, uint16_t *pport) { NTSTATUS status; @@ -2541,7 +2541,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, goto done; } - if (ndr_syntax_id_equal(abstract_syntax, + if (ndr_syntax_id_equal(&table->syntax_id, &ndr_table_epmapper.syntax_id)) { *pport = 135; return NT_STATUS_OK; @@ -2576,7 +2576,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, } map_binding->transport = NCACN_IP_TCP; - map_binding->object = *abstract_syntax; + map_binding->object = table->syntax_id; map_binding->host = host; /* needed? */ map_binding->endpoint = "0"; /* correct? needed? */ @@ -2612,7 +2612,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, status = dcerpc_epm_Map(epm_handle, tmp_ctx, discard_const_p(struct GUID, - &(abstract_syntax->uuid)), + &(table->syntax_id.uuid)), map_tower, entry_handle, max_towers, @@ -2669,7 +2669,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, NTSTATUS status; uint16_t port = 0; - status = rpc_pipe_get_tcp_port(host, addr, &table->syntax_id, &port); + status = rpc_pipe_get_tcp_port(host, addr, table, &port); if (!NT_STATUS_IS_OK(status)) { return status; } -- 1.9.3 From a032ff8c89e479792947af4315ed6eb59a69f8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:47:16 +0200 Subject: [PATCH 032/249] s3-rpc_cli: pass down ndr_interface_table to rpc_pipe_open_tcp_port(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 7bdcfcb37c5b96ee6aa0cecffd89c6d17291fe62) --- source3/rpc_client/cli_pipe.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 15e77db..1b2955f 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2447,7 +2447,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, const struct sockaddr_storage *ss_addr, uint16_t port, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result; @@ -2460,7 +2460,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, return NT_STATUS_NO_MEMORY; } - result->abstract_syntax = *abstract_syntax; + result->abstract_syntax = table->syntax_id; result->transfer_syntax = ndr_transfer_syntax_ndr; result->desthost = talloc_strdup(result, host); @@ -2549,7 +2549,7 @@ static NTSTATUS rpc_pipe_get_tcp_port(const char *host, /* open the connection to the endpoint mapper */ status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135, - &ndr_table_epmapper.syntax_id, + &ndr_table_epmapper, &epm_pipe); if (!NT_STATUS_IS_OK(status)) { @@ -2675,7 +2675,7 @@ NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, } return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port, - &table->syntax_id, presult); + table, presult); } /******************************************************************** -- 1.9.3 From 0b4ae5ec146e35c364f01c033d6c22efb99b7314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:52:05 +0200 Subject: [PATCH 033/249] s3-rpc_cli: pass down ndr_interface_table to rpc_transport_np_init(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit c41b6e5c5e7fcdbd98c1eb2bea08378b47d343d4) --- source3/rpc_client/cli_pipe.c | 2 +- source3/rpc_client/rpc_transport.h | 2 +- source3/rpc_client/rpc_transport_np.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 1b2955f..1fa8d91 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2807,7 +2807,7 @@ static NTSTATUS rpc_pipe_open_np(struct cli_state *cli, return NT_STATUS_NO_MEMORY; } - status = rpc_transport_np_init(result, cli, &table->syntax_id, + status = rpc_transport_np_init(result, cli, table, &result->transport); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(result); diff --git a/source3/rpc_client/rpc_transport.h b/source3/rpc_client/rpc_transport.h index bc115dd..2b4a323 100644 --- a/source3/rpc_client/rpc_transport.h +++ b/source3/rpc_client/rpc_transport.h @@ -89,7 +89,7 @@ NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_transport **presult); NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_cli_transport **presult); /* The following definitions come from rpc_client/rpc_transport_sock.c */ diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index f0696ad..7bd1ca3 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -152,7 +152,7 @@ NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, } NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, - const struct ndr_syntax_id *abstract_syntax, + const struct ndr_interface_table *table, struct rpc_cli_transport **presult) { TALLOC_CTX *frame = talloc_stackframe(); @@ -166,7 +166,7 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, goto fail; } - req = rpc_transport_np_init_send(frame, ev, cli, abstract_syntax); + req = rpc_transport_np_init_send(frame, ev, cli, &table->syntax_id); if (req == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; -- 1.9.3 From 739d05d91f23c4c6e17078c84192f30911cbdfcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 24 May 2013 13:56:53 +0200 Subject: [PATCH 034/249] s3-rpc_cli: pass down ndr_interface_table to rpc_transport_np_init_send(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit b19e7e6638a5dd53e3c6e6701f78bf31184ed493) --- source3/rpc_client/rpc_transport.h | 2 +- source3/rpc_client/rpc_transport_np.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/rpc_client/rpc_transport.h b/source3/rpc_client/rpc_transport.h index 2b4a323..72e7609 100644 --- a/source3/rpc_client/rpc_transport.h +++ b/source3/rpc_client/rpc_transport.h @@ -84,7 +84,7 @@ struct cli_state; struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - const struct ndr_syntax_id *abstract_syntax); + const struct ndr_interface_table *table); NTSTATUS rpc_transport_np_init_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct rpc_cli_transport **presult); diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index 7bd1ca3..c0f313e 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -40,7 +40,7 @@ static void rpc_transport_np_init_pipe_open(struct tevent_req *subreq); struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - const struct ndr_syntax_id *abstract_syntax) + const struct ndr_interface_table *table) { struct tevent_req *req; struct rpc_transport_np_init_state *state; @@ -55,7 +55,7 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->cli = cli; state->abs_timeout = timeval_current_ofs_msec(cli->timeout); - state->pipe_name = get_pipe_name_from_syntax(state, abstract_syntax); + state->pipe_name = get_pipe_name_from_syntax(state, &table->syntax_id); if (tevent_req_nomem(state->pipe_name, req)) { return tevent_req_post(req, ev); } @@ -166,7 +166,7 @@ NTSTATUS rpc_transport_np_init(TALLOC_CTX *mem_ctx, struct cli_state *cli, goto fail; } - req = rpc_transport_np_init_send(frame, ev, cli, &table->syntax_id); + req = rpc_transport_np_init_send(frame, ev, cli, table); if (req == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; -- 1.9.3 From c5529ee9045c44114ab1716b05d3408baa1b4e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 24 Sep 2008 11:04:42 +0200 Subject: [PATCH 035/249] s3: libnet_join: add admin_domain. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit c11a79c5a054e862f61c97093fa2ce5e5040f111) --- source3/librpc/idl/libnet_join.idl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source3/librpc/idl/libnet_join.idl b/source3/librpc/idl/libnet_join.idl index 4f28bb6..ac0a350 100644 --- a/source3/librpc/idl/libnet_join.idl +++ b/source3/librpc/idl/libnet_join.idl @@ -21,6 +21,7 @@ interface libnetjoin [in,ref] string *domain_name, [in] string account_ou, [in] string admin_account, + [in] string admin_domain, [in,noprint] string admin_password, [in] string machine_password, [in] wkssvc_joinflags join_flags, @@ -51,6 +52,7 @@ interface libnetjoin [in] string domain_name, [in] string account_ou, [in] string admin_account, + [in] string admin_domain, [in,noprint] string admin_password, [in] string machine_password, [in] wkssvc_joinflags unjoin_flags, -- 1.9.3 From a0d8f42ac44d279ae7bc599792cd1d564925dcbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 24 Sep 2008 11:05:37 +0200 Subject: [PATCH 036/249] s3: libnet_join: use admin_domain in libnetjoin. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit cc0cbd4fdc6e07538d67cc41ca07bad1eaebf493) --- source3/libnet/libnet_join.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 324c8f3..2253079 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -701,6 +701,7 @@ static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx, static NTSTATUS libnet_join_connect_dc_ipc(const char *dc, const char *user, + const char *domain, const char *pass, bool use_kerberos, struct cli_state **cli) @@ -720,7 +721,7 @@ static NTSTATUS libnet_join_connect_dc_ipc(const char *dc, NULL, 0, "IPC$", "IPC", user, - NULL, + domain, pass, flags, SMB_SIGNING_DEFAULT); @@ -742,6 +743,7 @@ static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx, status = libnet_join_connect_dc_ipc(r->in.dc_name, r->in.admin_account, + r->in.admin_domain, r->in.admin_password, r->in.use_kerberos, cli); @@ -1368,6 +1370,7 @@ static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx, status = libnet_join_connect_dc_ipc(r->in.dc_name, r->in.admin_account, + r->in.admin_domain, r->in.admin_password, r->in.use_kerberos, &cli); @@ -1755,6 +1758,17 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx, return WERR_SETUP_DOMAIN_CONTROLLER; } + if (!r->in.admin_domain) { + char *admin_domain = NULL; + char *admin_account = NULL; + split_domain_user(mem_ctx, + r->in.admin_account, + &admin_domain, + &admin_account); + r->in.admin_domain = admin_domain; + r->in.admin_account = admin_account; + } + if (!secrets_init()) { libnet_join_set_error_string(mem_ctx, r, "Unable to open secrets database"); @@ -2316,6 +2330,17 @@ static WERROR libnet_unjoin_pre_processing(TALLOC_CTX *mem_ctx, return WERR_SETUP_DOMAIN_CONTROLLER; } + if (!r->in.admin_domain) { + char *admin_domain = NULL; + char *admin_account = NULL; + split_domain_user(mem_ctx, + r->in.admin_account, + &admin_domain, + &admin_account); + r->in.admin_domain = admin_domain; + r->in.admin_account = admin_account; + } + if (!secrets_init()) { libnet_unjoin_set_error_string(mem_ctx, r, "Unable to open secrets database"); -- 1.9.3 From 46f8496292a12b7acdd045d126b61fa9d8afee74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 6 Nov 2008 11:40:03 +0100 Subject: [PATCH 037/249] s3-libnetjoin: add machine_name length check. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit c4d6d75cf48aed7b17728e283581366143fa4233) --- source3/libnet/libnet_join.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 2253079..b731d9b 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1746,6 +1746,15 @@ static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx, return WERR_INVALID_PARAM; } + if (strlen(r->in.machine_name) > 15) { + libnet_join_set_error_string(mem_ctx, r, + "Our netbios name can be at most 15 chars long, " + "\"%s\" is %u chars long\n", + r->in.machine_name, + (unsigned int)strlen(r->in.machine_name)); + return WERR_INVALID_PARAM; + } + if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name, &r->in.domain_name, &r->in.dc_name)) { -- 1.9.3 From a60cf7ddd4e2d41d92cdd35ab05f2d6a30b055c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 6 Nov 2008 13:37:45 +0100 Subject: [PATCH 038/249] s3-libnetjoin: move "net rpc oldjoin" to use libnetjoin. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit d398a12f7907866189c1b253ca6a40e5454f42a1) --- source3/utils/net_rpc.c | 182 ++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 98 deletions(-) diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 69ff14d..720e9d2 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -37,6 +37,8 @@ #include "secrets.h" #include "lib/netapi/netapi.h" #include "lib/netapi/netapi_net.h" +#include "librpc/gen_ndr/libnet_join.h" +#include "libnet/libnet_join.h" #include "rpc_client/init_lsa.h" #include "../libcli/security/security.h" #include "libsmb/libsmb.h" @@ -314,48 +316,46 @@ int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv) } /** - * Join a domain, the old way. + * Join a domain, the old way. This function exists to allow + * the message to be displayed when oldjoin was explicitly + * requested, but not when it was implied by "net rpc join". * * This uses 'machinename' as the inital password, and changes it. * * The password should be created with 'server manager' or equiv first. * - * All parameters are provided by the run_rpc_command function, except for - * argc, argv which are passed through. - * - * @param domain_sid The domain sid acquired from the remote server. - * @param cli A cli_state connected to the server. - * @param mem_ctx Talloc context, destroyed on completion of the function. * @param argc Standard main() style argc. * @param argv Standard main() style argv. Initial components are already * stripped. * - * @return Normal NTSTATUS return. + * @return A shell status integer (0 for success). **/ -static NTSTATUS rpc_oldjoin_internals(struct net_context *c, - const struct dom_sid *domain_sid, - const char *domain_name, - struct cli_state *cli, - struct rpc_pipe_client *pipe_hnd, - TALLOC_CTX *mem_ctx, - int argc, - const char **argv) +static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) { + struct libnet_JoinCtx *r = NULL; + TALLOC_CTX *mem_ctx; + WERROR werr; + const char *domain = lp_workgroup(); /* FIXME */ + bool modify_config = lp_config_backend_is_registry(); + enum netr_SchannelType sec_chan_type; + char *pw = NULL; - fstring trust_passwd; - unsigned char orig_trust_passwd_hash[16]; - NTSTATUS result; - enum netr_SchannelType sec_channel_type; + if (c->display_usage) { + d_printf("Usage:\n" + "net rpc oldjoin\n" + " Join a domain the old way\n"); + return 0; + } - result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, - &pipe_hnd); - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. " - "error was %s\n", - smbXcli_conn_remote_name(cli->conn), - nt_errstr(result) )); - return result; + mem_ctx = talloc_init("net_rpc_oldjoin"); + if (!mem_ctx) { + return -1; + } + + werr = libnet_init_JoinCtx(mem_ctx, &r); + if (!W_ERROR_IS_OK(werr)) { + goto fail; } /* @@ -363,92 +363,78 @@ static NTSTATUS rpc_oldjoin_internals(struct net_context *c, a BDC, the server must agree that we are a BDC. */ if (argc >= 0) { - sec_channel_type = get_sec_channel_type(argv[0]); + sec_chan_type = get_sec_channel_type(argv[0]); } else { - sec_channel_type = get_sec_channel_type(NULL); + sec_chan_type = get_sec_channel_type(NULL); } - fstrcpy(trust_passwd, lp_netbios_name()); - if (!strlower_m(trust_passwd)) { - return NT_STATUS_UNSUCCESSFUL; + if (!c->msg_ctx) { + d_fprintf(stderr, _("Could not initialise message context. " + "Try running as root\n")); + werr = WERR_ACCESS_DENIED; + goto fail; } - /* - * Machine names can be 15 characters, but the max length on - * a password is 14. --jerry - */ - - trust_passwd[14] = '\0'; - - E_md4hash(trust_passwd, orig_trust_passwd_hash); - - result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup, - lp_netbios_name(), - orig_trust_passwd_hash, - sec_channel_type); - - if (NT_STATUS_IS_OK(result)) - printf(_("Joined domain %s.\n"), c->opt_target_workgroup); + pw = talloc_strndup(r, lp_netbios_name(), 14); + if (pw == NULL) { + werr = WERR_NOMEM; + goto fail; + } + r->in.msg_ctx = c->msg_ctx; + r->in.domain_name = domain; + r->in.secure_channel_type = sec_chan_type; + r->in.dc_name = c->opt_host; + r->in.admin_account = ""; + r->in.admin_password = strlower_talloc(r, pw); + if (r->in.admin_password == NULL) { + werr = WERR_NOMEM; + goto fail; + } + r->in.debug = true; + r->in.modify_config = modify_config; + r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | + WKSSVC_JOIN_FLAGS_JOIN_UNSECURE | + WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED; - if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) { - DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup)); - result = NT_STATUS_UNSUCCESSFUL; + werr = libnet_Join(mem_ctx, r); + if (!W_ERROR_IS_OK(werr)) { + goto fail; } - return result; -} + /* Check the short name of the domain */ -/** - * Join a domain, the old way. - * - * @param argc Standard main() style argc. - * @param argv Standard main() style argv. Initial components are already - * stripped. - * - * @return A shell status integer (0 for success). - **/ + if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) { + d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE()); + d_printf("domain name obtained from the server.\n"); + d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name); + d_printf("You should set \"workgroup = %s\" in %s.\n", + r->out.netbios_domain_name, get_dyn_CONFIGFILE()); + } -static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv) -{ - return run_rpc_command(c, NULL, &ndr_table_netlogon, - NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, - rpc_oldjoin_internals, - argc, argv); -} + d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name); -/** - * Join a domain, the old way. This function exists to allow - * the message to be displayed when oldjoin was explicitly - * requested, but not when it was implied by "net rpc join". - * - * @param argc Standard main() style argc. - * @param argv Standard main() style argv. Initial components are already - * stripped. - * - * @return A shell status integer (0 for success). - **/ + if (r->out.dns_domain_name) { + d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name, + r->out.dns_domain_name); + } else { + d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name, + r->out.netbios_domain_name); + } -static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) -{ - int rc = -1; + TALLOC_FREE(mem_ctx); - if (c->display_usage) { - d_printf( "%s\n" - "net rpc oldjoin\n" - " %s\n", - _("Usage:"), - _("Join a domain the old way")); - return 0; - } + return 0; - rc = net_rpc_perform_oldjoin(c, argc, argv); +fail: + /* issue an overall failure message at the end. */ + d_fprintf(stderr, _("Failed to join domain: %s\n"), + r && r->out.error_string ? r->out.error_string : + get_friendly_werror_msg(werr)); - if (rc) { - d_fprintf(stderr, _("Failed to join domain\n")); - } + TALLOC_FREE(mem_ctx); - return rc; + return -1; } /** @@ -492,7 +478,7 @@ int net_rpc_join(struct net_context *c, int argc, const char **argv) return -1; } - if ((net_rpc_perform_oldjoin(c, argc, argv) == 0)) + if ((net_rpc_oldjoin(c, argc, argv) == 0)) return 0; return net_rpc_join_newstyle(c, argc, argv); -- 1.9.3 From 3185251186366984b5ec06322c75cfda71dccdbc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Jun 2013 19:12:27 +0200 Subject: [PATCH 039/249] s3:libnet: let the caller truncate the pw in libnet_join_joindomain_rpc_unsecure() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 1242ab0cb3bf575b695b39313604af9d0a7f1b3a) --- source3/libnet/libnet_join.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index b731d9b..d8ec235 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -818,7 +818,6 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *pipe_hnd = NULL; unsigned char orig_trust_passwd_hash[16]; unsigned char new_trust_passwd_hash[16]; - fstring trust_passwd; NTSTATUS status; status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, @@ -837,19 +836,7 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, E_md4hash(r->in.machine_password, new_trust_passwd_hash); /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */ - fstrcpy(trust_passwd, r->in.admin_password); - if (!strlower_m(trust_passwd)) { - return NT_STATUS_INVALID_PARAMETER; - } - - /* - * Machine names can be 15 characters, but the max length on - * a password is 14. --jerry - */ - - trust_passwd[14] = '\0'; - - E_md4hash(trust_passwd, orig_trust_passwd_hash); + E_md4hash(r->in.admin_password, orig_trust_passwd_hash); status = rpccli_netlogon_set_trust_password(pipe_hnd, mem_ctx, r->in.machine_name, -- 1.9.3 From e1e15a73a9a5215866f6471c5e583457c516b47e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 3 Feb 2009 20:10:05 +0100 Subject: [PATCH 040/249] s3-net: use libnetjoin for "net rpc testjoin". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 9cfa6251600ddea0e821f2bd3fd359c28eb1b7f9) --- source3/utils/net_proto.h | 2 +- source3/utils/net_rpc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ source3/utils/net_rpc_join.c | 29 ------------------- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index 03fb312..d791708 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -145,6 +145,7 @@ int run_rpc_command(struct net_context *c, int argc, const char **argv); int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv); +int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); int net_rpc_join(struct net_context *c, int argc, const char **argv); NTSTATUS rpc_info_internals(struct net_context *c, const struct dom_sid *domain_sid, @@ -205,7 +206,6 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, const char *server, const struct sockaddr_storage *server_ss); int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); -int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); /* The following definitions come from utils/net_rpc_printer.c */ diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 720e9d2..592be44 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -438,6 +438,72 @@ fail: } /** + * check that a join is OK + * + * @return A shell status integer (0 for success) + * + **/ +int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) +{ + NTSTATUS status; + TALLOC_CTX *mem_ctx; + const char *domain = c->opt_target_workgroup; + const char *dc = c->opt_host; + + if (c->display_usage) { + d_printf("Usage\n" + "net rpc testjoin\n" + " Test if a join is OK\n"); + return 0; + } + + mem_ctx = talloc_init("net_rpc_testjoin"); + if (!mem_ctx) { + return -1; + } + + if (!dc) { + struct netr_DsRGetDCNameInfo *info; + + if (!c->msg_ctx) { + d_fprintf(stderr, _("Could not initialise message context. " + "Try running as root\n")); + talloc_destroy(mem_ctx); + return -1; + } + + status = dsgetdcname(mem_ctx, + c->msg_ctx, + domain, + NULL, + NULL, + DS_RETURN_DNS_NAME, + &info); + if (!NT_STATUS_IS_OK(status)) { + talloc_destroy(mem_ctx); + return -1; + } + + dc = strip_hostname(info->dc_unc); + } + + /* Display success or failure */ + status = libnet_join_ok(c->opt_workgroup, lp_netbios_name(), dc, + c->opt_kerberos); + if (!NT_STATUS_IS_OK(status)) { + fprintf(stderr,"Join to domain '%s' is not valid: %s\n", + domain, nt_errstr(status)); + talloc_destroy(mem_ctx); + return -1; + } + + printf("Join to '%s' is OK\n",domain); + talloc_destroy(mem_ctx); + + return 0; +} + +/** * 'net rpc join' entrypoint. * @param argc Standard main() style argc. * @param argv Standard main() style argv. Initial components are already diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index aabbe54..ee39a5c 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -561,32 +561,3 @@ done: return retval; } - -/** - * check that a join is OK - * - * @return A shell status integer (0 for success) - * - **/ -int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) -{ - NTSTATUS nt_status; - - if (c->display_usage) { - d_printf(_("Usage\n" - "net rpc testjoin\n" - " Test if a join is OK\n")); - return 0; - } - - /* Display success or failure */ - nt_status = net_rpc_join_ok(c, c->opt_target_workgroup, NULL, NULL); - if (!NT_STATUS_IS_OK(nt_status)) { - fprintf(stderr, _("Join to domain '%s' is not valid: %s\n"), - c->opt_target_workgroup, nt_errstr(nt_status)); - return -1; - } - - printf(_("Join to '%s' is OK\n"), c->opt_target_workgroup); - return 0; -} -- 1.9.3 From a0474baa59c0991c2b2d8e3f425c9a6845162f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 3 Feb 2009 20:21:05 +0100 Subject: [PATCH 041/249] s3-net: use libnetjoin for "net rpc join" newstyle. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 3e4ded48bbeacdcd128f3c667cbdd12a3efca312) --- source3/utils/net_proto.h | 8 +--- source3/utils/net_rpc.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ source3/wscript_build | 2 +- 3 files changed, 108 insertions(+), 8 deletions(-) diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index d791708..1809ba9 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -146,6 +146,7 @@ int run_rpc_command(struct net_context *c, const char **argv); int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv); int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); +int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); int net_rpc_join(struct net_context *c, int argc, const char **argv); NTSTATUS rpc_info_internals(struct net_context *c, const struct dom_sid *domain_sid, @@ -200,13 +201,6 @@ int net_rpc(struct net_context *c, int argc, const char **argv); int net_rpc_audit(struct net_context *c, int argc, const char **argv); -/* The following definitions come from utils/net_rpc_join.c */ - -NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, - const char *server, - const struct sockaddr_storage *server_ss); -int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); - /* The following definitions come from utils/net_rpc_printer.c */ NTSTATUS net_copy_fileattr(struct net_context *c, diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 592be44..6358460 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -504,6 +504,112 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) } /** + * Join a domain using the administrator username and password + * + * @param argc Standard main() style argc + * @param argc Standard main() style argv. Initial components are already + * stripped. Currently not used. + * @return A shell status integer (0 for success) + * + **/ + +int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) +{ + struct libnet_JoinCtx *r = NULL; + TALLOC_CTX *mem_ctx; + WERROR werr; + const char *domain = lp_workgroup(); /* FIXME */ + bool modify_config = lp_config_backend_is_registry(); + enum netr_SchannelType sec_chan_type; + + if (c->display_usage) { + d_printf("Usage:\n" + "net rpc join\n" + " Join a domain the new way\n"); + return 0; + } + + mem_ctx = talloc_init("net_rpc_join_newstyle"); + if (!mem_ctx) { + return -1; + } + + werr = libnet_init_JoinCtx(mem_ctx, &r); + if (!W_ERROR_IS_OK(werr)) { + goto fail; + } + + /* + check what type of join - if the user want's to join as + a BDC, the server must agree that we are a BDC. + */ + if (argc >= 0) { + sec_chan_type = get_sec_channel_type(argv[0]); + } else { + sec_chan_type = get_sec_channel_type(NULL); + } + + if (!c->msg_ctx) { + d_fprintf(stderr, _("Could not initialise message context. " + "Try running as root\n")); + werr = WERR_ACCESS_DENIED; + goto fail; + } + + r->in.msg_ctx = c->msg_ctx; + r->in.domain_name = domain; + r->in.secure_channel_type = sec_chan_type; + r->in.dc_name = c->opt_host; + r->in.admin_account = c->opt_user_name; + r->in.admin_password = net_prompt_pass(c, c->opt_user_name); + r->in.debug = true; + r->in.use_kerberos = c->opt_kerberos; + r->in.modify_config = modify_config; + r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | + WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE | + WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; + + werr = libnet_Join(mem_ctx, r); + if (!W_ERROR_IS_OK(werr)) { + goto fail; + } + + /* Check the short name of the domain */ + + if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) { + d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE()); + d_printf("domain name obtained from the server.\n"); + d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name); + d_printf("You should set \"workgroup = %s\" in %s.\n", + r->out.netbios_domain_name, get_dyn_CONFIGFILE()); + } + + d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name); + + if (r->out.dns_domain_name) { + d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name, + r->out.dns_domain_name); + } else { + d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name, + r->out.netbios_domain_name); + } + + TALLOC_FREE(mem_ctx); + + return 0; + +fail: + /* issue an overall failure message at the end. */ + d_printf("Failed to join domain: %s\n", + r && r->out.error_string ? r->out.error_string : + get_friendly_werror_msg(werr)); + + TALLOC_FREE(mem_ctx); + + return -1; +} + +/** * 'net rpc join' entrypoint. * @param argc Standard main() style argc. * @param argv Standard main() style argv. Initial components are already diff --git a/source3/wscript_build b/source3/wscript_build index 9461b05..0bf84e2 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -507,7 +507,7 @@ LIBNET_SAMSYNC_SRC = '''libnet/libnet_samsync.c NET_SRC1 = '''utils/net.c utils/net_ads.c utils/net_help.c utils/net_rap.c utils/net_rpc.c utils/net_rpc_samsync.c - utils/net_rpc_join.c utils/net_time.c utils/net_lookup.c + utils/net_time.c utils/net_lookup.c utils/net_cache.c utils/net_groupmap.c utils/net_idmap.c utils/net_idmap_check.c utils/interact.c -- 1.9.3 From b2aad96d2ffd5545c250cce605dfdb7f0852806c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 15 Jul 2013 13:28:34 +0200 Subject: [PATCH 042/249] s3-net: avoid confusing output in net_rpc_oldjoin() if NET_FLAGS_EXPECT_FALLBACK is passed "net rpc join" tries net_rpc_oldjoin() first and falls back to net_rpc_join_newstyle(). We should not print the join failed if just net_rpc_oldjoin() failed. Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 05d9b4165af9e7f03d3fbeb64db4fc305fcec4df) --- source3/utils/net.h | 1 + source3/utils/net_proto.h | 1 - source3/utils/net_rpc.c | 15 +++++++++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/source3/utils/net.h b/source3/utils/net.h index 2056d89..e97734a 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -182,6 +182,7 @@ enum netdom_domain_t { ND_TYPE_NT4, ND_TYPE_AD }; #define NET_FLAGS_SIGN 0x00000040 /* sign RPC connection */ #define NET_FLAGS_SEAL 0x00000080 /* seal RPC connection */ #define NET_FLAGS_TCP 0x00000100 /* use ncacn_ip_tcp */ +#define NET_FLAGS_EXPECT_FALLBACK 0x00000200 /* the caller will fallback */ /* net share operation modes */ #define NET_MODE_SHARE_MIGRATE 1 diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index 1809ba9..25e9db2 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -146,7 +146,6 @@ int run_rpc_command(struct net_context *c, const char **argv); int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv); int net_rpc_testjoin(struct net_context *c, int argc, const char **argv); -int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv); int net_rpc_join(struct net_context *c, int argc, const char **argv); NTSTATUS rpc_info_internals(struct net_context *c, const struct dom_sid *domain_sid, diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 6358460..dff8801 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -427,11 +427,16 @@ static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) return 0; fail: + if (c->opt_flags & NET_FLAGS_EXPECT_FALLBACK) { + goto cleanup; + } + /* issue an overall failure message at the end. */ d_fprintf(stderr, _("Failed to join domain: %s\n"), r && r->out.error_string ? r->out.error_string : get_friendly_werror_msg(werr)); +cleanup: TALLOC_FREE(mem_ctx); return -1; @@ -513,7 +518,7 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) * **/ -int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) +static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) { struct libnet_JoinCtx *r = NULL; TALLOC_CTX *mem_ctx; @@ -623,6 +628,8 @@ fail: int net_rpc_join(struct net_context *c, int argc, const char **argv) { + int ret; + if (c->display_usage) { d_printf("%s\n%s", _("Usage:"), @@ -650,8 +657,12 @@ int net_rpc_join(struct net_context *c, int argc, const char **argv) return -1; } - if ((net_rpc_oldjoin(c, argc, argv) == 0)) + c->opt_flags |= NET_FLAGS_EXPECT_FALLBACK; + ret = net_rpc_oldjoin(c, argc, argv); + c->opt_flags &= ~NET_FLAGS_EXPECT_FALLBACK; + if (ret == 0) { return 0; + } return net_rpc_join_newstyle(c, argc, argv); } -- 1.9.3 From 8e8a2602d1c793f9a46e5219dea91a46e34d24ca Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 16 Jul 2013 10:07:30 +0200 Subject: [PATCH 043/249] s4:librpc: fix netlogon connections against servers without AES support LogonGetCapabilities() only works on the credential chain if the server supports AES, so we need to work on a temporary copy until we know the server replied a valid return authenticator. Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 34fa7946993506fde2c6b30e4a41bea27390a814) --- source4/librpc/rpc/dcerpc_schannel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 1480486..130ebeb 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -385,6 +385,7 @@ struct auth_schannel_state { struct loadparm_context *lp_ctx; uint8_t auth_level; struct netlogon_creds_CredentialState *creds_state; + struct netlogon_creds_CredentialState save_creds_state; struct netr_Authenticator auth; struct netr_Authenticator return_auth; union netr_Capabilities capabilities; @@ -449,7 +450,8 @@ static void continue_bind_auth(struct composite_context *ctx) s->creds_state = cli_credentials_get_netlogon_creds(s->credentials); if (composite_nomem(s->creds_state, c)) return; - netlogon_creds_client_authenticator(s->creds_state, &s->auth); + s->save_creds_state = *s->creds_state; + netlogon_creds_client_authenticator(&s->save_creds_state, &s->auth); s->c.in.server_name = talloc_asprintf(c, "\\\\%s", @@ -519,12 +521,14 @@ static void continue_get_capabilities(struct tevent_req *subreq) } /* verify credentials */ - if (!netlogon_creds_client_check(s->creds_state, + if (!netlogon_creds_client_check(&s->save_creds_state, &s->c.out.return_authenticator->cred)) { composite_error(c, NT_STATUS_UNSUCCESSFUL); return; } + *s->creds_state = s->save_creds_state; + if (!NT_STATUS_IS_OK(s->c.out.result)) { composite_error(c, s->c.out.result); return; -- 1.9.3 From 300fb415d5a6a60702b0c8464e0e76cf0e11fdeb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Mar 2013 15:07:10 +0100 Subject: [PATCH 044/249] s3:rpcclient: use talloc_stackframe() in do_cmd() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit d54c908ff5bef774f5cca038741558089ff6baeb) --- source3/rpcclient/rpcclient.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index c23ff2d..9bf296e 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -678,7 +678,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, /* Create mem_ctx */ - if (!(mem_ctx = talloc_init("do_cmd"))) { + if (!(mem_ctx = talloc_stackframe())) { DEBUG(0, ("talloc_init() failed\n")); return NT_STATUS_NO_MEMORY; } @@ -745,12 +745,14 @@ static NTSTATUS do_cmd(struct cli_state *cli, "auth type %u\n", cmd_entry->table->name, pipe_default_auth_type )); + talloc_free(mem_ctx); return NT_STATUS_UNSUCCESSFUL; } if (!NT_STATUS_IS_OK(ntresult)) { DEBUG(0, ("Could not initialise %s. Error was %s\n", cmd_entry->table->name, nt_errstr(ntresult) )); + talloc_free(mem_ctx); return ntresult; } @@ -765,6 +767,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, trust_password, &machine_account, &sec_channel_type)) { + talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -780,6 +783,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, if (!NT_STATUS_IS_OK(ntresult)) { DEBUG(0, ("Could not initialise credentials for %s.\n", cmd_entry->table->name)); + talloc_free(mem_ctx); return ntresult; } } @@ -803,7 +807,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, /* Cleanup */ - talloc_destroy(mem_ctx); + talloc_free(mem_ctx); return ntresult; } -- 1.9.3 From 95972ec54aafcf8a66e0164cd1fb478b6f4c58f6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 24 Apr 2013 12:36:04 +0200 Subject: [PATCH 045/249] libcli/auth: make netlogon_creds_crypt_samlogon_validation more robust Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 39fedd27182d9e1985418ea79b86aef69999dd57) --- libcli/auth/credentials.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index fb77ede..5c8b25b 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -493,8 +493,12 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede bool encrypt) { static const char zeros[16]; - struct netr_SamBaseInfo *base = NULL; + + if (validation == NULL) { + return; + } + switch (validation_level) { case 2: if (validation->sam2) { -- 1.9.3 From ac092a319c388cc2577bcbd87e16522ba37dc2d0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 14 Jun 2013 09:47:50 +0200 Subject: [PATCH 046/249] libcli/auth: fix shadowed declaration in netlogon_creds_crypt_samlogon_validation() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 291f6a1e031dc9db7d03b3ca924c4309b313cae5) --- libcli/auth/credentials.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 5c8b25b..2e9c87e 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -490,7 +490,7 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, union netr_Validation *validation, - bool encrypt) + bool do_encrypt) { static const char zeros[16]; struct netr_SamBaseInfo *base = NULL; @@ -531,7 +531,7 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */ if (memcmp(base->key.key, zeros, sizeof(base->key.key)) != 0) { - if (encrypt) { + if (do_encrypt) { netlogon_creds_aes_encrypt(creds, base->key.key, sizeof(base->key.key)); @@ -544,7 +544,7 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede if (memcmp(base->LMSessKey.key, zeros, sizeof(base->LMSessKey.key)) != 0) { - if (encrypt) { + if (do_encrypt) { netlogon_creds_aes_encrypt(creds, base->LMSessKey.key, sizeof(base->LMSessKey.key)); @@ -574,7 +574,7 @@ static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_Crede /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */ if (memcmp(base->LMSessKey.key, zeros, sizeof(base->LMSessKey.key)) != 0) { - if (encrypt) { + if (do_encrypt) { netlogon_creds_des_encrypt_LMKey(creds, &base->LMSessKey); } else { -- 1.9.3 From c535bfb9ead2175ae68b9d18a1692218a0fcf800 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 17:01:00 +0200 Subject: [PATCH 047/249] libcli/auth: add netlogon_creds_[de|en]crypt_samlogon_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit c7319fce604d5f89a89094b6b18ef459a347aef8) --- libcli/auth/credentials.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++ libcli/auth/proto.h | 6 +++ 2 files changed, 124 insertions(+) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 2e9c87e..78a8d7a 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -601,6 +601,124 @@ void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_Credential validation, true); } +static void netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, + enum netr_LogonInfoClass level, + union netr_LogonLevel *logon, + bool encrypt) +{ + static const char zeros[16]; + + if (logon == NULL) { + return; + } + + switch (level) { + case NetlogonInteractiveInformation: + case NetlogonInteractiveTransitiveInformation: + case NetlogonServiceInformation: + case NetlogonServiceTransitiveInformation: + if (logon->password == NULL) { + return; + } + + if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + uint8_t *h; + + h = logon->password->lmpassword.hash; + if (memcmp(h, zeros, 16) != 0) { + if (encrypt) { + netlogon_creds_aes_encrypt(creds, h, 16); + } else { + netlogon_creds_aes_decrypt(creds, h, 16); + } + } + + h = logon->password->ntpassword.hash; + if (memcmp(h, zeros, 16) != 0) { + if (encrypt) { + netlogon_creds_aes_encrypt(creds, h, 16); + } else { + netlogon_creds_aes_decrypt(creds, h, 16); + } + } + } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + uint8_t *h; + + h = logon->password->lmpassword.hash; + if (memcmp(h, zeros, 16) != 0) { + netlogon_creds_arcfour_crypt(creds, h, 16); + } + + h = logon->password->ntpassword.hash; + if (memcmp(h, zeros, 16) != 0) { + netlogon_creds_arcfour_crypt(creds, h, 16); + } + } else { + struct samr_Password *p; + + p = &logon->password->lmpassword; + if (memcmp(p->hash, zeros, 16) != 0) { + if (encrypt) { + netlogon_creds_des_encrypt(creds, p); + } else { + netlogon_creds_des_decrypt(creds, p); + } + } + p = &logon->password->ntpassword; + if (memcmp(p->hash, zeros, 16) != 0) { + if (encrypt) { + netlogon_creds_des_encrypt(creds, p); + } else { + netlogon_creds_des_decrypt(creds, p); + } + } + } + break; + + case NetlogonNetworkInformation: + case NetlogonNetworkTransitiveInformation: + break; + + case NetlogonGenericInformation: + if (logon->generic == NULL) { + return; + } + + if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + if (encrypt) { + netlogon_creds_aes_encrypt(creds, + logon->generic->data, + logon->generic->length); + } else { + netlogon_creds_aes_decrypt(creds, + logon->generic->data, + logon->generic->length); + } + } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + netlogon_creds_arcfour_crypt(creds, + logon->generic->data, + logon->generic->length); + } else { + /* Using DES to verify kerberos tickets makes no sense */ + } + break; + } +} + +void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, + enum netr_LogonInfoClass level, + union netr_LogonLevel *logon) +{ + netlogon_creds_crypt_samlogon_logon(creds, level, logon, false); +} + +void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, + enum netr_LogonInfoClass level, + union netr_LogonLevel *logon) +{ + netlogon_creds_crypt_samlogon_logon(creds, level, logon, true); +} + /* copy a netlogon_creds_CredentialState struct */ diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 6bc18d7..110e039 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -64,6 +64,12 @@ void netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_Credential void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, uint16_t validation_level, union netr_Validation *validation); +void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, + enum netr_LogonInfoClass level, + union netr_LogonLevel *logon); +void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, + enum netr_LogonInfoClass level, + union netr_LogonLevel *logon); /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/session.c */ -- 1.9.3 From d4f36f187d7c87c8daae3f94cdba52225faa19b8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 24 Apr 2013 12:53:27 +0200 Subject: [PATCH 048/249] libcli/auth: add netlogon_creds_shallow_copy_logon() This can be used before netlogon_creds_encrypt_samlogon_logon() in order to keep the provided buffers unchanged. Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 2ea749a1a43a6539b01d36dbe0402a99619444e1) --- libcli/auth/credentials.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ libcli/auth/proto.h | 3 ++ 2 files changed, 76 insertions(+) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 78a8d7a..1f664d3 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -719,6 +719,79 @@ void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState netlogon_creds_crypt_samlogon_logon(creds, level, logon, true); } +union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, + enum netr_LogonInfoClass level, + const union netr_LogonLevel *in) +{ + union netr_LogonLevel *out; + + if (in == NULL) { + return NULL; + } + + out = talloc(mem_ctx, union netr_LogonLevel); + if (out == NULL) { + return NULL; + } + + *out = *in; + + switch (level) { + case NetlogonInteractiveInformation: + case NetlogonInteractiveTransitiveInformation: + case NetlogonServiceInformation: + case NetlogonServiceTransitiveInformation: + if (in->password == NULL) { + return out; + } + + out->password = talloc(out, struct netr_PasswordInfo); + if (out->password == NULL) { + talloc_free(out); + return NULL; + } + *out->password = *in->password; + + return out; + + case NetlogonNetworkInformation: + case NetlogonNetworkTransitiveInformation: + break; + + case NetlogonGenericInformation: + if (in->generic == NULL) { + return out; + } + + out->generic = talloc(out, struct netr_GenericInfo); + if (out->generic == NULL) { + talloc_free(out); + return NULL; + } + *out->generic = *in->generic; + + if (in->generic->data == NULL) { + return out; + } + + if (in->generic->length == 0) { + return out; + } + + out->generic->data = talloc_memdup(out->generic, + in->generic->data, + in->generic->length); + if (out->generic->data == NULL) { + talloc_free(out); + return NULL; + } + + return out; + } + + return out; +} + /* copy a netlogon_creds_CredentialState struct */ diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 110e039..0c319d3 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -70,6 +70,9 @@ void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, enum netr_LogonInfoClass level, union netr_LogonLevel *logon); +union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, + enum netr_LogonInfoClass level, + const union netr_LogonLevel *in); /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/session.c */ -- 1.9.3 From 8cf11ba846fc31ce26020aabcf463817b56580a7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 24 Apr 2013 16:00:18 +0200 Subject: [PATCH 049/249] s4:netlogon: make use of netlogon_creds_decrypt_samlogon_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 9d548318da11247ffe8acf505cdb5299090c16f0) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 28 ++++++--------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 70239a4..c41cd02 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -712,29 +712,15 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info); NT_STATUS_HAVE_NO_MEMORY(user_info); + netlogon_creds_decrypt_samlogon_logon(creds, + r->in.logon_level, + r->in.logon); + switch (r->in.logon_level) { case NetlogonInteractiveInformation: case NetlogonServiceInformation: case NetlogonInteractiveTransitiveInformation: case NetlogonServiceTransitiveInformation: - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_decrypt(creds, - r->in.logon->password->lmpassword.hash, - sizeof(r->in.logon->password->lmpassword.hash)); - netlogon_creds_aes_decrypt(creds, - r->in.logon->password->ntpassword.hash, - sizeof(r->in.logon->password->ntpassword.hash)); - } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(creds, - r->in.logon->password->lmpassword.hash, - sizeof(r->in.logon->password->lmpassword.hash)); - netlogon_creds_arcfour_crypt(creds, - r->in.logon->password->ntpassword.hash, - sizeof(r->in.logon->password->ntpassword.hash)); - } else { - netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword); - netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword); - } /* TODO: we need to deny anonymous access here */ nt_status = auth_context_create(mem_ctx, @@ -788,11 +774,9 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_cal case NetlogonGenericInformation: { if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_decrypt(creds, - r->in.logon->generic->data, r->in.logon->generic->length); + /* OK */ } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(creds, - r->in.logon->generic->data, r->in.logon->generic->length); + /* OK */ } else { /* Using DES to verify kerberos tickets makes no sense */ return NT_STATUS_INVALID_PARAMETER; -- 1.9.3 From 22bdc484af1b1a4ebd9451fd5cde4d3993dd6f0a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 24 Apr 2013 16:00:44 +0200 Subject: [PATCH 050/249] s3:netlogon: make use of netlogon_creds_decrypt_samlogon_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 7b3ddd1a0bb41fe84c115555113362044620e484) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 45 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index e5ca474..09857b6 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1467,6 +1467,15 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, struct auth_context *auth_context = NULL; const char *fn; +#ifdef DEBUG_PASSWORD + logon = netlogon_creds_shallow_copy_logon(p->mem_ctx, + r->in.logon_level, + r->in.logon); + if (logon == NULL) { + logon = r->in.logon; + } +#endif + switch (p->opnum) { case NDR_NETR_LOGONSAMLOGON: fn = "_netr_LogonSamLogon"; @@ -1547,6 +1556,10 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, status = NT_STATUS_OK; + netlogon_creds_decrypt_samlogon_logon(creds, + r->in.logon_level, + logon); + switch (r->in.logon_level) { case NetlogonNetworkInformation: case NetlogonNetworkTransitiveInformation: @@ -1592,32 +1605,16 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, uint8_t chal[8]; #ifdef DEBUG_PASSWORD - DEBUG(100,("lm owf password:")); - dump_data(100, logon->password->lmpassword.hash, 16); - - DEBUG(100,("nt owf password:")); - dump_data(100, logon->password->ntpassword.hash, 16); -#endif - if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_decrypt(creds, - logon->password->lmpassword.hash, - 16); - netlogon_creds_aes_decrypt(creds, - logon->password->ntpassword.hash, - 16); - } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(creds, - logon->password->lmpassword.hash, - 16); - netlogon_creds_arcfour_crypt(creds, - logon->password->ntpassword.hash, - 16); - } else { - netlogon_creds_des_decrypt(creds, &logon->password->lmpassword); - netlogon_creds_des_decrypt(creds, &logon->password->ntpassword); + if (logon != r->in.logon) { + DEBUG(100,("lm owf password:")); + dump_data(100, + r->in.logon->password->lmpassword.hash, 16); + + DEBUG(100,("nt owf password:")); + dump_data(100, + r->in.logon->password->ntpassword.hash, 16); } -#ifdef DEBUG_PASSWORD DEBUG(100,("decrypt of lm owf password:")); dump_data(100, logon->password->lmpassword.hash, 16); -- 1.9.3 From b25c7249bdca17d4b4720a2e8f8ba329c4105e94 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 18:27:57 +0200 Subject: [PATCH 051/249] s3:rpc_client: make rpccli_schannel_bind_data() static Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 6ce645e03c279cbb2ed8a94f033b8e0601b61ef4) --- source3/rpc_client/cli_pipe.c | 9 +++++---- source3/rpc_client/cli_pipe.h | 6 ------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 1fa8d91..66fa2d2 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2401,10 +2401,11 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, return status; } -NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, - enum dcerpc_AuthLevel auth_level, - struct netlogon_creds_CredentialState *creds, - struct pipe_auth_data **presult) +static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, + const char *domain, + enum dcerpc_AuthLevel auth_level, + struct netlogon_creds_CredentialState *creds, + struct pipe_auth_data **presult) { struct schannel_state *schannel_auth; struct pipe_auth_data *result; diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 6fcc587..8eb6040 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -58,12 +58,6 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx, NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx, struct pipe_auth_data **presult); -NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, - const char *domain, - enum dcerpc_AuthLevel auth_level, - struct netlogon_creds_CredentialState *creds, - struct pipe_auth_data **presult); - NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host, const struct sockaddr_storage *ss_addr, -- 1.9.3 From 9f56e42ba78ce4e1248f06a0cecfc97789aea260 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 18:29:31 +0200 Subject: [PATCH 052/249] s3:rpc_client: use the correct context for netlogon_creds_copy() in rpccli_schannel_bind_data() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 8a302fc353de8d373a0ec8544da4da6f305ec923) --- source3/rpc_client/cli_pipe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 66fa2d2..afe8030 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2431,7 +2431,10 @@ static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, schannel_auth->state = SCHANNEL_STATE_START; schannel_auth->initiator = true; - schannel_auth->creds = netlogon_creds_copy(result, creds); + schannel_auth->creds = netlogon_creds_copy(schannel_auth, creds); + if (schannel_auth->creds == NULL) { + goto fail; + } result->auth_ctx = schannel_auth; *presult = result; -- 1.9.3 From 08d78b16f0adf1d223f29d613a498878230522be Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 19:43:58 +0200 Subject: [PATCH 053/249] s3:rpc_client: rename same variables in cli_rpc_pipe_open_schannel_with_key() Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 94be8d63cd21fbb9e31bf7a92af82e19c596f94f) --- source3/rpc_client/cli_pipe.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index afe8030..ec804e7 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3032,32 +3032,32 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, enum dcerpc_AuthLevel auth_level, const char *domain, struct netlogon_creds_CredentialState **pdc, - struct rpc_pipe_client **presult) + struct rpc_pipe_client **_rpccli) { - struct rpc_pipe_client *result; - struct pipe_auth_data *auth; + struct rpc_pipe_client *rpccli; + struct pipe_auth_data *rpcauth; NTSTATUS status; - status = cli_rpc_pipe_open(cli, transport, table, &result); + status = cli_rpc_pipe_open(cli, transport, table, &rpccli); if (!NT_STATUS_IS_OK(status)) { return status; } - status = rpccli_schannel_bind_data(result, domain, auth_level, - *pdc, &auth); + status = rpccli_schannel_bind_data(rpccli, domain, auth_level, + *pdc, &rpcauth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpccli_schannel_bind_data returned %s\n", nt_errstr(status))); - TALLOC_FREE(result); + TALLOC_FREE(rpccli); return status; } - status = rpc_pipe_bind(result, auth); + status = rpc_pipe_bind(rpccli, rpcauth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: " "cli_rpc_pipe_bind failed with error %s\n", nt_errstr(status) )); - TALLOC_FREE(result); + TALLOC_FREE(rpccli); return status; } @@ -3065,10 +3065,10 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, * The credentials on a new netlogon pipe are the ones we are passed * in - copy them over */ - if (result->dc == NULL) { - result->dc = netlogon_creds_copy(result, *pdc); - if (result->dc == NULL) { - TALLOC_FREE(result); + if (rpccli->dc == NULL) { + rpccli->dc = netlogon_creds_copy(rpccli, *pdc); + if (rpccli->dc == NULL) { + TALLOC_FREE(rpccli); return NT_STATUS_NO_MEMORY; } } @@ -3076,9 +3076,9 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " "for domain %s and bound using schannel.\n", get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), - result->desthost, domain)); + rpccli->desthost, domain)); - *presult = result; + *_rpccli = rpccli; return NT_STATUS_OK; } -- 1.9.3 From 33991d3ea286fc5da1458ca64aa4fc004547ae04 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 20:26:54 +0200 Subject: [PATCH 054/249] s3:libsmb: remove unused cli_state->is_guestlogin Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 11e0be0e72cfc4bc65ba2b0ffd10cbae3ad69b2d) --- source3/include/client.h | 1 - source3/libsmb/cliconnect.c | 5 ----- 2 files changed, 6 deletions(-) diff --git a/source3/include/client.h b/source3/include/client.h index 3f92d6d..59fb104 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -72,7 +72,6 @@ struct cli_state { int timeout; /* in milliseconds. */ int initialised; int win95; - bool is_guestlogin; /* What the server offered. */ uint32_t server_posix_capabilities; /* What the client requested. */ diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 13e7704..81bc028 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -240,7 +240,6 @@ static void cli_session_setup_lanman2_done(struct tevent_req *subreq) p = bytes; cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); - cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); status = smb_bytes_talloc_string(cli, inhdr, @@ -448,7 +447,6 @@ static void cli_session_setup_guest_done(struct tevent_req *subreq) p = bytes; cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); - cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); status = smb_bytes_talloc_string(cli, inhdr, @@ -613,7 +611,6 @@ static void cli_session_setup_plain_done(struct tevent_req *subreq) p = bytes; cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); - cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); status = smb_bytes_talloc_string(cli, inhdr, @@ -930,7 +927,6 @@ static void cli_session_setup_nt1_done(struct tevent_req *subreq) p = bytes; cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); - cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); status = smb_bytes_talloc_string(cli, inhdr, @@ -1180,7 +1176,6 @@ static void cli_sesssetup_blob_done(struct tevent_req *subreq) state->inbuf = in; inhdr = in + NBT_HDR_SIZE; cli_state_set_uid(state->cli, SVAL(inhdr, HDR_UID)); - cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0); blob_length = SVAL(vwv+3, 0); if (blob_length > num_bytes) { -- 1.9.3 From 937a0f2fc020e12c21c10597a889275614603add Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Jun 2013 09:41:52 +0200 Subject: [PATCH 055/249] s3:auth_domain: try to use NETLOGON_NEG_SUPPORTS_AES Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit d82ab70579ff2bcb69f997068482b198f321d1ef) --- source3/auth/auth_domain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 54ee5a1..06078e2 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -133,7 +133,8 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); if (!lp_client_schannel()) { /* We need to set up a creds chain on an unauthenticated netlogon pipe. */ - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; enum netr_SchannelType sec_chan_type = 0; unsigned char machine_pwd[16]; const char *account_name; -- 1.9.3 From 981a88bb20cef572e5573ee2f18115a6e395fbf9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Jun 2013 09:41:52 +0200 Subject: [PATCH 056/249] s3:libnet_join: try to use NETLOGON_NEG_SUPPORTS_AES Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit beba32619a91977543f882432fd08acc9de78fd3) --- source3/libnet/libnet_join.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index d8ec235..c1eccda 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1194,7 +1194,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, const char *dc_name, const bool use_kerberos) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; struct cli_state *cli = NULL; struct rpc_pipe_client *pipe_hnd = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; -- 1.9.3 From 846a35f004850695ca7c9d4597cd8729bb7c99e3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Jun 2013 09:41:52 +0200 Subject: [PATCH 057/249] s3:rpc_client: try to use NETLOGON_NEG_SUPPORTS_AES Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 04600634b3e761d7c56f699fd4ba80b4cd2926a1) --- source3/rpc_client/cli_netlogon.c | 3 ++- source3/rpc_client/cli_pipe_schannel.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 3d6a3e1..5e8a2fc 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -610,7 +610,8 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, struct dcerpc_binding_handle *b = cli->binding_handle; if (!cli->dc) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; result = rpccli_netlogon_setup_creds(cli, cli->desthost, /* server name */ lp_workgroup(), /* domain */ diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index bc672ef..de745c0 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -136,7 +136,8 @@ NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, const char *password, struct rpc_pipe_client **presult) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; struct rpc_pipe_client *netlogon_pipe = NULL; struct rpc_pipe_client *result = NULL; NTSTATUS status; @@ -175,7 +176,8 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, const char *domain, struct rpc_pipe_client **presult) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; struct rpc_pipe_client *netlogon_pipe = NULL; struct rpc_pipe_client *result = NULL; NTSTATUS status; -- 1.9.3 From a56391bc8cbe1fa9142d0a20f4bf977538f27e67 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Jun 2013 09:41:52 +0200 Subject: [PATCH 058/249] s3:rpcclient: try to use NETLOGON_NEG_SUPPORTS_AES Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit e77a64f505fc43628e487e832033d0cd8ec4de8e) --- source3/rpcclient/cmd_netlogon.c | 3 ++- source3/rpcclient/rpcclient.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 01d6da4..d92434b 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -1120,7 +1120,8 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS result; const char *server_name = cli->desthost; - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; struct netr_Authenticator clnt_creds, srv_cred; struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; unsigned char trust_passwd_hash[16]; diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 9bf296e..cb7b70f 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -758,7 +758,8 @@ static NTSTATUS do_cmd(struct cli_state *cli, if (ndr_syntax_id_equal(&cmd_entry->table->syntax_id, &ndr_table_netlogon.syntax_id)) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | + NETLOGON_NEG_SUPPORTS_AES; enum netr_SchannelType sec_channel_type; uchar trust_password[16]; const char *machine_account; -- 1.9.3 From 06c4ff36efc63ef014c449602dc314ca4e7016bd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 19:57:09 +0200 Subject: [PATCH 059/249] s3:rpc_client: fix/add AES downgrade detection to rpc_pipe_bind_step_two_done() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 90e28c1825b2c48714d7b34fdb57d3878116d07e) --- source3/rpc_client/cli_pipe.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index ec804e7..c354a6f 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1828,8 +1828,7 @@ static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, talloc_tos()); TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { - if (state->cli->dc && state->cli->dc->negotiate_flags & - NETLOGON_NEG_SUPPORTS_AES) { + if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { DEBUG(5, ("AES is not supported and the error was %s\n", nt_errstr(status))); tevent_req_nterror(req, @@ -1880,9 +1879,6 @@ static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) return; } - TALLOC_FREE(state->cli->dc); - state->cli->dc = talloc_steal(state->cli, state->creds); - if (!NT_STATUS_IS_OK(state->r.out.result)) { DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", nt_errstr(state->r.out.result))); @@ -1890,18 +1886,17 @@ static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) return; } - if (state->creds->negotiate_flags != - state->r.out.capabilities->server_capabilities) { - DEBUG(0, ("The client capabilities don't match the server " - "capabilities: local[0x%08X] remote[0x%08X]\n", - state->creds->negotiate_flags, - state->capabilities.server_capabilities)); + if (!(state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { + DEBUG(0, ("netr_LogonGetCapabilities is supported by %s, " + "but AES was not negotiated - downgrade detected", + state->cli->desthost)); tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); return; } - /* TODO: Add downgrade dectection. */ + TALLOC_FREE(state->cli->dc); + state->cli->dc = talloc_move(state->cli, &state->creds); tevent_req_done(req); return; -- 1.9.3 From e6416b9fe5019c3ce1aa8ecf42d73125a049338f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 19:45:52 +0200 Subject: [PATCH 060/249] s3:rpc_client: use netlogon_creds_copy before rpc_pipe_bind Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit e9c8e3fb92143525f846523e446e2213e5b55d9d) --- source3/rpc_client/cli_pipe.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index c354a6f..eb172db 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3047,6 +3047,18 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return status; } + /* + * The credentials on a new netlogon pipe are the ones we are passed + * in - copy them over + * + * This may get overwritten... in rpc_pipe_bind()... + */ + rpccli->dc = netlogon_creds_copy(rpccli, *pdc); + if (rpccli->dc == NULL) { + TALLOC_FREE(rpccli); + return NT_STATUS_NO_MEMORY; + } + status = rpc_pipe_bind(rpccli, rpcauth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: " @@ -3056,18 +3068,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return status; } - /* - * The credentials on a new netlogon pipe are the ones we are passed - * in - copy them over - */ - if (rpccli->dc == NULL) { - rpccli->dc = netlogon_creds_copy(rpccli, *pdc); - if (rpccli->dc == NULL) { - TALLOC_FREE(rpccli); - return NT_STATUS_NO_MEMORY; - } - } - DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " "for domain %s and bound using schannel.\n", get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), -- 1.9.3 From 1836ea96ed7dd055278fd6cac3f69a06ea979ea2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 19:34:13 +0200 Subject: [PATCH 061/249] s3:rpc_client: add netr_LogonGetCapabilities to cli_rpc_pipe_open_schannel_with_key() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit eecb5bafba5b362d4fdf33d6a2a32e4ee56f30a4) --- source3/rpc_client/cli_pipe.c | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index eb172db..314eb92 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3032,6 +3032,11 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct rpc_pipe_client *rpccli; struct pipe_auth_data *rpcauth; NTSTATUS status; + NTSTATUS result; + struct netlogon_creds_CredentialState save_creds; + struct netr_Authenticator auth; + struct netr_Authenticator return_auth; + union netr_Capabilities capabilities; status = cli_rpc_pipe_open(cli, transport, table, &rpccli); if (!NT_STATUS_IS_OK(status)) { @@ -3068,6 +3073,102 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return status; } + if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) { + goto done; + } + + save_creds = *rpccli->dc; + ZERO_STRUCT(return_auth); + ZERO_STRUCT(capabilities); + + netlogon_creds_client_authenticator(&save_creds, &auth); + + status = dcerpc_netr_LogonGetCapabilities(rpccli->binding_handle, + talloc_tos(), + rpccli->srv_name_slash, + save_creds.computer_name, + &auth, &return_auth, + 1, &capabilities, + &result); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + DEBUG(5, ("AES was negotiated and the error was %s - " + "downgrade detected\n", + nt_errstr(status))); + TALLOC_FREE(rpccli); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + /* This is probably an old Samba Version */ + DEBUG(5, ("We are checking against an NT or old Samba - %s\n", + nt_errstr(status))); + goto done; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", + nt_errstr(status))); + TALLOC_FREE(rpccli); + return status; + } + + if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { + if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + /* This means AES isn't supported. */ + DEBUG(5, ("AES was negotiated and the result was %s - " + "downgrade detected\n", + nt_errstr(result))); + TALLOC_FREE(rpccli); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + /* This is probably an old Windows version */ + DEBUG(5, ("We are checking against an win2k3 or Samba - %s\n", + nt_errstr(result))); + goto done; + } + + /* + * We need to check the credential state here, cause win2k3 and earlier + * returns NT_STATUS_NOT_IMPLEMENTED + */ + if (!netlogon_creds_client_check(&save_creds, &return_auth.cred)) { + /* + * Server replied with bad credential. Fail. + */ + DEBUG(0,("cli_rpc_pipe_open_schannel_with_key: server %s " + "replied with bad credential\n", + rpccli->desthost)); + TALLOC_FREE(rpccli); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + *rpccli->dc = save_creds; + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", + nt_errstr(result))); + TALLOC_FREE(rpccli); + return result; + } + + if (!(save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { + /* This means AES isn't supported. */ + DEBUG(5, ("AES is not negotiated, but netr_LogonGetCapabilities " + "was OK - downgrade detected\n")); + TALLOC_FREE(rpccli); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + if (save_creds.negotiate_flags != capabilities.server_capabilities) { + DEBUG(0, ("The client capabilities don't match the server " + "capabilities: local[0x%08X] remote[0x%08X]\n", + save_creds.negotiate_flags, + capabilities.server_capabilities)); + TALLOC_FREE(rpccli); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + +done: DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " "for domain %s and bound using schannel.\n", get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), -- 1.9.3 From 675be19880c2ac4bca14d69592ce39bb66a34dec Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 18:30:36 +0200 Subject: [PATCH 062/249] s3:rpc_client: remove netr_LogonGetCapabilities check from rpc_pipe_bind* It's done in the caller now. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3302356226cca474f0afab9a129220241c16663f) --- source3/rpc_client/cli_pipe.c | 150 +----------------------------------------- 1 file changed, 1 insertion(+), 149 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 314eb92..cba055a 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1568,15 +1568,9 @@ struct rpc_pipe_bind_state { DATA_BLOB rpc_out; bool auth3; uint32_t rpc_call_id; - struct netr_Authenticator auth; - struct netr_Authenticator return_auth; - struct netlogon_creds_CredentialState *creds; - union netr_Capabilities capabilities; - struct netr_LogonGetCapabilities r; }; static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq); -static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req); static NTSTATUS rpc_bind_next_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, DATA_BLOB *credentials); @@ -1679,14 +1673,11 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case DCERPC_AUTH_TYPE_NONE: case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: + case DCERPC_AUTH_TYPE_SCHANNEL: /* Bind complete. */ tevent_req_done(req); return; - case DCERPC_AUTH_TYPE_SCHANNEL: - rpc_pipe_bind_step_two_trigger(req); - return; - case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_KRB5: @@ -1763,145 +1754,6 @@ err_out: tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); } -static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq); - -static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req) -{ - struct rpc_pipe_bind_state *state = - tevent_req_data(req, - struct rpc_pipe_bind_state); - struct dcerpc_binding_handle *b = state->cli->binding_handle; - struct schannel_state *schannel_auth = - talloc_get_type_abort(state->cli->auth->auth_ctx, - struct schannel_state); - struct tevent_req *subreq; - - if (schannel_auth == NULL || - !ndr_syntax_id_equal(&state->cli->abstract_syntax, - &ndr_table_netlogon.syntax_id)) { - tevent_req_done(req); - return; - } - - ZERO_STRUCT(state->return_auth); - - state->creds = netlogon_creds_copy(state, schannel_auth->creds); - if (state->creds == NULL) { - tevent_req_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - netlogon_creds_client_authenticator(state->creds, &state->auth); - - state->r.in.server_name = state->cli->srv_name_slash; - state->r.in.computer_name = state->creds->computer_name; - state->r.in.credential = &state->auth; - state->r.in.query_level = 1; - state->r.in.return_authenticator = &state->return_auth; - - state->r.out.capabilities = &state->capabilities; - state->r.out.return_authenticator = &state->return_auth; - - subreq = dcerpc_netr_LogonGetCapabilities_r_send(talloc_tos(), - state->ev, - b, - &state->r); - if (subreq == NULL) { - tevent_req_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - tevent_req_set_callback(subreq, rpc_pipe_bind_step_two_done, req); - return; -} - -static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq) -{ - struct tevent_req *req = - tevent_req_callback_data(subreq, - struct tevent_req); - struct rpc_pipe_bind_state *state = - tevent_req_data(req, - struct rpc_pipe_bind_state); - NTSTATUS status; - - status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, talloc_tos()); - TALLOC_FREE(subreq); - if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { - if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - DEBUG(5, ("AES is not supported and the error was %s\n", - nt_errstr(status))); - tevent_req_nterror(req, - NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - /* This is probably NT */ - DEBUG(5, ("We are checking against an NT - %s\n", - nt_errstr(status))); - tevent_req_done(req); - return; - } else if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", - nt_errstr(status))); - tevent_req_nterror(req, status); - return; - } - - if (NT_STATUS_EQUAL(state->r.out.result, NT_STATUS_NOT_IMPLEMENTED)) { - if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - /* This means AES isn't supported. */ - DEBUG(5, ("AES is not supported and the error was %s\n", - nt_errstr(state->r.out.result))); - tevent_req_nterror(req, - NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - /* This is probably an old Samba version */ - DEBUG(5, ("We are checking against an old Samba version - %s\n", - nt_errstr(state->r.out.result))); - tevent_req_done(req); - return; - } - - /* We need to check the credential state here, cause win2k3 and earlier - * returns NT_STATUS_NOT_IMPLEMENTED */ - if (!netlogon_creds_client_check(state->creds, - &state->r.out.return_authenticator->cred)) { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("rpc_pipe_bind_step_two_done: server %s " - "replied with bad credential\n", - state->cli->desthost)); - tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); - return; - } - - if (!NT_STATUS_IS_OK(state->r.out.result)) { - DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n", - nt_errstr(state->r.out.result))); - tevent_req_nterror(req, state->r.out.result); - return; - } - - if (!(state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { - DEBUG(0, ("netr_LogonGetCapabilities is supported by %s, " - "but AES was not negotiated - downgrade detected", - state->cli->desthost)); - tevent_req_nterror(req, - NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - TALLOC_FREE(state->cli->dc); - state->cli->dc = talloc_move(state->cli, &state->creds); - - tevent_req_done(req); - return; -} - static NTSTATUS rpc_bind_next_send(struct tevent_req *req, struct rpc_pipe_bind_state *state, DATA_BLOB *auth_token) -- 1.9.3 From f9b4e38b8458ec905b5f78e402f21f23c4a967e1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 25 Apr 2013 19:33:28 +0200 Subject: [PATCH 063/249] s3:rpc_client: remove unused cli_rpc_pipe_open_ntlmssp_auth_schannel() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 04938cbeecc777f7b799a11f1ca0461b351d968a) --- source3/rpc_client/cli_pipe.h | 9 ---- source3/rpc_client/cli_pipe_schannel.c | 80 ---------------------------------- 2 files changed, 89 deletions(-) diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 8eb6040..ab99373 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -109,15 +109,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct netlogon_creds_CredentialState **pdc, struct rpc_pipe_client **presult); -NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, - const struct ndr_interface_table *table, - enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, - const char *domain, - const char *username, - const char *password, - struct rpc_pipe_client **presult); - NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, const struct ndr_interface_table *table, enum dcerpc_transport_t transport, diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index de745c0..aaae44b 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -86,86 +86,6 @@ static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon /**************************************************************************** Open a named pipe to an SMB server and bind using schannel (bind type 68). - Fetch the session key ourselves using a temporary netlogon pipe. This - version uses an ntlmssp auth bound netlogon pipe to get the key. - ****************************************************************************/ - -static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli, - const char *domain, - const char *username, - const char *password, - uint32 *pneg_flags, - struct rpc_pipe_client **presult) -{ - struct rpc_pipe_client *netlogon_pipe = NULL; - NTSTATUS status; - - status = cli_rpc_pipe_open_spnego( - cli, &ndr_table_netlogon, NCACN_NP, - GENSEC_OID_NTLMSSP, - DCERPC_AUTH_LEVEL_PRIVACY, - smbXcli_conn_remote_name(cli->conn), - domain, username, password, &netlogon_pipe); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = get_schannel_session_key_common(netlogon_pipe, cli, domain, - pneg_flags); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(netlogon_pipe); - return status; - } - - *presult = netlogon_pipe; - return NT_STATUS_OK; -} - -/**************************************************************************** - Open a named pipe to an SMB server and bind using schannel (bind type 68). - Fetch the session key ourselves using a temporary netlogon pipe. This version - uses an ntlmssp bind to get the session key. - ****************************************************************************/ - -NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli, - const struct ndr_interface_table *table, - enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, - const char *domain, - const char *username, - const char *password, - struct rpc_pipe_client **presult) -{ - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | - NETLOGON_NEG_SUPPORTS_AES; - struct rpc_pipe_client *netlogon_pipe = NULL; - struct rpc_pipe_client *result = NULL; - NTSTATUS status; - - status = get_schannel_session_key_auth_ntlmssp( - cli, domain, username, password, &neg_flags, &netlogon_pipe); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session " - "key from server %s for domain %s.\n", - smbXcli_conn_remote_name(cli->conn), domain )); - return status; - } - - status = cli_rpc_pipe_open_schannel_with_key( - cli, table, transport, auth_level, domain, &netlogon_pipe->dc, - &result); - - /* Now we've bound using the session key we can close the netlog pipe. */ - TALLOC_FREE(netlogon_pipe); - - if (NT_STATUS_IS_OK(status)) { - *presult = result; - } - return status; -} - -/**************************************************************************** - Open a named pipe to an SMB server and bind using schannel (bind type 68). Fetch the session key ourselves using a temporary netlogon pipe. ****************************************************************************/ -- 1.9.3 From 35d07a4d7ca15e4cf22f7cc96d6958c9856dc0a0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Aug 2013 11:26:13 +0200 Subject: [PATCH 064/249] auth/gensec: first check GENSEC_FEATURE_SESSION_KEY before returning NOT_IMPLEMENTED Preferr NT_STATUS_NO_USER_SESSION_KEY as return value of gensec_session_key(). Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 45c74c8084d2db14fef6a79cd98068be2ab73f30) --- auth/gensec/gensec.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c index ea62861..9a8f0ef 100644 --- a/auth/gensec/gensec.c +++ b/auth/gensec/gensec.c @@ -155,13 +155,14 @@ _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, DATA_BLOB *session_key) { - if (!gensec_security->ops->session_key) { - return NT_STATUS_NOT_IMPLEMENTED; - } if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) { return NT_STATUS_NO_USER_SESSION_KEY; } + if (!gensec_security->ops->session_key) { + return NT_STATUS_NOT_IMPLEMENTED; + } + return gensec_security->ops->session_key(gensec_security, mem_ctx, session_key); } -- 1.9.3 From 6eda030bd26347cef3fb670b0876956c97c00bfa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Aug 2013 11:43:58 +0200 Subject: [PATCH 065/249] auth/gensec: add gensec_security_by_auth_type() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 59b09564a7edac8dc241269587146342244ce58b) --- auth/gensec/gensec.h | 3 +++ auth/gensec/gensec_start.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h index 396a16d..c080861 100644 --- a/auth/gensec/gensec.h +++ b/auth/gensec/gensec.h @@ -268,6 +268,9 @@ const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security const char *oid_string); const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security, const char *sasl_name); +const struct gensec_security_ops *gensec_security_by_auth_type( + struct gensec_security *gensec_security, + uint32_t auth_type); struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx); const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index e46f0ee..c2cfa1c 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -246,6 +246,32 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name( return NULL; } +_PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type( + struct gensec_security *gensec_security, + uint32_t auth_type) +{ + int i; + struct gensec_security_ops **backends; + const struct gensec_security_ops *backend; + TALLOC_CTX *mem_ctx = talloc_new(gensec_security); + if (!mem_ctx) { + return NULL; + } + backends = gensec_security_mechs(gensec_security, mem_ctx); + for (i=0; backends && backends[i]; i++) { + if (!gensec_security_ops_enabled(backends[i], gensec_security)) + continue; + if (backends[i]->auth_type == auth_type) { + backend = backends[i]; + talloc_free(mem_ctx); + return backend; + } + } + talloc_free(mem_ctx); + + return NULL; +} + static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security, const char *name) { -- 1.9.3 From f4e1506ed3a032d38605207f592cbc4ece93a414 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 24 Apr 2013 12:33:28 +0200 Subject: [PATCH 066/249] libcli/auth: maintain the sequence number for the NETLOGON SSP as 64bit See [MS-NPRC] 3.3.4.2 The Netlogon Signature Token. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 9f2e81ae02549369db49c05edf7071612a03a8b8) --- libcli/auth/schannel.h | 2 +- libcli/auth/schannel_sign.c | 17 +++++++++++++---- source3/librpc/rpc/dcerpc_helpers.c | 4 ++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/libcli/auth/schannel.h b/libcli/auth/schannel.h index bfccd95..271b5bb 100644 --- a/libcli/auth/schannel.h +++ b/libcli/auth/schannel.h @@ -30,7 +30,7 @@ enum schannel_position { struct schannel_state { enum schannel_position state; - uint32_t seq_num; + uint64_t seq_num; bool initiator; struct netlogon_creds_CredentialState *creds; }; diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c index 1871da2..6e5d454 100644 --- a/libcli/auth/schannel_sign.c +++ b/libcli/auth/schannel_sign.c @@ -24,6 +24,17 @@ #include "../libcli/auth/schannel.h" #include "../lib/crypto/crypto.h" +#define SETUP_SEQNUM(state, buf, initiator) do { \ + uint8_t *_buf = buf; \ + uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ + uint32_t _seq_num_high = (state)->seq_num >> 32; \ + if (initiator) { \ + _seq_num_high |= 0x80000000; \ + } \ + RSIVAL(_buf, 0, _seq_num_low); \ + RSIVAL(_buf, 4, _seq_num_high); \ +} while(0) + static void netsec_offset_and_sizes(struct schannel_state *state, bool do_seal, uint32_t *_min_sig_size, @@ -255,8 +266,7 @@ NTSTATUS netsec_incoming_packet(struct schannel_state *state, confounder = NULL; } - RSIVAL(seq_num, 0, state->seq_num); - SIVAL(seq_num, 4, state->initiator?0:0x80); + SETUP_SEQNUM(state, seq_num, !state->initiator); if (do_unseal) { netsec_do_seal(state, seq_num, @@ -325,8 +335,7 @@ NTSTATUS netsec_outgoing_packet(struct schannel_state *state, &checksum_length, &confounder_ofs); - RSIVAL(seq_num, 0, state->seq_num); - SIVAL(seq_num, 4, state->initiator?0x80:0); + SETUP_SEQNUM(state, seq_num, state->initiator); if (do_seal) { confounder = _confounder; diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index a55e419..0095990 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -462,8 +462,8 @@ static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas, return NT_STATUS_INVALID_PARAMETER; } - DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n", - sas->seq_num)); + DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%llu\n", + (unsigned long long)sas->seq_num)); switch (auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: -- 1.9.3 From f99afc1924dbb267e696bbdf26db606a8c77f093 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 12:53:42 +0200 Subject: [PATCH 067/249] libcli/auth: add netsec_create_state() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 33215398f32c76f4b8ada7b547c6d0741cb2ac16) --- libcli/auth/schannel_proto.h | 3 +++ libcli/auth/schannel_sign.c | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libcli/auth/schannel_proto.h b/libcli/auth/schannel_proto.h index 0414218..da76559 100644 --- a/libcli/auth/schannel_proto.h +++ b/libcli/auth/schannel_proto.h @@ -28,6 +28,9 @@ struct schannel_state; struct db_context *open_schannel_session_store(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx); +struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds, + bool initiator); NTSTATUS netsec_incoming_packet(struct schannel_state *state, bool do_unseal, uint8_t *data, size_t length, diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c index 6e5d454..518a6a9 100644 --- a/libcli/auth/schannel_sign.c +++ b/libcli/auth/schannel_sign.c @@ -35,6 +35,29 @@ RSIVAL(_buf, 4, _seq_num_high); \ } while(0) +struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds, + bool initiator) +{ + struct schannel_state *state; + + state = talloc(mem_ctx, struct schannel_state); + if (state == NULL) { + return NULL; + } + + state->state = SCHANNEL_STATE_UPDATE_1; + state->initiator = initiator; + state->seq_num = 0; + state->creds = netlogon_creds_copy(state, creds); + if (state->creds == NULL) { + talloc_free(state); + return NULL; + } + + return state; +} + static void netsec_offset_and_sizes(struct schannel_state *state, bool do_seal, uint32_t *_min_sig_size, -- 1.9.3 From f13417a00173fcde96417773a1a551caced24c8b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 13:28:11 +0200 Subject: [PATCH 068/249] s3:cli_pipe: make use of netsec_create_state() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit e96142fc439efb7c90719f9c387778c4218ae637) --- source3/rpc_client/cli_pipe.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index cba055a..9e979b0 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2271,18 +2271,11 @@ static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, goto fail; } - schannel_auth = talloc_zero(result, struct schannel_state); + schannel_auth = netsec_create_state(result, creds, true /* initiator */); if (schannel_auth == NULL) { goto fail; } - schannel_auth->state = SCHANNEL_STATE_START; - schannel_auth->initiator = true; - schannel_auth->creds = netlogon_creds_copy(schannel_auth, creds); - if (schannel_auth->creds == NULL) { - goto fail; - } - result->auth_ctx = schannel_auth; *presult = result; return NT_STATUS_OK; -- 1.9.3 From becf68bc072fdfab4489326d148775ebdbe27fda Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 13:28:59 +0200 Subject: [PATCH 069/249] s3:cli_pipe: pass down creds->computer_name to NL_AUTH_MESSAGE We need to use the same computer_name value as in the netr_Authenticate3() request. We abuse cli->auth->user_name to pass the value down. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 838cb539621ef19cac6badb4b10678dcc3a6f68a) --- source3/rpc_client/cli_pipe.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 9e979b0..1de71fb 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1027,13 +1027,12 @@ static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, NTSTATUS status; struct NL_AUTH_MESSAGE r; - /* Use lp_workgroup() if domain not specified */ + if (!cli->auth->user_name || !cli->auth->user_name[0]) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } if (!cli->auth->domain || !cli->auth->domain[0]) { - cli->auth->domain = talloc_strdup(cli, lp_workgroup()); - if (cli->auth->domain == NULL) { - return NT_STATUS_NO_MEMORY; - } + return NT_STATUS_INVALID_PARAMETER_MIX; } /* @@ -1044,7 +1043,7 @@ static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; r.oem_netbios_domain.a = cli->auth->domain; - r.oem_netbios_computer.a = lp_netbios_name(); + r.oem_netbios_computer.a = cli->auth->user_name; status = dcerpc_push_schannel_bind(cli, &r, auth_token); if (!NT_STATUS_IS_OK(status)) { @@ -2265,7 +2264,7 @@ static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; result->auth_level = auth_level; - result->user_name = talloc_strdup(result, ""); + result->user_name = talloc_strdup(result, creds->computer_name); result->domain = talloc_strdup(result, domain); if ((result->user_name == NULL) || (result->domain == NULL)) { goto fail; -- 1.9.3 From b447ab32047f33d306ee891d1d3fe2ae5a8c56f1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Aug 2013 08:50:54 +0200 Subject: [PATCH 070/249] s3:cli_pipe.c: return NO_USER_SESSION_KEY in cli_get_session_key() for schannel SCHANNEL connections don't have a user session key, they're like anonymous connections. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit af4dc306846a30a5a1201306cc2cbf4d494e16e7) --- source3/rpc_client/cli_pipe.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 1de71fb..470469f 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3091,7 +3091,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, { NTSTATUS status; struct pipe_auth_data *a; - struct schannel_state *schannel_auth; struct gensec_security *gensec_security; DATA_BLOB sk = data_blob_null; bool make_dup = false; @@ -3107,12 +3106,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, } switch (cli->auth->auth_type) { - case DCERPC_AUTH_TYPE_SCHANNEL: - schannel_auth = talloc_get_type_abort(a->auth_ctx, - struct schannel_state); - sk = data_blob_const(schannel_auth->creds->session_key, 16); - make_dup = true; - break; case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: -- 1.9.3 From abebeb10c26f6fa7e61c56553ce1e52b5d45937a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 13:33:37 +0200 Subject: [PATCH 071/249] s3:rpc_server: make use of netsec_create_state() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a964309bf7631f4f6953e0d6556f8ed8e5300dcc) --- source3/rpc_server/srv_pipe.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 7daff04..9043a14 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -462,8 +462,8 @@ static bool pipe_schannel_auth_bind(struct pipes_struct *p, */ become_root(); - status = schannel_get_creds_state(p, lp_ctx, - neg.oem_netbios_computer.a, &creds); + status = schannel_get_creds_state(p->mem_ctx, lp_ctx, + neg.oem_netbios_computer.a, &creds); unbecome_root(); talloc_unlink(p, lp_ctx); @@ -472,16 +472,12 @@ static bool pipe_schannel_auth_bind(struct pipes_struct *p, return False; } - schannel_auth = talloc_zero(p, struct schannel_state); + schannel_auth = netsec_create_state(p, creds, false /* not initiator */); + TALLOC_FREE(creds); if (!schannel_auth) { - TALLOC_FREE(creds); return False; } - schannel_auth->state = SCHANNEL_STATE_START; - schannel_auth->initiator = false; - schannel_auth->creds = creds; - /* * JRA. Should we also copy the schannel session key into the pipe session key p->session_key * here ? We do that for NTLMSSP, but the session key is already set up from the vuser -- 1.9.3 From b567c4ef93de5c098d724c15b614f5f233903812 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 13:36:30 +0200 Subject: [PATCH 072/249] s3:dcerpc_helpers: remove unused DEBUG message of schannel_state->seq_num. This is a layer violation and not needed anymore as we know how the seqnum handling works now. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a36ccdc83edb7437dd00601c459421286fd79db4) --- source3/librpc/rpc/dcerpc_helpers.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 0095990..97999d7 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -462,9 +462,6 @@ static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas, return NT_STATUS_INVALID_PARAMETER; } - DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%llu\n", - (unsigned long long)sas->seq_num)); - switch (auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: status = netsec_outgoing_packet(sas, -- 1.9.3 From e044773b51b76b3582669ee7e3a388d6471e2f2e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 10:08:54 +0200 Subject: [PATCH 073/249] s4:libnet: avoid usage of dcerpc_schannel_creds() We use cli_credentials_get_netlogon_creds() which returns the same value. dcerpc_schannel_creds() is a layer violation. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit c0144273af8f0956a05d102113c40cec77069f7a) --- source4/libnet/libnet_samsync.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source4/libnet/libnet_samsync.c b/source4/libnet/libnet_samsync.c index 9629b9f..206d81e 100644 --- a/source4/libnet/libnet_samsync.c +++ b/source4/libnet/libnet_samsync.c @@ -25,7 +25,6 @@ #include "libcli/auth/libcli_auth.h" #include "../libcli/samsync/samsync.h" #include "auth/gensec/gensec.h" -#include "auth/gensec/schannel.h" #include "auth/credentials/credentials.h" #include "libcli/auth/schannel.h" #include "librpc/gen_ndr/ndr_netlogon.h" @@ -183,9 +182,9 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx /* get NETLOGON credentials */ - nt_status = dcerpc_schannel_creds(p->conn->security_state.generic_state, samsync_ctx, &creds); - if (!NT_STATUS_IS_OK(nt_status)) { - r->out.error_string = talloc_strdup(mem_ctx, "Could not obtain NETLOGON credentials from DCERPC/GENSEC layer"); + creds = cli_credentials_get_netlogon_creds(machine_account); + if (creds == NULL) { + r->out.error_string = talloc_strdup(mem_ctx, "Could not obtain NETLOGON credentials from credentials"); talloc_free(samsync_ctx); return nt_status; } -- 1.9.3 From 322dc86454fc4e60de641ef02da2c2744c347001 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 10:08:54 +0200 Subject: [PATCH 074/249] s4:torture: avoid usage of dcerpc_schannel_creds() We use cli_credentials_get_netlogon_creds() which returns the same value. dcerpc_schannel_creds() is a layer violation. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 2ea3a24dced0814100e352bbbca124011be73602) --- source4/torture/rpc/samlogon.c | 5 ++--- source4/torture/rpc/samr.c | 6 +++--- source4/torture/rpc/samsync.c | 11 ++++------- source4/torture/rpc/schannel.c | 6 ++---- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c index 4861038..886ff39 100644 --- a/source4/torture/rpc/samlogon.c +++ b/source4/torture/rpc/samlogon.c @@ -29,7 +29,6 @@ #include "lib/cmdline/popt_common.h" #include "torture/rpc/torture_rpc.h" #include "auth/gensec/gensec.h" -#include "auth/gensec/schannel.h" #include "libcli/auth/libcli_auth.h" #include "param/param.h" @@ -1764,8 +1763,8 @@ bool torture_rpc_samlogon(struct torture_context *torture) torture_assert_ntstatus_ok_goto(torture, status, ret, failed, talloc_asprintf(torture, "RPC pipe connect as domain member failed: %s\n", nt_errstr(status))); - status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds); - if (!NT_STATUS_IS_OK(status)) { + creds = cli_credentials_get_netlogon_creds(machine_credentials); + if (creds == NULL) { ret = false; goto failed; } diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index cdfa2b8..d4d64f9 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -37,7 +37,6 @@ #include "torture/rpc/torture_rpc.h" #include "param/param.h" #include "auth/gensec/gensec.h" -#include "auth/gensec/schannel.h" #include "auth/gensec/gensec_proto.h" #include "../libcli/auth/schannel.h" @@ -2959,6 +2958,7 @@ static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b, static bool test_SamLogon(struct torture_context *tctx, struct dcerpc_pipe *p, + struct cli_credentials *machine_credentials, struct cli_credentials *test_credentials, NTSTATUS expected_result, bool interactive) @@ -2978,7 +2978,7 @@ static bool test_SamLogon(struct torture_context *tctx, struct netr_Authenticator a; struct dcerpc_binding_handle *b = p->binding_handle; - torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), ""); + torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), ""); if (lpcfg_client_lanman_auth(tctx->lp_ctx)) { flags |= CLI_CRED_LANMAN_AUTH; @@ -3105,7 +3105,7 @@ static bool test_SamLogon_with_creds(struct torture_context *tctx, torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n", interactive ? "interactive" : "network", acct_name, password); - if (!test_SamLogon(tctx, p, test_credentials, + if (!test_SamLogon(tctx, p, machine_creds, test_credentials, expected_samlogon_result, interactive)) { torture_warning(tctx, "new password did not work\n"); ret = false; diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c index 81027d0..15cab73 100644 --- a/source4/torture/rpc/samsync.c +++ b/source4/torture/rpc/samsync.c @@ -27,7 +27,6 @@ #include "system/time.h" #include "torture/rpc/torture_rpc.h" #include "auth/gensec/gensec.h" -#include "auth/gensec/schannel.h" #include "libcli/auth/libcli_auth.h" #include "libcli/samsync/samsync.h" #include "libcli/security/security.h" @@ -1720,9 +1719,8 @@ bool torture_rpc_samsync(struct torture_context *torture) } samsync_state->b = samsync_state->p->binding_handle; - status = dcerpc_schannel_creds(samsync_state->p->conn->security_state.generic_state, - samsync_state, &samsync_state->creds); - if (!NT_STATUS_IS_OK(status)) { + samsync_state->creds = cli_credentials_get_netlogon_creds(credentials); + if (samsync_state->creds == NULL) { ret = false; } @@ -1758,9 +1756,8 @@ bool torture_rpc_samsync(struct torture_context *torture) goto failed; } - status = dcerpc_schannel_creds(samsync_state->p_netlogon_wksta->conn->security_state.generic_state, - samsync_state, &samsync_state->creds_netlogon_wksta); - if (!NT_STATUS_IS_OK(status)) { + samsync_state->creds_netlogon_wksta = cli_credentials_get_netlogon_creds(credentials_wksta); + if (samsync_state->creds_netlogon_wksta == NULL) { torture_comment(torture, "Failed to obtail schanel creds!\n"); ret = false; } diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c index 8203749..0098dcf 100644 --- a/source4/torture/rpc/schannel.c +++ b/source4/torture/rpc/schannel.c @@ -26,14 +26,12 @@ #include "auth/credentials/credentials.h" #include "torture/rpc/torture_rpc.h" #include "lib/cmdline/popt_common.h" -#include "auth/gensec/schannel.h" #include "../libcli/auth/schannel.h" #include "libcli/auth/libcli_auth.h" #include "libcli/security/security.h" #include "system/filesys.h" #include "param/param.h" #include "librpc/rpc/dcerpc_proto.h" -#include "auth/gensec/gensec.h" #include "libcli/composite/composite.h" #include "lib/events/events.h" @@ -413,8 +411,8 @@ static bool test_schannel(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "bind auth"); - status = dcerpc_schannel_creds(p_netlogon->conn->security_state.generic_state, tctx, &creds); - torture_assert_ntstatus_ok(tctx, status, "schannel creds"); + creds = cli_credentials_get_netlogon_creds(credentials); + torture_assert(tctx, (creds != NULL), "schannel creds"); /* checks the capabilities */ torture_assert(tctx, test_netlogon_capabilities(p_netlogon, tctx, credentials, creds), -- 1.9.3 From fa1c5bc2cdff9decd361c919567c502ef0c09385 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 12:31:41 +0200 Subject: [PATCH 075/249] s4:gensec/schannel: remove unused dcerpc_schannel_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 4cad5dcb6d5e49cc9bb1aa4ca454f369e00e8c6f) --- source4/auth/gensec/schannel.c | 23 ----------------------- source4/auth/gensec/schannel.h | 26 -------------------------- 2 files changed, 49 deletions(-) delete mode 100644 source4/auth/gensec/schannel.h diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index e7c545f..10d2565 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -29,7 +29,6 @@ #include "../libcli/auth/schannel.h" #include "librpc/rpc/dcerpc.h" #include "param/param.h" -#include "auth/gensec/schannel.h" #include "auth/gensec/gensec_toplevel_proto.h" _PUBLIC_ NTSTATUS gensec_schannel_init(void); @@ -204,28 +203,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ } /** - * Return the struct netlogon_creds_CredentialState. - * - * Make sure not to call this unless gensec is using schannel... - */ - -/* TODO: make this non-public */ - -_PUBLIC_ NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState **creds) -{ - struct schannel_state *state = talloc_get_type(gensec_security->private_data, struct schannel_state); - - *creds = talloc_reference(mem_ctx, state->creds); - if (!*creds) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - - -/** * Returns anonymous credentials for schannel, matching Win2k3. * */ diff --git a/source4/auth/gensec/schannel.h b/source4/auth/gensec/schannel.h deleted file mode 100644 index 88a32a7..0000000 --- a/source4/auth/gensec/schannel.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - dcerpc schannel operations - - Copyright (C) Andrew Tridgell 2004 - Copyright (C) Andrew Bartlett 2004-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 - (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 . -*/ - -struct netlogon_creds_CredentialState; -NTSTATUS dcerpc_schannel_creds(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState **creds); -- 1.9.3 From eeb52af669e963ac856fc77be6a47f7ed33d8580 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 13:04:07 +0200 Subject: [PATCH 076/249] s4:gensec/schannel: simplify the code by using netsec_create_state() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 49f347eb11bd12a3f25b0fcb8ba36d4a36594868) --- source4/auth/gensec/schannel.c | 98 +++++++++++++----------------------------- 1 file changed, 30 insertions(+), 68 deletions(-) diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index 10d2565..3896a41 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -35,12 +35,11 @@ _PUBLIC_ NTSTATUS gensec_schannel_init(void); static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size) { - struct schannel_state *state = (struct schannel_state *)gensec_security->private_data; - uint32_t sig_size; - - sig_size = netsec_outgoing_sig_size(state); + struct schannel_state *state = + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); - return sig_size; + return netsec_outgoing_sig_size(state); } static NTSTATUS schannel_session_key(struct gensec_security *gensec_security, @@ -54,7 +53,9 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ struct tevent_context *ev, const DATA_BLOB in, DATA_BLOB *out) { - struct schannel_state *state = (struct schannel_state *)gensec_security->private_data; + struct schannel_state *state = + talloc_get_type(gensec_security->private_data, + struct schannel_state); NTSTATUS status; enum ndr_err_code ndr_err; struct NL_AUTH_MESSAGE bind_schannel; @@ -67,24 +68,22 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ switch (gensec_security->gensec_role) { case GENSEC_CLIENT: - if (state->state != SCHANNEL_STATE_START) { + if (state != NULL) { /* we could parse the bind ack, but we don't know what it is yet */ return NT_STATUS_OK; } - state->creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); - if (state->creds == NULL) { + creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); + if (creds == NULL) { return NT_STATUS_INVALID_PARAMETER_MIX; } - /* - * We need to create a reference here or we don't get - * updates performed on the credentials if we create a - * copy. - */ - state->creds = talloc_reference(state, state->creds); - if (state->creds == NULL) { + + state = netsec_create_state(gensec_security, + creds, true /* initiator */); + if (state == NULL) { return NT_STATUS_NO_MEMORY; } + gensec_security->private_data = state; bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; #if 0 @@ -117,12 +116,10 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ return status; } - state->state = SCHANNEL_STATE_UPDATE_1; - return NT_STATUS_MORE_PROCESSING_REQUIRED; case GENSEC_SERVER: - if (state->state != SCHANNEL_STATE_START) { + if (state != NULL) { /* no third leg on this protocol */ return NT_STATUS_INVALID_PARAMETER; } @@ -177,7 +174,12 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ return status; } - state->creds = talloc_steal(state, creds); + state = netsec_create_state(gensec_security, + creds, false /* not initiator */); + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } + gensec_security->private_data = state; bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; bind_schannel_ack.Flags = 0; @@ -195,8 +197,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ return status; } - state->state = SCHANNEL_STATE_UPDATE_1; - return NT_STATUS_OK; } return NT_STATUS_INVALID_PARAMETER; @@ -214,54 +214,16 @@ static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, return auth_anonymous_session_info(mem_ctx, gensec_security->settings->lp_ctx, _session_info); } -static NTSTATUS schannel_start(struct gensec_security *gensec_security) -{ - struct schannel_state *state; - - state = talloc_zero(gensec_security, struct schannel_state); - if (!state) { - return NT_STATUS_NO_MEMORY; - } - - state->state = SCHANNEL_STATE_START; - gensec_security->private_data = state; - - return NT_STATUS_OK; -} - static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) { - NTSTATUS status; - struct schannel_state *state; - - status = schannel_start(gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - state = (struct schannel_state *)gensec_security->private_data; - state->initiator = false; - return NT_STATUS_OK; } static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) { - NTSTATUS status; - struct schannel_state *state; - - status = schannel_start(gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - state = (struct schannel_state *)gensec_security->private_data; - state->initiator = true; - return NT_STATUS_OK; } - static bool schannel_have_feature(struct gensec_security *gensec_security, uint32_t feature) { @@ -287,8 +249,8 @@ static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, const DATA_BLOB *sig) { struct schannel_state *state = - talloc_get_type(gensec_security->private_data, - struct schannel_state); + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); return netsec_incoming_packet(state, true, discard_const_p(uint8_t, data), @@ -304,8 +266,8 @@ static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, const DATA_BLOB *sig) { struct schannel_state *state = - talloc_get_type(gensec_security->private_data, - struct schannel_state); + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); return netsec_incoming_packet(state, false, discard_const_p(uint8_t, data), @@ -321,8 +283,8 @@ static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, DATA_BLOB *sig) { struct schannel_state *state = - talloc_get_type(gensec_security->private_data, - struct schannel_state); + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); return netsec_outgoing_packet(state, mem_ctx, true, data, length, sig); @@ -338,8 +300,8 @@ static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, DATA_BLOB *sig) { struct schannel_state *state = - talloc_get_type(gensec_security->private_data, - struct schannel_state); + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); return netsec_outgoing_packet(state, mem_ctx, false, discard_const_p(uint8_t, data), -- 1.9.3 From 685f00cfd7be11f4c62441e17d6416b9a668bb47 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 13:25:20 +0200 Subject: [PATCH 077/249] s4:gensec/schannel: use the correct computer_name from netlogon_creds_CredentialState We need to use the same computer_name we used in the netr_Authenticate3 request. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit b5104768225ae0308aa3f22f8d9bca389ef3cb3a) --- source4/auth/gensec/schannel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index 3896a41..91f166b 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -94,17 +94,17 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ NL_FLAG_UTF8_DNS_DOMAIN_NAME | NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); - bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); + bind_schannel.oem_netbios_computer.a = creds->computer_name; bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); /* w2k3 refuses us if we use the full DNS workstation? why? perhaps because we don't fill in the dNSHostName attribute in the machine account? */ - bind_schannel.utf8_netbios_computer = cli_credentials_get_workstation(gensec_security->credentials); + bind_schannel.utf8_netbios_computer = creds->computer_name; #else bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); - bind_schannel.oem_netbios_computer.a = cli_credentials_get_workstation(gensec_security->credentials); + bind_schannel.oem_netbios_computer.a = creds->computer_name; #endif ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, -- 1.9.3 From bd54e89fc5eb4d6afed3ef770dabf14a6ac6b060 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Aug 2013 11:21:32 +0200 Subject: [PATCH 078/249] s4:gensec/schannel: GENSEC_FEATURE_ASYNC_REPLIES is not supported There's a sequence number attached to the connection, which needs to be incremented with each message... Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a07049a839729e29ca888bae353cd37fd6238486) --- source4/auth/gensec/schannel.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index 91f166b..7fc0c7c 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -234,9 +234,6 @@ static bool schannel_have_feature(struct gensec_security *gensec_security, if (feature & GENSEC_FEATURE_DCE_STYLE) { return true; } - if (feature & GENSEC_FEATURE_ASYNC_REPLIES) { - return true; - } return false; } -- 1.9.3 From afcf626800e8aaf94878d62d1fd7318b2ffe21c1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Aug 2013 11:27:55 +0200 Subject: [PATCH 079/249] s4:gensec/schannel: there's no point in having schannel_session_key() gensec_session_key() will return NT_STATUS_NO_USER_SESSION_KEY before calling schannel_session_key(), as we don't provide GENSEC_FEATURE_SESSION_KEY. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 9b9ab1ae6963b3819dc2b095cbe9e1432f3459b7) --- source4/auth/gensec/schannel.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index 7fc0c7c..ebf6469 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -42,13 +42,6 @@ static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t return netsec_outgoing_sig_size(state); } -static NTSTATUS schannel_session_key(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, struct tevent_context *ev, const DATA_BLOB in, DATA_BLOB *out) @@ -315,7 +308,6 @@ static const struct gensec_security_ops gensec_schannel_security_ops = { .sign_packet = schannel_sign_packet, .check_packet = schannel_check_packet, .unseal_packet = schannel_unseal_packet, - .session_key = schannel_session_key, .session_info = schannel_session_info, .sig_size = schannel_sig_size, .have_feature = schannel_have_feature, -- 1.9.3 From 56599b7019eabe3656bdba676214c74191ad068f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 3 Aug 2013 11:32:31 +0200 Subject: [PATCH 080/249] s4:gensec/schannel: only require librpc/gen_ndr/dcerpc.h We just need DCERPC_AUTH_TYPE_SCHANNEL Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit e90e1b5c76db4cf589adf8856eb32e5f0d955734) --- source4/auth/gensec/schannel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index ebf6469..e67432c 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -27,7 +27,7 @@ #include "auth/gensec/gensec.h" #include "auth/gensec/gensec_proto.h" #include "../libcli/auth/schannel.h" -#include "librpc/rpc/dcerpc.h" +#include "librpc/gen_ndr/dcerpc.h" #include "param/param.h" #include "auth/gensec/gensec_toplevel_proto.h" -- 1.9.3 From baa82a6ef22c1761c7206323e90781d008a7888b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 13:37:54 +0200 Subject: [PATCH 081/249] libcli/auth/schannel: make struct schannel_state private Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 4c978b68d9a87001f625c10421e7d4cc140b4554) --- libcli/auth/schannel.h | 13 ------------- libcli/auth/schannel_sign.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libcli/auth/schannel.h b/libcli/auth/schannel.h index 271b5bb..c53d68e 100644 --- a/libcli/auth/schannel.h +++ b/libcli/auth/schannel.h @@ -22,17 +22,4 @@ #include "libcli/auth/libcli_auth.h" #include "libcli/auth/schannel_state.h" - -enum schannel_position { - SCHANNEL_STATE_START = 0, - SCHANNEL_STATE_UPDATE_1 -}; - -struct schannel_state { - enum schannel_position state; - uint64_t seq_num; - bool initiator; - struct netlogon_creds_CredentialState *creds; -}; - #include "libcli/auth/schannel_proto.h" diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c index 518a6a9..88a6e1e 100644 --- a/libcli/auth/schannel_sign.c +++ b/libcli/auth/schannel_sign.c @@ -24,6 +24,18 @@ #include "../libcli/auth/schannel.h" #include "../lib/crypto/crypto.h" +enum schannel_position { + SCHANNEL_STATE_START = 0, + SCHANNEL_STATE_UPDATE_1 +}; + +struct schannel_state { + enum schannel_position state; + uint64_t seq_num; + bool initiator; + struct netlogon_creds_CredentialState *creds; +}; + #define SETUP_SEQNUM(state, buf, initiator) do { \ uint8_t *_buf = buf; \ uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ -- 1.9.3 From 29806ef23a9826688ace1dc52cd7af554cf83294 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Aug 2013 15:42:21 +0200 Subject: [PATCH 082/249] libcli/auth/schannel: remove unused schannel_position Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 57bcbb9c50f0a0252110a1e04a2883b511cd9165) --- libcli/auth/schannel_sign.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c index 88a6e1e..9502cba 100644 --- a/libcli/auth/schannel_sign.c +++ b/libcli/auth/schannel_sign.c @@ -24,13 +24,7 @@ #include "../libcli/auth/schannel.h" #include "../lib/crypto/crypto.h" -enum schannel_position { - SCHANNEL_STATE_START = 0, - SCHANNEL_STATE_UPDATE_1 -}; - struct schannel_state { - enum schannel_position state; uint64_t seq_num; bool initiator; struct netlogon_creds_CredentialState *creds; @@ -58,7 +52,6 @@ struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, return NULL; } - state->state = SCHANNEL_STATE_UPDATE_1; state->initiator = initiator; state->seq_num = 0; state->creds = netlogon_creds_copy(state, creds); -- 1.9.3 From a6ad9118c250446ea9571f5ce9895b11ab8537ed Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 07:12:01 +0200 Subject: [PATCH 083/249] auth/gensec: introduce gensec_internal.h We should treat most gensec related structures private. It's a long way, but this is a start. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 71c63e85e7a09acb57f6b75284358f2b3b29eeed) --- auth/gensec/gensec.c | 1 + auth/gensec/gensec.h | 100 ++------------------------- auth/gensec/gensec_internal.h | 127 +++++++++++++++++++++++++++++++++++ auth/gensec/gensec_start.c | 1 + auth/gensec/gensec_util.c | 1 + auth/gensec/spnego.c | 1 + auth/ntlmssp/gensec_ntlmssp.c | 1 + auth/ntlmssp/gensec_ntlmssp_server.c | 1 + auth/ntlmssp/ntlmssp.c | 1 + auth/ntlmssp/ntlmssp_client.c | 1 + auth/ntlmssp/ntlmssp_server.c | 1 + source3/libads/authdata.c | 1 + source3/librpc/crypto/gse.c | 1 + source3/libsmb/ntlmssp_wrap.c | 1 + source3/utils/ntlm_auth.c | 1 + source4/auth/gensec/cyrus_sasl.c | 1 + source4/auth/gensec/gensec_gssapi.c | 1 + source4/auth/gensec/gensec_krb5.c | 1 + source4/auth/gensec/pygensec.c | 1 + source4/auth/gensec/schannel.c | 1 + source4/ldap_server/ldap_backend.c | 1 + source4/libcli/ldap/ldap_bind.c | 1 + source4/torture/auth/ntlmssp.c | 1 + source4/utils/ntlm_auth.c | 1 + 24 files changed, 153 insertions(+), 96 deletions(-) create mode 100644 auth/gensec/gensec_internal.h diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c index 9a8f0ef..d364a34 100644 --- a/auth/gensec/gensec.c +++ b/auth/gensec/gensec.c @@ -26,6 +26,7 @@ #include "lib/tsocket/tsocket.h" #include "lib/util/tevent_ntstatus.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "librpc/rpc/dcerpc.h" /* diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h index c080861..5d39d81 100644 --- a/auth/gensec/gensec.h +++ b/auth/gensec/gensec.h @@ -76,6 +76,7 @@ struct gensec_settings; struct tevent_context; struct tevent_req; struct smb_krb5_context; +struct tsocket_address; struct gensec_settings { struct loadparm_context *lp_ctx; @@ -93,106 +94,13 @@ struct gensec_settings { const char *server_netbios_name; }; -struct gensec_security_ops { - const char *name; - const char *sasl_name; - uint8_t auth_type; /* 0 if not offered on DCE-RPC */ - const char **oid; /* NULL if not offered by SPNEGO */ - NTSTATUS (*client_start)(struct gensec_security *gensec_security); - NTSTATUS (*server_start)(struct gensec_security *gensec_security); - /** - Determine if a packet has the right 'magic' for this mechanism - */ - NTSTATUS (*magic)(struct gensec_security *gensec_security, - const DATA_BLOB *first_packet); - NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, - struct tevent_context *ev, - const DATA_BLOB in, DATA_BLOB *out); - NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig); - NTSTATUS (*sign_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig); - size_t (*sig_size)(struct gensec_security *gensec_security, size_t data_size); - size_t (*max_input_size)(struct gensec_security *gensec_security); - size_t (*max_wrapped_size)(struct gensec_security *gensec_security); - NTSTATUS (*check_packet)(struct gensec_security *gensec_security, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - const DATA_BLOB *sig); - NTSTATUS (*unseal_packet)(struct gensec_security *gensec_security, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - const DATA_BLOB *sig); - NTSTATUS (*wrap)(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const DATA_BLOB *in, - DATA_BLOB *out); - NTSTATUS (*unwrap)(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const DATA_BLOB *in, - DATA_BLOB *out); - NTSTATUS (*wrap_packets)(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const DATA_BLOB *in, - DATA_BLOB *out, - size_t *len_processed); - NTSTATUS (*unwrap_packets)(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const DATA_BLOB *in, - DATA_BLOB *out, - size_t *len_processed); - NTSTATUS (*packet_full_request)(struct gensec_security *gensec_security, - DATA_BLOB blob, size_t *size); - NTSTATUS (*session_key)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key); - NTSTATUS (*session_info)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, - struct auth_session_info **session_info); - void (*want_feature)(struct gensec_security *gensec_security, - uint32_t feature); - bool (*have_feature)(struct gensec_security *gensec_security, - uint32_t feature); - NTTIME (*expire_time)(struct gensec_security *gensec_security); - bool enabled; - bool kerberos; - enum gensec_priority priority; -}; - -struct gensec_security_ops_wrapper { - const struct gensec_security_ops *op; - const char *oid; -}; +struct gensec_security_ops; +struct gensec_security_ops_wrapper; #define GENSEC_INTERFACE_VERSION 0 -struct gensec_security { - const struct gensec_security_ops *ops; - void *private_data; - struct cli_credentials *credentials; - struct gensec_target target; - enum gensec_role gensec_role; - bool subcontext; - uint32_t want_features; - uint32_t max_update_size; - uint8_t dcerpc_auth_level; - struct tsocket_address *local_addr, *remote_addr; - struct gensec_settings *settings; - - /* When we are a server, this may be filled in to provide an - * NTLM authentication backend, and user lookup (such as if no - * PAC is found) */ - struct auth4_context *auth_context; -}; - /* this structure is used by backends to determine the size of some critical types */ -struct gensec_critical_sizes { - int interface_version; - int sizeof_gensec_security_ops; - int sizeof_gensec_security; -}; +struct gensec_critical_sizes; const struct gensec_critical_sizes *gensec_interface_version(void); /* Socket wrapper */ diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h new file mode 100644 index 0000000..41b6f0d --- /dev/null +++ b/auth/gensec/gensec_internal.h @@ -0,0 +1,127 @@ +/* + Unix SMB/CIFS implementation. + + Generic Authentication Interface + + Copyright (C) Andrew Tridgell 2003 + Copyright (C) Andrew Bartlett 2004-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 + (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 . +*/ + +#ifndef __GENSEC_INTERNAL_H__ +#define __GENSEC_INTERNAL_H__ + +struct gensec_security; + +struct gensec_security_ops { + const char *name; + const char *sasl_name; + uint8_t auth_type; /* 0 if not offered on DCE-RPC */ + const char **oid; /* NULL if not offered by SPNEGO */ + NTSTATUS (*client_start)(struct gensec_security *gensec_security); + NTSTATUS (*server_start)(struct gensec_security *gensec_security); + /** + Determine if a packet has the right 'magic' for this mechanism + */ + NTSTATUS (*magic)(struct gensec_security *gensec_security, + const DATA_BLOB *first_packet); + NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, + struct tevent_context *ev, + const DATA_BLOB in, DATA_BLOB *out); + NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, + uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + DATA_BLOB *sig); + NTSTATUS (*sign_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, + const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + DATA_BLOB *sig); + size_t (*sig_size)(struct gensec_security *gensec_security, size_t data_size); + size_t (*max_input_size)(struct gensec_security *gensec_security); + size_t (*max_wrapped_size)(struct gensec_security *gensec_security); + NTSTATUS (*check_packet)(struct gensec_security *gensec_security, + const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig); + NTSTATUS (*unseal_packet)(struct gensec_security *gensec_security, + uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig); + NTSTATUS (*wrap)(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out); + NTSTATUS (*unwrap)(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out); + NTSTATUS (*wrap_packets)(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out, + size_t *len_processed); + NTSTATUS (*unwrap_packets)(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const DATA_BLOB *in, + DATA_BLOB *out, + size_t *len_processed); + NTSTATUS (*packet_full_request)(struct gensec_security *gensec_security, + DATA_BLOB blob, size_t *size); + NTSTATUS (*session_key)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, + DATA_BLOB *session_key); + NTSTATUS (*session_info)(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, + struct auth_session_info **session_info); + void (*want_feature)(struct gensec_security *gensec_security, + uint32_t feature); + bool (*have_feature)(struct gensec_security *gensec_security, + uint32_t feature); + NTTIME (*expire_time)(struct gensec_security *gensec_security); + bool enabled; + bool kerberos; + enum gensec_priority priority; +}; + +struct gensec_security_ops_wrapper { + const struct gensec_security_ops *op; + const char *oid; +}; + +struct gensec_security { + const struct gensec_security_ops *ops; + void *private_data; + struct cli_credentials *credentials; + struct gensec_target target; + enum gensec_role gensec_role; + bool subcontext; + uint32_t want_features; + uint32_t max_update_size; + uint8_t dcerpc_auth_level; + struct tsocket_address *local_addr, *remote_addr; + struct gensec_settings *settings; + + /* When we are a server, this may be filled in to provide an + * NTLM authentication backend, and user lookup (such as if no + * PAC is found) */ + struct auth4_context *auth_context; +}; + +/* this structure is used by backends to determine the size of some critical types */ +struct gensec_critical_sizes { + int interface_version; + int sizeof_gensec_security_ops; + int sizeof_gensec_security; +}; + +#endif /* __GENSEC_H__ */ diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index c2cfa1c..34029f5 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -27,6 +27,7 @@ #include "librpc/rpc/dcerpc.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "lib/param/param.h" #include "lib/util/tsort.h" #include "lib/util/samba_modules.h" diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c index 64952b1..568128a 100644 --- a/auth/gensec/gensec_util.c +++ b/auth/gensec/gensec_util.c @@ -22,6 +22,7 @@ #include "includes.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/common_auth.h" #include "../lib/util/asn1.h" diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c index da1fc0e..38a45f8 100644 --- a/auth/gensec/spnego.c +++ b/auth/gensec/spnego.c @@ -27,6 +27,7 @@ #include "librpc/gen_ndr/ndr_dcerpc.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "param/param.h" #include "lib/util/asn1.h" diff --git a/auth/ntlmssp/gensec_ntlmssp.c b/auth/ntlmssp/gensec_ntlmssp.c index 9e1d8a8..654c0e3 100644 --- a/auth/ntlmssp/gensec_ntlmssp.c +++ b/auth/ntlmssp/gensec_ntlmssp.c @@ -22,6 +22,7 @@ #include "includes.h" #include "auth/ntlmssp/ntlmssp.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/ntlmssp/ntlmssp_private.h" NTSTATUS gensec_ntlmssp_magic(struct gensec_security *gensec_security, diff --git a/auth/ntlmssp/gensec_ntlmssp_server.c b/auth/ntlmssp/gensec_ntlmssp_server.c index f4dfab3..69c56fb 100644 --- a/auth/ntlmssp/gensec_ntlmssp_server.c +++ b/auth/ntlmssp/gensec_ntlmssp_server.c @@ -31,6 +31,7 @@ #include "../libcli/auth/libcli_auth.h" #include "../lib/crypto/crypto.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/common_auth.h" #include "param/param.h" diff --git a/auth/ntlmssp/ntlmssp.c b/auth/ntlmssp/ntlmssp.c index 1a2d662..916b376 100644 --- a/auth/ntlmssp/ntlmssp.c +++ b/auth/ntlmssp/ntlmssp.c @@ -29,6 +29,7 @@ struct auth_session_info; #include "../libcli/auth/libcli_auth.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" /** * Callbacks for NTLMSSP - for both client and server operating modes diff --git a/auth/ntlmssp/ntlmssp_client.c b/auth/ntlmssp/ntlmssp_client.c index fc66a8d..f99257d 100644 --- a/auth/ntlmssp/ntlmssp_client.c +++ b/auth/ntlmssp/ntlmssp_client.c @@ -29,6 +29,7 @@ struct auth_session_info; #include "../libcli/auth/libcli_auth.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "param/param.h" #include "auth/ntlmssp/ntlmssp_private.h" #include "../librpc/gen_ndr/ndr_ntlmssp.h" diff --git a/auth/ntlmssp/ntlmssp_server.c b/auth/ntlmssp/ntlmssp_server.c index 57179e1..2f3f0bb 100644 --- a/auth/ntlmssp/ntlmssp_server.c +++ b/auth/ntlmssp/ntlmssp_server.c @@ -28,6 +28,7 @@ #include "../libcli/auth/libcli_auth.h" #include "../lib/crypto/crypto.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/common_auth.h" /** diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 2c667a6..582917d 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -30,6 +30,7 @@ #include "lib/param/param.h" #include "librpc/crypto/gse.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ #include "../libcli/auth/spnego.h" #ifdef HAVE_KRB5 diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c index 11a5457..8db3cdd 100644 --- a/source3/librpc/crypto/gse.c +++ b/source3/librpc/crypto/gse.c @@ -26,6 +26,7 @@ #include "libads/kerberos_proto.h" #include "auth/common_auth.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/credentials/credentials.h" #include "../librpc/gen_ndr/dcerpc.h" diff --git a/source3/libsmb/ntlmssp_wrap.c b/source3/libsmb/ntlmssp_wrap.c index 9ce4b12..46f68ae 100644 --- a/source3/libsmb/ntlmssp_wrap.c +++ b/source3/libsmb/ntlmssp_wrap.c @@ -23,6 +23,7 @@ #include "auth/ntlmssp/ntlmssp_private.h" #include "auth_generic.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/credentials/credentials.h" #include "librpc/rpc/dcerpc.h" #include "lib/param/param.h" diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index a5e0cd2..5fcb60e 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -32,6 +32,7 @@ #include "../libcli/auth/spnego.h" #include "auth/ntlmssp/ntlmssp.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/credentials/credentials.h" #include "librpc/crypto/gse.h" #include "smb_krb5.h" diff --git a/source4/auth/gensec/cyrus_sasl.c b/source4/auth/gensec/cyrus_sasl.c index 2e733bf..08dccd6 100644 --- a/source4/auth/gensec/cyrus_sasl.c +++ b/source4/auth/gensec/cyrus_sasl.c @@ -23,6 +23,7 @@ #include "lib/tsocket/tsocket.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/gensec/gensec_proto.h" #include "auth/gensec/gensec_toplevel_proto.h" #include diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 4fc544f..63a53bf 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -34,6 +34,7 @@ #include "auth/credentials/credentials.h" #include "auth/credentials/credentials_krb5.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/gensec/gensec_proto.h" #include "auth/gensec/gensec_toplevel_proto.h" #include "param/param.h" diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index fbec64c..ecc3331 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -34,6 +34,7 @@ #include "auth/credentials/credentials_krb5.h" #include "auth/kerberos/kerberos_credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/gensec/gensec_proto.h" #include "auth/gensec/gensec_toplevel_proto.h" #include "param/param.h" diff --git a/source4/auth/gensec/pygensec.c b/source4/auth/gensec/pygensec.c index 02e5ae2..fd6daff 100644 --- a/source4/auth/gensec/pygensec.c +++ b/source4/auth/gensec/pygensec.c @@ -20,6 +20,7 @@ #include "includes.h" #include "param/pyparam.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ #include "auth/credentials/pycredentials.h" #include "libcli/util/pyerrors.h" #include "python/modules.h" diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c index e67432c..eb2e100 100644 --- a/source4/auth/gensec/schannel.c +++ b/source4/auth/gensec/schannel.c @@ -25,6 +25,7 @@ #include "auth/auth.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/gensec/gensec_proto.h" #include "../libcli/auth/schannel.h" #include "librpc/gen_ndr/dcerpc.h" diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c index 4a195e5..f0da82c 100644 --- a/source4/ldap_server/ldap_backend.c +++ b/source4/ldap_server/ldap_backend.c @@ -23,6 +23,7 @@ #include "../lib/util/dlinklist.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ #include "param/param.h" #include "smbd/service_stream.h" #include "dsdb/samdb/samdb.h" diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c index b355e18..f0a498b 100644 --- a/source4/libcli/ldap/ldap_bind.c +++ b/source4/libcli/ldap/ldap_bind.c @@ -27,6 +27,7 @@ #include "libcli/ldap/ldap_client.h" #include "lib/tls/tls.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ #include "auth/gensec/gensec_socket.h" #include "auth/credentials/credentials.h" #include "lib/stream/packet.h" diff --git a/source4/torture/auth/ntlmssp.c b/source4/torture/auth/ntlmssp.c index bdaa65b..45e5889 100644 --- a/source4/torture/auth/ntlmssp.c +++ b/source4/torture/auth/ntlmssp.c @@ -19,6 +19,7 @@ #include "includes.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" #include "auth/ntlmssp/ntlmssp.h" #include "auth/ntlmssp/ntlmssp_private.h" #include "lib/cmdline/popt_common.h" diff --git a/source4/utils/ntlm_auth.c b/source4/utils/ntlm_auth.c index 136e238..1e2feb0 100644 --- a/source4/utils/ntlm_auth.c +++ b/source4/utils/ntlm_auth.c @@ -27,6 +27,7 @@ #include #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" /* TODO: remove this */ #include "auth/auth.h" #include "librpc/gen_ndr/ndr_netlogon.h" #include "auth/auth_sam.h" -- 1.9.3 From fabdf9f539385d97bc4bf2550e7fd4de2d1b5d01 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 10:37:26 +0200 Subject: [PATCH 084/249] auth/gensec: avoid talloc_reference in gensec_use_kerberos_mechs() We now always copy. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3e3534f882651880093381f5a7846c0938df6501) --- auth/gensec/gensec_start.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index 34029f5..096ad36 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -80,13 +80,6 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ use_kerberos = cli_credentials_get_kerberos_state(creds); } - if (use_kerberos == CRED_AUTO_USE_KERBEROS) { - if (!talloc_reference(mem_ctx, old_gensec_list)) { - return NULL; - } - return old_gensec_list; - } - for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) { /* noop */ } @@ -99,35 +92,44 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ j = 0; for (i=0; old_gensec_list && old_gensec_list[i]; i++) { int oid_idx; - bool found_spnego = false; + bool keep = false; + for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) { if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) { - new_gensec_list[j] = old_gensec_list[i]; - j++; - found_spnego = true; + keep = true; break; } } - if (found_spnego) { - continue; - } + switch (use_kerberos) { + case CRED_AUTO_USE_KERBEROS: + keep = true; + break; + case CRED_DONT_USE_KERBEROS: if (old_gensec_list[i]->kerberos == false) { - new_gensec_list[j] = old_gensec_list[i]; - j++; + keep = true; } + break; + case CRED_MUST_USE_KERBEROS: if (old_gensec_list[i]->kerberos == true) { - new_gensec_list[j] = old_gensec_list[i]; - j++; + keep = true; } + break; default: /* Can't happen or invalid parameter */ return NULL; } + + if (!keep) { + continue; + } + + new_gensec_list[j] = old_gensec_list[i]; + j++; } new_gensec_list[j] = NULL; -- 1.9.3 From b71ed3dd183d64beda108d0881c03978ef4b3892 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 10:39:16 +0200 Subject: [PATCH 085/249] auth/gensec: avoid talloc_reference in gensec_security_mechs() We now always copy. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 6a7a44db5999af7262478eb1c186d784d6075beb) --- auth/gensec/gensec_start.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index 096ad36..00e2759 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -140,28 +140,19 @@ _PUBLIC_ struct gensec_security_ops **gensec_security_mechs( struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx) { - struct gensec_security_ops **backends; - if (!gensec_security) { - backends = gensec_security_all(); - if (!talloc_reference(mem_ctx, backends)) { - return NULL; - } - return backends; - } else { - struct cli_credentials *creds = gensec_get_credentials(gensec_security); + struct cli_credentials *creds = NULL; + struct gensec_security_ops **backends = gensec_security_all(); + + if (gensec_security != NULL) { + creds = gensec_get_credentials(gensec_security); + if (gensec_security->settings->backends) { backends = gensec_security->settings->backends; - } else { - backends = gensec_security_all(); } - if (!creds) { - if (!talloc_reference(mem_ctx, backends)) { - return NULL; - } - return backends; - } - return gensec_use_kerberos_mechs(mem_ctx, backends, creds); } + + return gensec_use_kerberos_mechs(mem_ctx, backends, creds); + } static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security, -- 1.9.3 From fe6a14d48b0eb3dfcfc6d7f0b68e8f28b7ad9796 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 16:12:13 +0200 Subject: [PATCH 086/249] auth/gensec: make it possible to implement async backends Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit e81550c8117166d0fbf69ba1d3957cb950c42961) --- auth/gensec/gensec.c | 202 ++++++++++++++++++++++++++++++++---------- auth/gensec/gensec_internal.h | 7 ++ 2 files changed, 160 insertions(+), 49 deletions(-) diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c index d364a34..abcbcb9 100644 --- a/auth/gensec/gensec.c +++ b/auth/gensec/gensec.c @@ -218,61 +218,92 @@ _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_ const DATA_BLOB in, DATA_BLOB *out) { NTSTATUS status; + const struct gensec_security_ops *ops = gensec_security->ops; + TALLOC_CTX *frame = NULL; + struct tevent_req *subreq = NULL; + bool ok; - status = gensec_security->ops->update(gensec_security, out_mem_ctx, - ev, in, out); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + if (ops->update_send == NULL) { - /* - * Because callers using the - * gensec_start_mech_by_auth_type() never call - * gensec_want_feature(), it isn't sensible for them - * to have to call gensec_have_feature() manually, and - * these are not points of negotiation, but are - * asserted by the client - */ - switch (gensec_security->dcerpc_auth_level) { - case DCERPC_AUTH_LEVEL_INTEGRITY: - if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { - DEBUG(0,("Did not manage to negotiate mandetory feature " - "SIGN for dcerpc auth_level %u\n", - gensec_security->dcerpc_auth_level)); - return NT_STATUS_ACCESS_DENIED; - } - break; - case DCERPC_AUTH_LEVEL_PRIVACY: - if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { - DEBUG(0,("Did not manage to negotiate mandetory feature " - "SIGN for dcerpc auth_level %u\n", - gensec_security->dcerpc_auth_level)); - return NT_STATUS_ACCESS_DENIED; + status = ops->update(gensec_security, out_mem_ctx, + ev, in, out); + if (!NT_STATUS_IS_OK(status)) { + return status; } - if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { - DEBUG(0,("Did not manage to negotiate mandetory feature " - "SEAL for dcerpc auth_level %u\n", - gensec_security->dcerpc_auth_level)); - return NT_STATUS_ACCESS_DENIED; + + /* + * Because callers using the + * gensec_start_mech_by_auth_type() never call + * gensec_want_feature(), it isn't sensible for them + * to have to call gensec_have_feature() manually, and + * these are not points of negotiation, but are + * asserted by the client + */ + switch (gensec_security->dcerpc_auth_level) { + case DCERPC_AUTH_LEVEL_INTEGRITY: + if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { + DEBUG(0,("Did not manage to negotiate mandetory feature " + "SIGN for dcerpc auth_level %u\n", + gensec_security->dcerpc_auth_level)); + return NT_STATUS_ACCESS_DENIED; + } + break; + case DCERPC_AUTH_LEVEL_PRIVACY: + if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { + DEBUG(0,("Did not manage to negotiate mandetory feature " + "SIGN for dcerpc auth_level %u\n", + gensec_security->dcerpc_auth_level)); + return NT_STATUS_ACCESS_DENIED; + } + if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { + DEBUG(0,("Did not manage to negotiate mandetory feature " + "SEAL for dcerpc auth_level %u\n", + gensec_security->dcerpc_auth_level)); + return NT_STATUS_ACCESS_DENIED; + } + break; + default: + break; } - break; - default: - break; + + return NT_STATUS_OK; } - return NT_STATUS_OK; + frame = talloc_stackframe(); + + subreq = ops->update_send(frame, ev, gensec_security, in); + if (subreq == NULL) { + goto fail; + } + ok = tevent_req_poll_ntstatus(subreq, ev, &status); + if (!ok) { + goto fail; + } + status = ops->update_recv(subreq, out_mem_ctx, out); + fail: + TALLOC_FREE(frame); + return status; } struct gensec_update_state { - struct tevent_immediate *im; + const struct gensec_security_ops *ops; + struct tevent_req *subreq; struct gensec_security *gensec_security; - DATA_BLOB in; DATA_BLOB out; + + /* + * only for sync backends, we should remove this + * once all backends are async. + */ + struct tevent_immediate *im; + DATA_BLOB in; }; static void gensec_update_async_trigger(struct tevent_context *ctx, struct tevent_immediate *im, void *private_data); +static void gensec_update_subreq_done(struct tevent_req *subreq); + /** * Next state function for the GENSEC state machine async version * @@ -298,17 +329,31 @@ _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx, return NULL; } - state->gensec_security = gensec_security; - state->in = in; - state->out = data_blob(NULL, 0); - state->im = tevent_create_immediate(state); - if (tevent_req_nomem(state->im, req)) { + state->ops = gensec_security->ops; + state->gensec_security = gensec_security; + + if (state->ops->update_send == NULL) { + state->in = in; + state->im = tevent_create_immediate(state); + if (tevent_req_nomem(state->im, req)) { + return tevent_req_post(req, ev); + } + + tevent_schedule_immediate(state->im, ev, + gensec_update_async_trigger, + req); + + return req; + } + + state->subreq = state->ops->update_send(state, ev, gensec_security, in); + if (tevent_req_nomem(state->subreq, req)) { return tevent_req_post(req, ev); } - tevent_schedule_immediate(state->im, ev, - gensec_update_async_trigger, - req); + tevent_req_set_callback(state->subreq, + gensec_update_subreq_done, + req); return req; } @@ -323,12 +368,71 @@ static void gensec_update_async_trigger(struct tevent_context *ctx, tevent_req_data(req, struct gensec_update_state); NTSTATUS status; - status = gensec_update(state->gensec_security, state, ctx, - state->in, &state->out); + status = state->ops->update(state->gensec_security, state, ctx, + state->in, &state->out); + if (tevent_req_nterror(req, status)) { + return; + } + + tevent_req_done(req); +} + +static void gensec_update_subreq_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct gensec_update_state *state = + tevent_req_data(req, + struct gensec_update_state); + NTSTATUS status; + + state->subreq = NULL; + + status = state->ops->update_recv(subreq, state, &state->out); + TALLOC_FREE(subreq); if (tevent_req_nterror(req, status)) { return; } + /* + * Because callers using the + * gensec_start_mech_by_authtype() never call + * gensec_want_feature(), it isn't sensible for them + * to have to call gensec_have_feature() manually, and + * these are not points of negotiation, but are + * asserted by the client + */ + switch (state->gensec_security->dcerpc_auth_level) { + case DCERPC_AUTH_LEVEL_INTEGRITY: + if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SIGN)) { + DEBUG(0,("Did not manage to negotiate mandetory feature " + "SIGN for dcerpc auth_level %u\n", + state->gensec_security->dcerpc_auth_level)); + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + break; + case DCERPC_AUTH_LEVEL_PRIVACY: + if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SIGN)) { + DEBUG(0,("Did not manage to negotiate mandetory feature " + "SIGN for dcerpc auth_level %u\n", + state->gensec_security->dcerpc_auth_level)); + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + if (!gensec_have_feature(state->gensec_security, GENSEC_FEATURE_SEAL)) { + DEBUG(0,("Did not manage to negotiate mandetory feature " + "SEAL for dcerpc auth_level %u\n", + state->gensec_security->dcerpc_auth_level)); + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + break; + default: + break; + } + tevent_req_done(req); } diff --git a/auth/gensec/gensec_internal.h b/auth/gensec/gensec_internal.h index 41b6f0d..c04164a 100644 --- a/auth/gensec/gensec_internal.h +++ b/auth/gensec/gensec_internal.h @@ -40,6 +40,13 @@ struct gensec_security_ops { NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, struct tevent_context *ev, const DATA_BLOB in, DATA_BLOB *out); + struct tevent_req *(*update_send)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct gensec_security *gensec_security, + const DATA_BLOB in); + NTSTATUS (*update_recv)(struct tevent_req *req, + TALLOC_CTX *out_mem_ctx, + DATA_BLOB *out); NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, uint8_t *data, size_t length, const uint8_t *whole_pdu, size_t pdu_length, -- 1.9.3 From aa559f2fc6f228fba268adafa92392dff8152747 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 11:10:55 +0200 Subject: [PATCH 087/249] auth/gensec: use 'const char * const *' for function parameters Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit c81b6f7448d7f945635784de645bea4f7f2e230f) --- auth/gensec/gensec.h | 2 +- auth/gensec/gensec_start.c | 2 +- auth/gensec/spnego.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h index 5d39d81..d0bc451 100644 --- a/auth/gensec/gensec.h +++ b/auth/gensec/gensec.h @@ -184,7 +184,7 @@ struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gense const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, - const char **oid_strings, + const char * const *oid_strings, const char *skip); const char **gensec_security_oids(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index 00e2759..2874c13 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -373,7 +373,7 @@ static const struct gensec_security_ops **gensec_security_by_sasl_list( _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, - const char **oid_strings, + const char * const *oid_strings, const char *skip) { struct gensec_security_ops_wrapper *backends_out; diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c index 38a45f8..0eb6da1 100644 --- a/auth/gensec/spnego.c +++ b/auth/gensec/spnego.c @@ -417,7 +417,7 @@ static NTSTATUS gensec_spnego_parse_negTokenInit(struct gensec_security *gensec_ struct spnego_state *spnego_state, TALLOC_CTX *out_mem_ctx, struct tevent_context *ev, - const char **mechType, + const char * const *mechType, const DATA_BLOB unwrapped_in, DATA_BLOB *unwrapped_out) { int i; -- 1.9.3 From a2e14962e1eeebaac2fb4539794a454b0f486869 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 11:20:21 +0200 Subject: [PATCH 088/249] auth/gensec: treat struct gensec_security_ops as const if possible. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 966faef9c61d2ec02d75fc3ccc82a61524fb77e4) --- auth/gensec/gensec.h | 14 +++++----- auth/gensec/gensec_start.c | 52 ++++++++++++++++++++------------------ auth/gensec/spnego.c | 8 +++--- source3/auth/auth_generic.c | 15 ++++++----- source3/libads/authdata.c | 11 ++++---- source3/libsmb/auth_generic.c | 15 ++++++----- source3/utils/ntlm_auth.c | 22 ++++++++-------- source4/ldap_server/ldap_backend.c | 4 +-- 8 files changed, 75 insertions(+), 66 deletions(-) diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h index d0bc451..ac1fadf 100644 --- a/auth/gensec/gensec.h +++ b/auth/gensec/gensec.h @@ -85,7 +85,7 @@ struct gensec_settings { /* this allows callers to specify a specific set of ops that * should be used, rather than those loaded by the plugin * mechanism */ - struct gensec_security_ops **backends; + const struct gensec_security_ops * const *backends; /* To fill in our own name in the NTLMSSP server */ const char *server_dns_domain; @@ -179,7 +179,7 @@ const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_sec const struct gensec_security_ops *gensec_security_by_auth_type( struct gensec_security *gensec_security, uint32_t auth_type); -struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security, +const struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx); const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( struct gensec_security *gensec_security, @@ -243,11 +243,11 @@ NTSTATUS gensec_wrap(struct gensec_security *gensec_security, const DATA_BLOB *in, DATA_BLOB *out); -struct gensec_security_ops **gensec_security_all(void); -bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security); -struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, - struct gensec_security_ops **old_gensec_list, - struct cli_credentials *creds); +const struct gensec_security_ops * const *gensec_security_all(void); +bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security); +const struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, + const struct gensec_security_ops * const *old_gensec_list, + struct cli_credentials *creds); NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security, const char *sasl_name); diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index 2874c13..3ae64d5 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -33,17 +33,17 @@ #include "lib/util/samba_modules.h" /* the list of currently registered GENSEC backends */ -static struct gensec_security_ops **generic_security_ops; +static const struct gensec_security_ops **generic_security_ops; static int gensec_num_backends; /* Return all the registered mechs. Don't modify the return pointer, - * but you may talloc_reference it if convient */ -_PUBLIC_ struct gensec_security_ops **gensec_security_all(void) + * but you may talloc_referen it if convient */ +_PUBLIC_ const struct gensec_security_ops * const *gensec_security_all(void) { return generic_security_ops; } -bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security) +bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security) { return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled); } @@ -68,11 +68,11 @@ bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_ * more compplex. */ -_PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, - struct gensec_security_ops **old_gensec_list, - struct cli_credentials *creds) +_PUBLIC_ const struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, + const struct gensec_security_ops * const *old_gensec_list, + struct cli_credentials *creds) { - struct gensec_security_ops **new_gensec_list; + const struct gensec_security_ops **new_gensec_list; int i, j, num_mechs_in; enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS; @@ -84,7 +84,9 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ /* noop */ } - new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1); + new_gensec_list = talloc_array(mem_ctx, + const struct gensec_security_ops *, + num_mechs_in + 1); if (!new_gensec_list) { return NULL; } @@ -136,12 +138,12 @@ _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ return new_gensec_list; } -_PUBLIC_ struct gensec_security_ops **gensec_security_mechs( +_PUBLIC_ const struct gensec_security_ops **gensec_security_mechs( struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx) { struct cli_credentials *creds = NULL; - struct gensec_security_ops **backends = gensec_security_all(); + const struct gensec_security_ops * const *backends = gensec_security_all(); if (gensec_security != NULL) { creds = gensec_get_credentials(gensec_security); @@ -159,7 +161,7 @@ static const struct gensec_security_ops *gensec_security_by_authtype(struct gens uint8_t auth_type) { int i; - struct gensec_security_ops **backends; + const struct gensec_security_ops **backends; const struct gensec_security_ops *backend; TALLOC_CTX *mem_ctx = talloc_new(gensec_security); if (!mem_ctx) { @@ -185,7 +187,7 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid( const char *oid_string) { int i, j; - struct gensec_security_ops **backends; + const struct gensec_security_ops **backends; const struct gensec_security_ops *backend; TALLOC_CTX *mem_ctx = talloc_new(gensec_security); if (!mem_ctx) { @@ -218,7 +220,7 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name( const char *sasl_name) { int i; - struct gensec_security_ops **backends; + const struct gensec_security_ops **backends; const struct gensec_security_ops *backend; TALLOC_CTX *mem_ctx = talloc_new(gensec_security); if (!mem_ctx) { @@ -245,7 +247,7 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type( uint32_t auth_type) { int i; - struct gensec_security_ops **backends; + const struct gensec_security_ops **backends; const struct gensec_security_ops *backend; TALLOC_CTX *mem_ctx = talloc_new(gensec_security); if (!mem_ctx) { @@ -270,7 +272,7 @@ static const struct gensec_security_ops *gensec_security_by_name(struct gensec_s const char *name) { int i; - struct gensec_security_ops **backends; + const struct gensec_security_ops **backends; const struct gensec_security_ops *backend; TALLOC_CTX *mem_ctx = talloc_new(gensec_security); if (!mem_ctx) { @@ -306,7 +308,7 @@ static const struct gensec_security_ops **gensec_security_by_sasl_list( const char **sasl_names) { const struct gensec_security_ops **backends_out; - struct gensec_security_ops **backends; + const struct gensec_security_ops **backends; int i, k, sasl_idx; int num_backends_out = 0; @@ -377,7 +379,7 @@ _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( const char *skip) { struct gensec_security_ops_wrapper *backends_out; - struct gensec_security_ops **backends; + const struct gensec_security_ops **backends; int i, j, k, oid_idx; int num_backends_out = 0; @@ -451,7 +453,7 @@ _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list( static const char **gensec_security_oids_from_ops( struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, - struct gensec_security_ops **ops, + const struct gensec_security_ops * const *ops, const char *skip) { int i; @@ -542,8 +544,10 @@ _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_securi TALLOC_CTX *mem_ctx, const char *skip) { - struct gensec_security_ops **ops - = gensec_security_mechs(gensec_security, mem_ctx); + const struct gensec_security_ops **ops; + + ops = gensec_security_mechs(gensec_security, mem_ctx); + return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip); } @@ -876,13 +880,13 @@ _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops) generic_security_ops = talloc_realloc(talloc_autofree_context(), generic_security_ops, - struct gensec_security_ops *, + const struct gensec_security_ops *, gensec_num_backends+2); if (!generic_security_ops) { return NT_STATUS_NO_MEMORY; } - generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops); + generic_security_ops[gensec_num_backends] = ops; gensec_num_backends++; generic_security_ops[gensec_num_backends] = NULL; @@ -908,7 +912,7 @@ _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void) return &critical_sizes; } -static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) { +static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) { return (*gs2)->priority - (*gs1)->priority; } diff --git a/auth/gensec/spnego.c b/auth/gensec/spnego.c index 0eb6da1..d90a50c 100644 --- a/auth/gensec/spnego.c +++ b/auth/gensec/spnego.c @@ -352,9 +352,11 @@ static NTSTATUS gensec_spnego_server_try_fallback(struct gensec_security *gensec const DATA_BLOB in, DATA_BLOB *out) { int i,j; - struct gensec_security_ops **all_ops - = gensec_security_mechs(gensec_security, out_mem_ctx); - for (i=0; all_ops[i]; i++) { + const struct gensec_security_ops **all_ops; + + all_ops = gensec_security_mechs(gensec_security, out_mem_ctx); + + for (i=0; all_ops && all_ops[i]; i++) { bool is_spnego; NTSTATUS nt_status; diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index a2ba4e3..e15c87e 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -203,6 +203,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, return nt_status; } } else { + const struct gensec_security_ops **backends = NULL; struct gensec_settings *gensec_settings; struct loadparm_context *lp_ctx; size_t idx = 0; @@ -259,24 +260,24 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - gensec_settings->backends = talloc_zero_array(gensec_settings, - struct gensec_security_ops *, 4); - if (gensec_settings->backends == NULL) { + backends = talloc_zero_array(gensec_settings, + const struct gensec_security_ops *, 4); + if (backends == NULL) { TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } + gensec_settings->backends = backends; gensec_init(); /* These need to be in priority order, krb5 before NTLMSSP */ #if defined(HAVE_KRB5) - gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; + backends[idx++] = &gensec_gse_krb5_security_ops; #endif - gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); + backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); - gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, - GENSEC_OID_SPNEGO); + backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); /* * This is anonymous for now, because we just use it diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 582917d..801e551 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -111,7 +111,7 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, const char *cc = "MEMORY:kerberos_return_pac"; struct auth_session_info *session_info; struct gensec_security *gensec_server_context; - + const struct gensec_security_ops **backends; struct gensec_settings *gensec_settings; size_t idx = 0; struct auth4_context *auth_context; @@ -230,16 +230,17 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, goto out; } - gensec_settings->backends = talloc_zero_array(gensec_settings, - struct gensec_security_ops *, 2); - if (gensec_settings->backends == NULL) { + backends = talloc_zero_array(gensec_settings, + const struct gensec_security_ops *, 2); + if (backends == NULL) { status = NT_STATUS_NO_MEMORY; goto out; } + gensec_settings->backends = backends; gensec_init(); - gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; + backends[idx++] = &gensec_gse_krb5_security_ops; status = gensec_server_start(tmp_ctx, gensec_settings, auth_context, &gensec_server_context); diff --git a/source3/libsmb/auth_generic.c b/source3/libsmb/auth_generic.c index ba0a0ce..e30c1b7 100644 --- a/source3/libsmb/auth_generic.c +++ b/source3/libsmb/auth_generic.c @@ -54,6 +54,7 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st NTSTATUS nt_status; size_t idx = 0; struct gensec_settings *gensec_settings; + const struct gensec_security_ops **backends = NULL; struct loadparm_context *lp_ctx; ans = talloc_zero(mem_ctx, struct auth_generic_state); @@ -76,24 +77,24 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st return NT_STATUS_NO_MEMORY; } - gensec_settings->backends = talloc_zero_array(gensec_settings, - struct gensec_security_ops *, 4); - if (gensec_settings->backends == NULL) { + backends = talloc_zero_array(gensec_settings, + const struct gensec_security_ops *, 4); + if (backends == NULL) { TALLOC_FREE(ans); return NT_STATUS_NO_MEMORY; } + gensec_settings->backends = backends; gensec_init(); /* These need to be in priority order, krb5 before NTLMSSP */ #if defined(HAVE_KRB5) - gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; + backends[idx++] = &gensec_gse_krb5_security_ops; #endif - gensec_settings->backends[idx++] = &gensec_ntlmssp3_client_ops; + backends[idx++] = &gensec_ntlmssp3_client_ops; - gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, - GENSEC_OID_SPNEGO); + backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); nt_status = gensec_client_start(ans, &ans->gensec_security, gensec_settings); diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 5fcb60e..25e717c 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -1035,7 +1035,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(TALLOC_CTX *mem_ctx, NTSTATUS nt_status; TALLOC_CTX *tmp_ctx; - + const struct gensec_security_ops **backends; struct gensec_settings *gensec_settings; size_t idx = 0; struct cli_credentials *server_credentials; @@ -1079,26 +1079,26 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(TALLOC_CTX *mem_ctx, gensec_settings->server_dns_name = strlower_talloc(gensec_settings, get_mydnsfullname()); - gensec_settings->backends = talloc_zero_array(gensec_settings, - struct gensec_security_ops *, 4); + backends = talloc_zero_array(gensec_settings, + const struct gensec_security_ops *, 4); - if (gensec_settings->backends == NULL) { + if (backends == NULL) { TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } - + gensec_settings->backends = backends; + gensec_init(); /* These need to be in priority order, krb5 before NTLMSSP */ #if defined(HAVE_KRB5) - gensec_settings->backends[idx++] = &gensec_gse_krb5_security_ops; + backends[idx++] = &gensec_gse_krb5_security_ops; #endif - - gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); - gensec_settings->backends[idx++] = gensec_security_by_oid(NULL, - GENSEC_OID_SPNEGO); - + backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP); + + backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); + /* * This is anonymous for now, because we just use it * to set the kerberos state at the moment diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c index f0da82c..3432594 100644 --- a/source4/ldap_server/ldap_backend.c +++ b/source4/ldap_server/ldap_backend.c @@ -192,8 +192,8 @@ NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn) if (conn->server_credentials) { char **sasl_mechs = NULL; - struct gensec_security_ops **backends = gensec_security_all(); - struct gensec_security_ops **ops + const struct gensec_security_ops * const *backends = gensec_security_all(); + const struct gensec_security_ops **ops = gensec_use_kerberos_mechs(conn, backends, conn->server_credentials); unsigned int i, j = 0; for (i = 0; ops && ops[i]; i++) { -- 1.9.3 From 6a58d4f4cb60bf25c1493ef0aedd5978abc06969 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 10:43:38 +0200 Subject: [PATCH 089/249] libcli/auth: avoid possible mem leak in read_negTokenInit() Also add error checks. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit f1e60142e12deb560e3c62441fd9ff2acd086b60) --- libcli/auth/spnego_parse.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c index 3bf7aea..2c73613 100644 --- a/libcli/auth/spnego_parse.c +++ b/libcli/auth/spnego_parse.c @@ -46,13 +46,24 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, asn1_start_tag(asn1, ASN1_CONTEXT(0)); asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - token->mechTypes = talloc(NULL, const char *); + token->mechTypes = talloc(mem_ctx, const char *); + if (token->mechTypes == NULL) { + asn1->has_error = true; + return false; + } for (i = 0; !asn1->has_error && 0 < asn1_tag_remaining(asn1); i++) { char *oid; - token->mechTypes = talloc_realloc(NULL, - token->mechTypes, - const char *, i+2); + const char **p; + p = talloc_realloc(mem_ctx, + token->mechTypes, + const char *, i+2); + if (p == NULL) { + TALLOC_FREE(token->mechTypes); + asn1->has_error = true; + return false; + } + token->mechTypes = p; asn1_read_OID(asn1, token->mechTypes, &oid); token->mechTypes[i] = oid; } -- 1.9.3 From 8835471a993521e49aa48ef55f324874e1933108 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Aug 2013 10:46:47 +0200 Subject: [PATCH 090/249] libcli/auth: add more const to spnego_negTokenInit->mechTypes Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Sat Aug 10 11:11:54 CEST 2013 on sn-devel-104 (cherry picked from commit 9177a0d1c1c92c45ef92fbda55fc6dd8aeb76b6c) --- libcli/auth/spnego.h | 2 +- libcli/auth/spnego_parse.c | 27 ++++++++++++++++----------- libcli/auth/spnego_proto.h | 2 +- source3/utils/ntlm_auth.c | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/libcli/auth/spnego.h b/libcli/auth/spnego.h index 9a93f2e..539b903 100644 --- a/libcli/auth/spnego.h +++ b/libcli/auth/spnego.h @@ -49,7 +49,7 @@ enum spnego_negResult { }; struct spnego_negTokenInit { - const char **mechTypes; + const char * const *mechTypes; DATA_BLOB reqFlags; uint8_t reqFlagsPadding; DATA_BLOB mechToken; diff --git a/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c index 2c73613..b1ca07d 100644 --- a/libcli/auth/spnego_parse.c +++ b/libcli/auth/spnego_parse.c @@ -42,12 +42,14 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, switch (context) { /* Read mechTypes */ - case ASN1_CONTEXT(0): + case ASN1_CONTEXT(0): { + const char **mechTypes; + asn1_start_tag(asn1, ASN1_CONTEXT(0)); asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - token->mechTypes = talloc(mem_ctx, const char *); - if (token->mechTypes == NULL) { + mechTypes = talloc(mem_ctx, const char *); + if (mechTypes == NULL) { asn1->has_error = true; return false; } @@ -56,22 +58,25 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, char *oid; const char **p; p = talloc_realloc(mem_ctx, - token->mechTypes, + mechTypes, const char *, i+2); if (p == NULL) { - TALLOC_FREE(token->mechTypes); + talloc_free(mechTypes); asn1->has_error = true; return false; } - token->mechTypes = p; - asn1_read_OID(asn1, token->mechTypes, &oid); - token->mechTypes[i] = oid; + mechTypes = p; + + asn1_read_OID(asn1, mechTypes, &oid); + mechTypes[i] = oid; } - token->mechTypes[i] = NULL; + mechTypes[i] = NULL; + token->mechTypes = mechTypes; asn1_end_tag(asn1); asn1_end_tag(asn1); break; + } /* Read reqFlags */ case ASN1_CONTEXT(1): asn1_start_tag(asn1, ASN1_CONTEXT(1)); @@ -366,7 +371,7 @@ bool spnego_free_data(struct spnego_data *spnego) switch(spnego->type) { case SPNEGO_NEG_TOKEN_INIT: if (spnego->negTokenInit.mechTypes) { - talloc_free(spnego->negTokenInit.mechTypes); + talloc_free(discard_const(spnego->negTokenInit.mechTypes)); } data_blob_free(&spnego->negTokenInit.reqFlags); data_blob_free(&spnego->negTokenInit.mechToken); @@ -390,7 +395,7 @@ out: } bool spnego_write_mech_types(TALLOC_CTX *mem_ctx, - const char **mech_types, + const char * const *mech_types, DATA_BLOB *blob) { struct asn1_data *asn1 = asn1_init(mem_ctx); diff --git a/libcli/auth/spnego_proto.h b/libcli/auth/spnego_proto.h index 5fd5e59..c0fa934 100644 --- a/libcli/auth/spnego_proto.h +++ b/libcli/auth/spnego_proto.h @@ -24,5 +24,5 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_data *spnego); bool spnego_free_data(struct spnego_data *spnego); bool spnego_write_mech_types(TALLOC_CTX *mem_ctx, - const char **mech_types, + const char * const *mech_types, DATA_BLOB *blob); diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 25e717c..1df615c 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -2058,7 +2058,7 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper /* The server offers a list of mechanisms */ - const char **mechType = (const char **)spnego.negTokenInit.mechTypes; + const char *const *mechType = spnego.negTokenInit.mechTypes; while (*mechType != NULL) { -- 1.9.3 From c06bb0c3d2c032f8b4848c75baa1fd900650866a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 9 Aug 2013 10:15:05 +0200 Subject: [PATCH 091/249] auth/credentials: make sure cli_credentials_get_nt_hash() always returns a talloc object Signed-off-by: Stefan Metzmacher --- auth/credentials/credentials.c | 19 ++++++++++++++----- auth/credentials/credentials.h | 4 ++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index be497bc..57a7c0b 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -471,8 +471,8 @@ _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred, * @param cred credentials context * @retval If set, the cleartext password, otherwise NULL */ -_PUBLIC_ const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, - TALLOC_CTX *mem_ctx) +_PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, + TALLOC_CTX *mem_ctx) { const char *password = cli_credentials_get_password(cred); @@ -481,13 +481,22 @@ _PUBLIC_ const struct samr_Password *cli_credentials_get_nt_hash(struct cli_cred if (!nt_hash) { return NULL; } - + E_md4hash(password, nt_hash->hash); return nt_hash; - } else { - return cred->nt_hash; + } else if (cred->nt_hash != NULL) { + struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password); + if (!nt_hash) { + return NULL; + } + + *nt_hash = *cred->nt_hash; + + return nt_hash; } + + return NULL; } /** diff --git a/auth/credentials/credentials.h b/auth/credentials/credentials.h index cb09dc3..766a513 100644 --- a/auth/credentials/credentials.h +++ b/auth/credentials/credentials.h @@ -141,8 +141,8 @@ bool cli_credentials_set_password(struct cli_credentials *cred, enum credentials_obtained obtained); struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx); void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained); -const struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, - TALLOC_CTX *mem_ctx); +struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred, + TALLOC_CTX *mem_ctx); bool cli_credentials_set_realm(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained); -- 1.9.3 From 8a3ed9f72ef9f9de32da4d454b866d64eb24ee17 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 17 Sep 2013 13:09:50 -0700 Subject: [PATCH 092/249] Add SASL/EXTERNAL gensec module Signed-off-by: Howard Chu Reviewed-by: Andrew Bartlett Reviewed-by: Nadezhda Ivanova (cherry picked from commit 6bf59b03d72b94b71e53fc2404c11e0d237e41b2) --- auth/gensec/external.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ auth/gensec/gensec.h | 3 +- auth/gensec/wscript_build | 7 ++++ 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 auth/gensec/external.c diff --git a/auth/gensec/external.c b/auth/gensec/external.c new file mode 100644 index 0000000..a26e435 --- /dev/null +++ b/auth/gensec/external.c @@ -0,0 +1,82 @@ +/* + Unix SMB/CIFS implementation. + + SASL/EXTERNAL authentication. + + Copyright (C) Howard Chu 2013 + + 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 "includes.h" +#include "auth/credentials/credentials.h" +#include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" +#include "auth/gensec/gensec_proto.h" +#include "auth/gensec/gensec_toplevel_proto.h" + +/* SASL/EXTERNAL is essentially a no-op; it is only usable when the transport + * layer is already mutually authenticated. + */ + +NTSTATUS gensec_external_init(void); + +static NTSTATUS gensec_external_start(struct gensec_security *gensec_security) +{ + if (gensec_security->want_features & GENSEC_FEATURE_SIGN) + return NT_STATUS_INVALID_PARAMETER; + if (gensec_security->want_features & GENSEC_FEATURE_SEAL) + return NT_STATUS_INVALID_PARAMETER; + + return NT_STATUS_OK; +} + +static NTSTATUS gensec_external_update(struct gensec_security *gensec_security, + TALLOC_CTX *out_mem_ctx, + struct tevent_context *ev, + const DATA_BLOB in, DATA_BLOB *out) +{ + *out = data_blob_talloc(out_mem_ctx, "", 0); + return NT_STATUS_OK; +} + +/* We have no features */ +static bool gensec_external_have_feature(struct gensec_security *gensec_security, + uint32_t feature) +{ + return false; +} + +static const struct gensec_security_ops gensec_external_ops = { + .name = "sasl-EXTERNAL", + .sasl_name = "EXTERNAL", + .client_start = gensec_external_start, + .update = gensec_external_update, + .have_feature = gensec_external_have_feature, + .enabled = true, + .priority = GENSEC_EXTERNAL +}; + + +NTSTATUS gensec_external_init(void) +{ + NTSTATUS ret; + + ret = gensec_register(&gensec_external_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' gensec backend!\n", + gensec_external_ops.name)); + } + return ret; +} diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h index ac1fadf..6974f87 100644 --- a/auth/gensec/gensec.h +++ b/auth/gensec/gensec.h @@ -41,7 +41,8 @@ enum gensec_priority { GENSEC_SCHANNEL = 60, GENSEC_NTLMSSP = 50, GENSEC_SASL = 20, - GENSEC_OTHER = 0 + GENSEC_OTHER = 10, + GENSEC_EXTERNAL = 0 }; struct gensec_security; diff --git a/auth/gensec/wscript_build b/auth/gensec/wscript_build index fcd74a3..71222f7 100755 --- a/auth/gensec/wscript_build +++ b/auth/gensec/wscript_build @@ -16,3 +16,10 @@ bld.SAMBA_MODULE('gensec_spnego', init_function='gensec_spnego_init', deps='asn1util samba-credentials SPNEGO_PARSE' ) + +bld.SAMBA_MODULE('gensec_external', + source='external.c', + autoproto='external_proto.h', + subsystem='gensec', + init_function='gensec_external_init' + ) -- 1.9.3 From 75d9566940069ebeb367191ec6a6641bf7d45a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 17:24:10 +0200 Subject: [PATCH 093/249] gensec: move schannel module to toplevel. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit 4d2ec9e37ee9dcf7b521806a1c0aabdffe524d47) --- auth/gensec/schannel.c | 330 ++++++++++++++++++++++++++++++++++++++ auth/gensec/wscript_build | 8 + source4/auth/gensec/schannel.c | 330 -------------------------------------- source4/auth/gensec/wscript_build | 10 -- 4 files changed, 338 insertions(+), 340 deletions(-) create mode 100644 auth/gensec/schannel.c delete mode 100644 source4/auth/gensec/schannel.c diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c new file mode 100644 index 0000000..eb2e100 --- /dev/null +++ b/auth/gensec/schannel.c @@ -0,0 +1,330 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc schannel operations + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Andrew Bartlett 2004-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 + (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 "includes.h" +#include "librpc/gen_ndr/ndr_schannel.h" +#include "auth/auth.h" +#include "auth/credentials/credentials.h" +#include "auth/gensec/gensec.h" +#include "auth/gensec/gensec_internal.h" +#include "auth/gensec/gensec_proto.h" +#include "../libcli/auth/schannel.h" +#include "librpc/gen_ndr/dcerpc.h" +#include "param/param.h" +#include "auth/gensec/gensec_toplevel_proto.h" + +_PUBLIC_ NTSTATUS gensec_schannel_init(void); + +static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size) +{ + struct schannel_state *state = + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); + + return netsec_outgoing_sig_size(state); +} + +static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, + struct tevent_context *ev, + const DATA_BLOB in, DATA_BLOB *out) +{ + struct schannel_state *state = + talloc_get_type(gensec_security->private_data, + struct schannel_state); + NTSTATUS status; + enum ndr_err_code ndr_err; + struct NL_AUTH_MESSAGE bind_schannel; + struct NL_AUTH_MESSAGE bind_schannel_ack; + struct netlogon_creds_CredentialState *creds; + const char *workstation; + const char *domain; + + *out = data_blob(NULL, 0); + + switch (gensec_security->gensec_role) { + case GENSEC_CLIENT: + if (state != NULL) { + /* we could parse the bind ack, but we don't know what it is yet */ + return NT_STATUS_OK; + } + + creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); + if (creds == NULL) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + state = netsec_create_state(gensec_security, + creds, true /* initiator */); + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } + gensec_security->private_data = state; + + bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; +#if 0 + /* to support this we'd need to have access to the full domain name */ + /* 0x17, 23 */ + bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | + NL_FLAG_OEM_NETBIOS_COMPUTER_NAME | + NL_FLAG_UTF8_DNS_DOMAIN_NAME | + NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; + bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); + bind_schannel.oem_netbios_computer.a = creds->computer_name; + bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); + /* w2k3 refuses us if we use the full DNS workstation? + why? perhaps because we don't fill in the dNSHostName + attribute in the machine account? */ + bind_schannel.utf8_netbios_computer = creds->computer_name; +#else + bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | + NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; + bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); + bind_schannel.oem_netbios_computer.a = creds->computer_name; +#endif + + ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, + (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + DEBUG(3, ("Could not create schannel bind: %s\n", + nt_errstr(status))); + return status; + } + + return NT_STATUS_MORE_PROCESSING_REQUIRED; + case GENSEC_SERVER: + + if (state != NULL) { + /* no third leg on this protocol */ + return NT_STATUS_INVALID_PARAMETER; + } + + /* parse the schannel startup blob */ + ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel, + (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + DEBUG(3, ("Could not parse incoming schannel bind: %s\n", + nt_errstr(status))); + return status; + } + + if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) { + domain = bind_schannel.oem_netbios_domain.a; + if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) { + DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", + domain, lpcfg_workgroup(gensec_security->settings->lp_ctx))); + return NT_STATUS_LOGON_FAILURE; + } + } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) { + domain = bind_schannel.utf8_dns_domain.u; + if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) { + DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", + domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx))); + return NT_STATUS_LOGON_FAILURE; + } + } else { + DEBUG(3, ("Request for schannel to without domain\n")); + return NT_STATUS_LOGON_FAILURE; + } + + if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) { + workstation = bind_schannel.oem_netbios_computer.a; + } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) { + workstation = bind_schannel.utf8_netbios_computer.u; + } else { + DEBUG(3, ("Request for schannel to without netbios workstation\n")); + return NT_STATUS_LOGON_FAILURE; + } + + status = schannel_get_creds_state(out_mem_ctx, + gensec_security->settings->lp_ctx, + workstation, &creds); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", + workstation, nt_errstr(status))); + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { + return NT_STATUS_LOGON_FAILURE; + } + return status; + } + + state = netsec_create_state(gensec_security, + creds, false /* not initiator */); + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } + gensec_security->private_data = state; + + bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; + bind_schannel_ack.Flags = 0; + bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think + * this does not have + * any meaning here + * - gd */ + + ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack, + (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", + workstation, nt_errstr(status))); + return status; + } + + return NT_STATUS_OK; + } + return NT_STATUS_INVALID_PARAMETER; +} + +/** + * Returns anonymous credentials for schannel, matching Win2k3. + * + */ + +static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + struct auth_session_info **_session_info) +{ + return auth_anonymous_session_info(mem_ctx, gensec_security->settings->lp_ctx, _session_info); +} + +static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) +{ + return NT_STATUS_OK; +} + +static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) +{ + return NT_STATUS_OK; +} + +static bool schannel_have_feature(struct gensec_security *gensec_security, + uint32_t feature) +{ + if (feature & (GENSEC_FEATURE_SIGN | + GENSEC_FEATURE_SEAL)) { + return true; + } + if (feature & GENSEC_FEATURE_DCE_STYLE) { + return true; + } + return false; +} + +/* + unseal a packet +*/ +static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, + uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig) +{ + struct schannel_state *state = + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); + + return netsec_incoming_packet(state, true, + discard_const_p(uint8_t, data), + length, sig); +} + +/* + check the signature on a packet +*/ +static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, + const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig) +{ + struct schannel_state *state = + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); + + return netsec_incoming_packet(state, false, + discard_const_p(uint8_t, data), + length, sig); +} +/* + seal a packet +*/ +static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + DATA_BLOB *sig) +{ + struct schannel_state *state = + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); + + return netsec_outgoing_packet(state, mem_ctx, true, + data, length, sig); +} + +/* + sign a packet +*/ +static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, + TALLOC_CTX *mem_ctx, + const uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, + DATA_BLOB *sig) +{ + struct schannel_state *state = + talloc_get_type_abort(gensec_security->private_data, + struct schannel_state); + + return netsec_outgoing_packet(state, mem_ctx, false, + discard_const_p(uint8_t, data), + length, sig); +} + +static const struct gensec_security_ops gensec_schannel_security_ops = { + .name = "schannel", + .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, + .client_start = schannel_client_start, + .server_start = schannel_server_start, + .update = schannel_update, + .seal_packet = schannel_seal_packet, + .sign_packet = schannel_sign_packet, + .check_packet = schannel_check_packet, + .unseal_packet = schannel_unseal_packet, + .session_info = schannel_session_info, + .sig_size = schannel_sig_size, + .have_feature = schannel_have_feature, + .enabled = true, + .priority = GENSEC_SCHANNEL +}; + +_PUBLIC_ NTSTATUS gensec_schannel_init(void) +{ + NTSTATUS ret; + ret = gensec_register(&gensec_schannel_security_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register '%s' gensec backend!\n", + gensec_schannel_security_ops.name)); + return ret; + } + + return ret; +} diff --git a/auth/gensec/wscript_build b/auth/gensec/wscript_build index 71222f7..7329eec 100755 --- a/auth/gensec/wscript_build +++ b/auth/gensec/wscript_build @@ -17,6 +17,14 @@ bld.SAMBA_MODULE('gensec_spnego', deps='asn1util samba-credentials SPNEGO_PARSE' ) +bld.SAMBA_MODULE('gensec_schannel', + source='schannel.c', + autoproto='schannel_proto.h', + subsystem='gensec', + init_function='gensec_schannel_init', + deps='COMMON_SCHANNEL NDR_SCHANNEL samba-credentials auth_session' + ) + bld.SAMBA_MODULE('gensec_external', source='external.c', autoproto='external_proto.h', diff --git a/source4/auth/gensec/schannel.c b/source4/auth/gensec/schannel.c deleted file mode 100644 index eb2e100..0000000 --- a/source4/auth/gensec/schannel.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - dcerpc schannel operations - - Copyright (C) Andrew Tridgell 2004 - Copyright (C) Andrew Bartlett 2004-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 - (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 "includes.h" -#include "librpc/gen_ndr/ndr_schannel.h" -#include "auth/auth.h" -#include "auth/credentials/credentials.h" -#include "auth/gensec/gensec.h" -#include "auth/gensec/gensec_internal.h" -#include "auth/gensec/gensec_proto.h" -#include "../libcli/auth/schannel.h" -#include "librpc/gen_ndr/dcerpc.h" -#include "param/param.h" -#include "auth/gensec/gensec_toplevel_proto.h" - -_PUBLIC_ NTSTATUS gensec_schannel_init(void); - -static size_t schannel_sig_size(struct gensec_security *gensec_security, size_t data_size) -{ - struct schannel_state *state = - talloc_get_type_abort(gensec_security->private_data, - struct schannel_state); - - return netsec_outgoing_sig_size(state); -} - -static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, - struct tevent_context *ev, - const DATA_BLOB in, DATA_BLOB *out) -{ - struct schannel_state *state = - talloc_get_type(gensec_security->private_data, - struct schannel_state); - NTSTATUS status; - enum ndr_err_code ndr_err; - struct NL_AUTH_MESSAGE bind_schannel; - struct NL_AUTH_MESSAGE bind_schannel_ack; - struct netlogon_creds_CredentialState *creds; - const char *workstation; - const char *domain; - - *out = data_blob(NULL, 0); - - switch (gensec_security->gensec_role) { - case GENSEC_CLIENT: - if (state != NULL) { - /* we could parse the bind ack, but we don't know what it is yet */ - return NT_STATUS_OK; - } - - creds = cli_credentials_get_netlogon_creds(gensec_security->credentials); - if (creds == NULL) { - return NT_STATUS_INVALID_PARAMETER_MIX; - } - - state = netsec_create_state(gensec_security, - creds, true /* initiator */); - if (state == NULL) { - return NT_STATUS_NO_MEMORY; - } - gensec_security->private_data = state; - - bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; -#if 0 - /* to support this we'd need to have access to the full domain name */ - /* 0x17, 23 */ - bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | - NL_FLAG_OEM_NETBIOS_COMPUTER_NAME | - NL_FLAG_UTF8_DNS_DOMAIN_NAME | - NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME; - bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); - bind_schannel.oem_netbios_computer.a = creds->computer_name; - bind_schannel.utf8_dns_domain = cli_credentials_get_realm(gensec_security->credentials); - /* w2k3 refuses us if we use the full DNS workstation? - why? perhaps because we don't fill in the dNSHostName - attribute in the machine account? */ - bind_schannel.utf8_netbios_computer = creds->computer_name; -#else - bind_schannel.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | - NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; - bind_schannel.oem_netbios_domain.a = cli_credentials_get_domain(gensec_security->credentials); - bind_schannel.oem_netbios_computer.a = creds->computer_name; -#endif - - ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel, - (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - status = ndr_map_error2ntstatus(ndr_err); - DEBUG(3, ("Could not create schannel bind: %s\n", - nt_errstr(status))); - return status; - } - - return NT_STATUS_MORE_PROCESSING_REQUIRED; - case GENSEC_SERVER: - - if (state != NULL) { - /* no third leg on this protocol */ - return NT_STATUS_INVALID_PARAMETER; - } - - /* parse the schannel startup blob */ - ndr_err = ndr_pull_struct_blob(&in, out_mem_ctx, &bind_schannel, - (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - status = ndr_map_error2ntstatus(ndr_err); - DEBUG(3, ("Could not parse incoming schannel bind: %s\n", - nt_errstr(status))); - return status; - } - - if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_DOMAIN_NAME) { - domain = bind_schannel.oem_netbios_domain.a; - if (strcasecmp_m(domain, lpcfg_workgroup(gensec_security->settings->lp_ctx)) != 0) { - DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", - domain, lpcfg_workgroup(gensec_security->settings->lp_ctx))); - return NT_STATUS_LOGON_FAILURE; - } - } else if (bind_schannel.Flags & NL_FLAG_UTF8_DNS_DOMAIN_NAME) { - domain = bind_schannel.utf8_dns_domain.u; - if (strcasecmp_m(domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx)) != 0) { - DEBUG(3, ("Request for schannel to incorrect domain: %s != our domain %s\n", - domain, lpcfg_dnsdomain(gensec_security->settings->lp_ctx))); - return NT_STATUS_LOGON_FAILURE; - } - } else { - DEBUG(3, ("Request for schannel to without domain\n")); - return NT_STATUS_LOGON_FAILURE; - } - - if (bind_schannel.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME) { - workstation = bind_schannel.oem_netbios_computer.a; - } else if (bind_schannel.Flags & NL_FLAG_UTF8_NETBIOS_COMPUTER_NAME) { - workstation = bind_schannel.utf8_netbios_computer.u; - } else { - DEBUG(3, ("Request for schannel to without netbios workstation\n")); - return NT_STATUS_LOGON_FAILURE; - } - - status = schannel_get_creds_state(out_mem_ctx, - gensec_security->settings->lp_ctx, - workstation, &creds); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not find session key for attempted schannel connection from %s: %s\n", - workstation, nt_errstr(status))); - if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { - return NT_STATUS_LOGON_FAILURE; - } - return status; - } - - state = netsec_create_state(gensec_security, - creds, false /* not initiator */); - if (state == NULL) { - return NT_STATUS_NO_MEMORY; - } - gensec_security->private_data = state; - - bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; - bind_schannel_ack.Flags = 0; - bind_schannel_ack.Buffer.dummy = 0x6c0000; /* actually I think - * this does not have - * any meaning here - * - gd */ - - ndr_err = ndr_push_struct_blob(out, out_mem_ctx, &bind_schannel_ack, - (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - status = ndr_map_error2ntstatus(ndr_err); - DEBUG(3, ("Could not return schannel bind ack for client %s: %s\n", - workstation, nt_errstr(status))); - return status; - } - - return NT_STATUS_OK; - } - return NT_STATUS_INVALID_PARAMETER; -} - -/** - * Returns anonymous credentials for schannel, matching Win2k3. - * - */ - -static NTSTATUS schannel_session_info(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - struct auth_session_info **_session_info) -{ - return auth_anonymous_session_info(mem_ctx, gensec_security->settings->lp_ctx, _session_info); -} - -static NTSTATUS schannel_server_start(struct gensec_security *gensec_security) -{ - return NT_STATUS_OK; -} - -static NTSTATUS schannel_client_start(struct gensec_security *gensec_security) -{ - return NT_STATUS_OK; -} - -static bool schannel_have_feature(struct gensec_security *gensec_security, - uint32_t feature) -{ - if (feature & (GENSEC_FEATURE_SIGN | - GENSEC_FEATURE_SEAL)) { - return true; - } - if (feature & GENSEC_FEATURE_DCE_STYLE) { - return true; - } - return false; -} - -/* - unseal a packet -*/ -static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - const DATA_BLOB *sig) -{ - struct schannel_state *state = - talloc_get_type_abort(gensec_security->private_data, - struct schannel_state); - - return netsec_incoming_packet(state, true, - discard_const_p(uint8_t, data), - length, sig); -} - -/* - check the signature on a packet -*/ -static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - const DATA_BLOB *sig) -{ - struct schannel_state *state = - talloc_get_type_abort(gensec_security->private_data, - struct schannel_state); - - return netsec_incoming_packet(state, false, - discard_const_p(uint8_t, data), - length, sig); -} -/* - seal a packet -*/ -static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) -{ - struct schannel_state *state = - talloc_get_type_abort(gensec_security->private_data, - struct schannel_state); - - return netsec_outgoing_packet(state, mem_ctx, true, - data, length, sig); -} - -/* - sign a packet -*/ -static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, - TALLOC_CTX *mem_ctx, - const uint8_t *data, size_t length, - const uint8_t *whole_pdu, size_t pdu_length, - DATA_BLOB *sig) -{ - struct schannel_state *state = - talloc_get_type_abort(gensec_security->private_data, - struct schannel_state); - - return netsec_outgoing_packet(state, mem_ctx, false, - discard_const_p(uint8_t, data), - length, sig); -} - -static const struct gensec_security_ops gensec_schannel_security_ops = { - .name = "schannel", - .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, - .client_start = schannel_client_start, - .server_start = schannel_server_start, - .update = schannel_update, - .seal_packet = schannel_seal_packet, - .sign_packet = schannel_sign_packet, - .check_packet = schannel_check_packet, - .unseal_packet = schannel_unseal_packet, - .session_info = schannel_session_info, - .sig_size = schannel_sig_size, - .have_feature = schannel_have_feature, - .enabled = true, - .priority = GENSEC_SCHANNEL -}; - -_PUBLIC_ NTSTATUS gensec_schannel_init(void) -{ - NTSTATUS ret; - ret = gensec_register(&gensec_schannel_security_ops); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register '%s' gensec backend!\n", - gensec_schannel_security_ops.name)); - return ret; - } - - return ret; -} diff --git a/source4/auth/gensec/wscript_build b/source4/auth/gensec/wscript_build index 04fccc5..a3eff97 100755 --- a/source4/auth/gensec/wscript_build +++ b/source4/auth/gensec/wscript_build @@ -32,16 +32,6 @@ bld.SAMBA_MODULE('cyrus_sasl', ) -bld.SAMBA_MODULE('gensec_schannel', - source='schannel.c', - subsystem='gensec', - deps='COMMON_SCHANNEL NDR_SCHANNEL samba-credentials ndr auth_session', - internal_module=True, - autoproto='schannel_proto.h', - init_function='gensec_schannel_init' - ) - - bld.SAMBA_PYTHON('pygensec', source='pygensec.c', deps='gensec pytalloc-util pyparam_util', -- 1.9.3 From c4829848f45db27d6c145b35a20bea2f33bcb4d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 17:24:49 +0200 Subject: [PATCH 094/249] gensec: remove duplicate gensec_security_by_authtype() call. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should use the equivalent gensec_security_by_auth_type() call which is exposed in the public header. Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit d433ad077f354de4fc1d5a155d991f417ae9967c) --- auth/gensec/gensec_start.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index 3ae64d5..906ef67 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -157,31 +157,6 @@ _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs( } -static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security, - uint8_t auth_type) -{ - int i; - const struct gensec_security_ops **backends; - const struct gensec_security_ops *backend; - TALLOC_CTX *mem_ctx = talloc_new(gensec_security); - if (!mem_ctx) { - return NULL; - } - backends = gensec_security_mechs(gensec_security, mem_ctx); - for (i=0; backends && backends[i]; i++) { - if (!gensec_security_ops_enabled(backends[i], gensec_security)) - continue; - if (backends[i]->auth_type == auth_type) { - backend = backends[i]; - talloc_free(mem_ctx); - return backend; - } - } - talloc_free(mem_ctx); - - return NULL; -} - _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid( struct gensec_security *gensec_security, const char *oid_string) @@ -719,7 +694,7 @@ NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security, _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security, uint8_t auth_type, uint8_t auth_level) { - gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type); + gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type); if (!gensec_security->ops) { DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type)); return NT_STATUS_INVALID_PARAMETER; @@ -746,7 +721,7 @@ _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_s _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype) { const struct gensec_security_ops *ops; - ops = gensec_security_by_authtype(gensec_security, authtype); + ops = gensec_security_by_auth_type(gensec_security, authtype); if (ops) { return ops->name; } -- 1.9.3 From 8c54d2ee4861a35def7cce29b900a68112356f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 17:25:55 +0200 Subject: [PATCH 095/249] gensec: check for NULL gensec_security in gensec_security_by_auth_type(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have equivalent checks in other gensec_security_by_X calls already. Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit 4f979525e4137c536118a9c2b2b4ef798c270e27) --- auth/gensec/gensec_start.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index 906ef67..476134a 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -230,8 +230,10 @@ _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type( } backends = gensec_security_mechs(gensec_security, mem_ctx); for (i=0; backends && backends[i]; i++) { - if (!gensec_security_ops_enabled(backends[i], gensec_security)) - continue; + if (gensec_security != NULL && + !gensec_security_ops_enabled(backends[i], gensec_security)) { + continue; + } if (backends[i]->auth_type == auth_type) { backend = backends[i]; talloc_free(mem_ctx); -- 1.9.3 From 5b941811c7ebd51bf2c8d421517fd92b3065ba47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 17:27:28 +0200 Subject: [PATCH 096/249] s3-auth: also load schannel module from auth_generic_client_prepare(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit 8fce75aa58ec70547ad218bde154e141f2d17303) --- source3/libsmb/auth_generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/libsmb/auth_generic.c b/source3/libsmb/auth_generic.c index e30c1b7..3130dec 100644 --- a/source3/libsmb/auth_generic.c +++ b/source3/libsmb/auth_generic.c @@ -78,7 +78,7 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st } backends = talloc_zero_array(gensec_settings, - const struct gensec_security_ops *, 4); + const struct gensec_security_ops *, 5); if (backends == NULL) { TALLOC_FREE(ans); return NT_STATUS_NO_MEMORY; @@ -95,6 +95,7 @@ NTSTATUS auth_generic_client_prepare(TALLOC_CTX *mem_ctx, struct auth_generic_st backends[idx++] = &gensec_ntlmssp3_client_ops; backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); + backends[idx++] = gensec_security_by_auth_type(NULL, DCERPC_AUTH_TYPE_SCHANNEL); nt_status = gensec_client_start(ans, &ans->gensec_security, gensec_settings); -- 1.9.3 From 28b5f156bcc03b88f8c0f3e52cd051a0b069334e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 17:44:10 +0200 Subject: [PATCH 097/249] s3-rpc_cli: allow to pass down a netlogon CredentialState struct to gensec. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit 7b570b4128f9af212048ce56abd841a1f6fdc259) --- source3/rpc_client/cli_pipe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 470469f..2acbad6 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2178,6 +2178,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, const char *username, const char *password, enum credentials_use_kerberos use_kerberos, + struct netlogon_creds_CredentialState *creds, struct pipe_auth_data **presult) { struct auth_generic_state *auth_generic_ctx; @@ -2231,6 +2232,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, } cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos); + cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds); status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level); if (!NT_STATUS_IS_OK(status)) { @@ -2830,6 +2832,7 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, server, target_service, domain, username, password, CRED_AUTO_USE_KERBEROS, + NULL, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpccli_generic_bind_data returned %s\n", @@ -3057,7 +3060,7 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, DCERPC_AUTH_TYPE_SPNEGO, auth_level, server, target_service, domain, username, password, - use_kerberos, + use_kerberos, NULL, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpccli_generic_bind_data returned %s\n", -- 1.9.3 From 4775b3fd2905e54b2c824d901fd8a99fb8caae04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 18:23:40 +0200 Subject: [PATCH 098/249] s3-auth: register schannel gensec module in auth_generic_prepare() as well. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit 090671aca5234f47f390054de771198e3c177060) --- source3/auth/auth_generic.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index e15c87e..e07d3b7 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -32,6 +32,7 @@ #include "librpc/crypto/gse.h" #include "auth/credentials/credentials.h" #include "lib/param/loadparm.h" +#include "librpc/gen_ndr/dcerpc.h" static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, TALLOC_CTX *mem_ctx, @@ -261,7 +262,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, } backends = talloc_zero_array(gensec_settings, - const struct gensec_security_ops *, 4); + const struct gensec_security_ops *, 5); if (backends == NULL) { TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; @@ -279,6 +280,8 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO); + backends[idx++] = gensec_security_by_auth_type(NULL, DCERPC_AUTH_TYPE_SCHANNEL); + /* * This is anonymous for now, because we just use it * to set the kerberos state at the moment -- 1.9.3 From 080c2ac3cbd28318bc6c682dff0aea17fad07a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 18:33:14 +0200 Subject: [PATCH 099/249] s3-rpc_cli: use gensec for schannel bind. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit 89d0b89b5d58ceef13bc10036d396b10f8a102ae) --- source3/rpc_client/cli_pipe.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 2acbad6..8a642e2 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1120,12 +1120,6 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, switch (auth->auth_type) { case DCERPC_AUTH_TYPE_SCHANNEL: - ret = create_schannel_auth_rpc_bind_req(cli, &auth_token); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - break; - case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_SPNEGO: @@ -2884,16 +2878,26 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct netr_Authenticator auth; struct netr_Authenticator return_auth; union netr_Capabilities capabilities; + const char *target_service = table->authservices->names[0]; status = cli_rpc_pipe_open(cli, transport, table, &rpccli); if (!NT_STATUS_IS_OK(status)) { return status; } - status = rpccli_schannel_bind_data(rpccli, domain, auth_level, - *pdc, &rpcauth); + status = rpccli_generic_bind_data(rpccli, + DCERPC_AUTH_TYPE_SCHANNEL, + auth_level, + NULL, + target_service, + domain, + (*pdc)->computer_name, + NULL, + CRED_AUTO_USE_KERBEROS, + *pdc, + &rpcauth); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("rpccli_schannel_bind_data returned %s\n", + DEBUG(0, ("rpccli_generic_bind_data returned %s\n", nt_errstr(status))); TALLOC_FREE(rpccli); return status; -- 1.9.3 From 40ffd89f975e06821379fbd240187f5e268da5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 18:34:58 +0200 Subject: [PATCH 100/249] s3-rpc_srv: use gensec for schannel bind. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit a32a83ba9d6c7b5bbe9077973e5402ba65c068e7) --- source3/rpc_server/srv_pipe.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 9043a14..fd7a90a 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -808,10 +808,15 @@ static bool api_pipe_bind_req(struct pipes_struct *p, break; case DCERPC_AUTH_TYPE_SCHANNEL: - if (!pipe_schannel_auth_bind(p, pkt, - &auth_info, &auth_resp)) { + if (!pipe_auth_generic_bind(p, pkt, + &auth_info, &auth_resp)) { + goto err_exit; + } + if (!session_info_set_session_key(p->session_info, generic_session_key())) { + DEBUG(0, ("session_info_set_session_key failed\n")); goto err_exit; } + p->pipe_bound = true; break; case DCERPC_AUTH_TYPE_SPNEGO: -- 1.9.3 From 285de020b6e284ad5074492d62740ba8a370826a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 18:36:19 +0200 Subject: [PATCH 101/249] s3-rpc: use gensec for schannel footer processing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Stefan Metzmacher (cherry picked from commit 5a628490e46f428432cd9b32c2b4b3a34a3736ae) --- source3/librpc/rpc/dcerpc_helpers.c | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 97999d7..b9e05cb 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -273,7 +273,6 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, size_t max_len; size_t mod_len; struct gensec_security *gensec_security; - struct schannel_state *schannel_auth; /* no auth token cases first */ switch (auth->auth_level) { @@ -307,16 +306,11 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_SCHANNEL: gensec_security = talloc_get_type_abort(auth->auth_ctx, struct gensec_security); *auth_len = gensec_sig_size(gensec_security, max_len); break; - - case DCERPC_AUTH_TYPE_SCHANNEL: - schannel_auth = talloc_get_type_abort(auth->auth_ctx, - struct schannel_state); - *auth_len = netsec_outgoing_sig_size(schannel_auth); - break; default: return NT_STATUS_INVALID_PARAMETER; } @@ -548,7 +542,6 @@ static NTSTATUS get_schannel_auth_footer(TALLOC_CTX *mem_ctx, NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, size_t pad_len, DATA_BLOB *rpc_out) { - struct schannel_state *schannel_auth; struct gensec_security *gensec_security; char pad[CLIENT_NDR_PADDING_SIZE] = { 0, }; DATA_BLOB auth_info; @@ -600,19 +593,13 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_SCHANNEL: gensec_security = talloc_get_type_abort(auth->auth_ctx, struct gensec_security); status = add_generic_auth_footer(gensec_security, auth->auth_level, rpc_out); break; - case DCERPC_AUTH_TYPE_SCHANNEL: - schannel_auth = talloc_get_type_abort(auth->auth_ctx, - struct schannel_state); - status = add_schannel_auth_footer(schannel_auth, - auth->auth_level, - rpc_out); - break; default: status = NT_STATUS_INVALID_PARAMETER; break; @@ -640,7 +627,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, DATA_BLOB *raw_pkt, size_t *pad_len) { - struct schannel_state *schannel_auth; struct gensec_security *gensec_security; NTSTATUS status; struct dcerpc_auth auth_info; @@ -710,6 +696,7 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_SCHANNEL: DEBUG(10, ("GENSEC auth\n")); @@ -723,22 +710,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, return status; } break; - - case DCERPC_AUTH_TYPE_SCHANNEL: - - DEBUG(10, ("SCHANNEL auth\n")); - - schannel_auth = talloc_get_type_abort(auth->auth_ctx, - struct schannel_state); - status = get_schannel_auth_footer(pkt, schannel_auth, - auth->auth_level, - &data, &full_pkt, - &auth_info.credentials); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - break; - default: DEBUG(0, ("process_request_pdu: " "unknown auth type %u set.\n", -- 1.9.3 From cfa396d153cedb9b10356540a479ff299c480cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 19 Sep 2013 11:03:31 +0200 Subject: [PATCH 102/249] s3-rpc_cli: remove unused schannel calls from dcerpc_helpers.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit 639f60b1513a8c877d307ed86b7748250821fb3f) --- source3/librpc/rpc/dcerpc.h | 3 - source3/librpc/rpc/dcerpc_helpers.c | 124 ------------------------------------ 2 files changed, 127 deletions(-) diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index b3ae3b4..38d59cd 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -60,9 +60,6 @@ NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct ncacn_packet *r, bool bigendian); -NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, - struct NL_AUTH_MESSAGE *r, - DATA_BLOB *blob); NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx, enum dcerpc_AuthType auth_type, enum dcerpc_AuthLevel auth_level, diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index b9e05cb..2400bfd 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -21,9 +21,6 @@ #include "includes.h" #include "librpc/rpc/dcerpc.h" #include "librpc/gen_ndr/ndr_dcerpc.h" -#include "librpc/gen_ndr/ndr_schannel.h" -#include "../libcli/auth/schannel.h" -#include "../libcli/auth/spnego.h" #include "librpc/crypto/gse.h" #include "auth/gensec/gensec.h" @@ -135,34 +132,6 @@ NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx, } /** -* @brief NDR Encodes a NL_AUTH_MESSAGE -* -* @param mem_ctx The memory context the blob will be allocated on -* @param r The NL_AUTH_MESSAGE to encode -* @param blob [out] The encoded blob if successful -* -* @return a NTSTATUS error code -*/ -NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx, - struct NL_AUTH_MESSAGE *r, - DATA_BLOB *blob) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_push_struct_blob(blob, mem_ctx, r, - (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r); - } - - return NT_STATUS_OK; -} - -/** * @brief NDR Encodes a dcerpc_auth structure * * @param mem_ctx The memory context the blob will be allocated on @@ -437,99 +406,6 @@ static NTSTATUS get_generic_auth_footer(struct gensec_security *gensec_security, } } -/******************************************************************* - Create and add the schannel sign/seal auth data. - ********************************************************************/ - -static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas, - enum dcerpc_AuthLevel auth_level, - DATA_BLOB *rpc_out) -{ - uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH; - size_t data_and_pad_len = rpc_out->length - - DCERPC_RESPONSE_LENGTH - - DCERPC_AUTH_TRAILER_LENGTH; - DATA_BLOB auth_blob; - NTSTATUS status; - - if (!sas) { - return NT_STATUS_INVALID_PARAMETER; - } - - switch (auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - status = netsec_outgoing_packet(sas, - rpc_out->data, - true, - data_p, - data_and_pad_len, - &auth_blob); - break; - case DCERPC_AUTH_LEVEL_INTEGRITY: - status = netsec_outgoing_packet(sas, - rpc_out->data, - false, - data_p, - data_and_pad_len, - &auth_blob); - break; - default: - status = NT_STATUS_INTERNAL_ERROR; - break; - } - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n", - nt_errstr(status))); - return status; - } - - if (DEBUGLEVEL >= 10) { - dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob); - } - - /* Finally attach the blob. */ - if (!data_blob_append(NULL, rpc_out, - auth_blob.data, auth_blob.length)) { - return NT_STATUS_NO_MEMORY; - } - data_blob_free(&auth_blob); - - return NT_STATUS_OK; -} - -/******************************************************************* - Check/unseal the Schannel auth data. (Unseal in place). - ********************************************************************/ - -static NTSTATUS get_schannel_auth_footer(TALLOC_CTX *mem_ctx, - struct schannel_state *auth_state, - enum dcerpc_AuthLevel auth_level, - DATA_BLOB *data, DATA_BLOB *full_pkt, - DATA_BLOB *auth_token) -{ - switch (auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - /* Data portion is encrypted. */ - return netsec_incoming_packet(auth_state, - true, - data->data, - data->length, - auth_token); - - case DCERPC_AUTH_LEVEL_INTEGRITY: - /* Data is signed. */ - return netsec_incoming_packet(auth_state, - false, - data->data, - data->length, - auth_token); - - default: - return NT_STATUS_INVALID_PARAMETER; - } -} - /** * @brief Append an auth footer according to what is the current mechanism * -- 1.9.3 From 3c10a3501c04e1f5f9bd2bb1418b95b4b17248a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 19 Sep 2013 11:04:19 +0200 Subject: [PATCH 103/249] s3-rpc_cli: remove unused schannel calls from cli_pipe.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit 45949d721892a0e8a6b1a76e221c6b3bfd6a872f) --- source3/rpc_client/cli_pipe.c | 76 ------------------------------------------- 1 file changed, 76 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 8a642e2..b73f2f2 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -22,11 +22,8 @@ #include "includes.h" #include "../lib/util/tevent_ntstatus.h" #include "librpc/gen_ndr/ndr_epmapper_c.h" -#include "../librpc/gen_ndr/ndr_schannel.h" #include "../librpc/gen_ndr/ndr_dssetup.h" #include "../libcli/auth/schannel.h" -#include "../libcli/auth/spnego.h" -#include "../auth/ntlmssp/ntlmssp.h" #include "auth_generic.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/gen_ndr/ndr_netlogon_c.h" @@ -1018,42 +1015,6 @@ static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli, } /******************************************************************* - Creates schannel auth bind. - ********************************************************************/ - -static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli, - DATA_BLOB *auth_token) -{ - NTSTATUS status; - struct NL_AUTH_MESSAGE r; - - if (!cli->auth->user_name || !cli->auth->user_name[0]) { - return NT_STATUS_INVALID_PARAMETER_MIX; - } - - if (!cli->auth->domain || !cli->auth->domain[0]) { - return NT_STATUS_INVALID_PARAMETER_MIX; - } - - /* - * Now marshall the data into the auth parse_struct. - */ - - r.MessageType = NL_NEGOTIATE_REQUEST; - r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME | - NL_FLAG_OEM_NETBIOS_COMPUTER_NAME; - r.oem_netbios_domain.a = cli->auth->domain; - r.oem_netbios_computer.a = cli->auth->user_name; - - status = dcerpc_push_schannel_bind(cli, &r, auth_token); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} - -/******************************************************************* Creates the internals of a DCE/RPC bind request or alter context PDU. ********************************************************************/ @@ -2243,43 +2204,6 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, return status; } -static NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, - const char *domain, - enum dcerpc_AuthLevel auth_level, - struct netlogon_creds_CredentialState *creds, - struct pipe_auth_data **presult) -{ - struct schannel_state *schannel_auth; - struct pipe_auth_data *result; - - result = talloc(mem_ctx, struct pipe_auth_data); - if (result == NULL) { - return NT_STATUS_NO_MEMORY; - } - - result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; - result->auth_level = auth_level; - - result->user_name = talloc_strdup(result, creds->computer_name); - result->domain = talloc_strdup(result, domain); - if ((result->user_name == NULL) || (result->domain == NULL)) { - goto fail; - } - - schannel_auth = netsec_create_state(result, creds, true /* initiator */); - if (schannel_auth == NULL) { - goto fail; - } - - result->auth_ctx = schannel_auth; - *presult = result; - return NT_STATUS_OK; - - fail: - TALLOC_FREE(result); - return NT_STATUS_NO_MEMORY; -} - /** * Create an rpc pipe client struct, connecting to a tcp port. */ -- 1.9.3 From e4b33d6311e051501815199bd6c6dbba33f1bc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 19 Sep 2013 11:05:21 +0200 Subject: [PATCH 104/249] s3-rpc_srv: remove unused schannel calls from srv_pipe.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Autobuild-User(master): Günther Deschner Autobuild-Date(master): Thu Sep 19 12:59:04 CEST 2013 on sn-devel-104 (cherry picked from commit 6965f918c04328535c55a0ef9b7fe6392fba193a) --- source3/rpc_server/srv_pipe.c | 116 ------------------------------------------ 1 file changed, 116 deletions(-) diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index fd7a90a..06752a8 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -30,11 +30,8 @@ #include "includes.h" #include "system/filesys.h" #include "srv_pipe_internal.h" -#include "../librpc/gen_ndr/ndr_schannel.h" #include "../librpc/gen_ndr/dcerpc.h" #include "../librpc/rpc/rpc_common.h" -#include "../libcli/auth/schannel.h" -#include "../libcli/auth/spnego.h" #include "dcesrv_auth_generic.h" #include "rpc_server.h" #include "rpc_dce.h" @@ -415,119 +412,6 @@ bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) } /******************************************************************* - Handle an schannel bind auth. -*******************************************************************/ - -static bool pipe_schannel_auth_bind(struct pipes_struct *p, - TALLOC_CTX *mem_ctx, - struct dcerpc_auth *auth_info, - DATA_BLOB *response) -{ - struct NL_AUTH_MESSAGE neg; - struct NL_AUTH_MESSAGE reply; - bool ret; - NTSTATUS status; - struct netlogon_creds_CredentialState *creds; - enum ndr_err_code ndr_err; - struct schannel_state *schannel_auth; - struct loadparm_context *lp_ctx; - - ndr_err = ndr_pull_struct_blob( - &auth_info->credentials, mem_ctx, &neg, - (ndr_pull_flags_fn_t)ndr_pull_NL_AUTH_MESSAGE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(0,("pipe_schannel_auth_bind: Could not unmarshal SCHANNEL auth neg\n")); - return false; - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &neg); - } - - if (!(neg.Flags & NL_FLAG_OEM_NETBIOS_COMPUTER_NAME)) { - DEBUG(0,("pipe_schannel_auth_bind: Did not receive netbios computer name\n")); - return false; - } - - lp_ctx = loadparm_init_s3(p, loadparm_s3_helpers()); - if (!lp_ctx) { - DEBUG(0,("pipe_schannel_auth_bind: loadparm_init_s3() failed!\n")); - return false; - } - - /* - * The neg.oem_netbios_computer.a key here must match the remote computer name - * given in the DOM_CLNT_SRV.uni_comp_name used on all netlogon pipe - * operations that use credentials. - */ - - become_root(); - status = schannel_get_creds_state(p->mem_ctx, lp_ctx, - neg.oem_netbios_computer.a, &creds); - unbecome_root(); - - talloc_unlink(p, lp_ctx); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("pipe_schannel_auth_bind: Attempt to bind using schannel without successful serverauth2\n")); - return False; - } - - schannel_auth = netsec_create_state(p, creds, false /* not initiator */); - TALLOC_FREE(creds); - if (!schannel_auth) { - return False; - } - - /* - * JRA. Should we also copy the schannel session key into the pipe session key p->session_key - * here ? We do that for NTLMSSP, but the session key is already set up from the vuser - * struct of the person who opened the pipe. I need to test this further. JRA. - * - * VL. As we are mapping this to guest set the generic key - * "SystemLibraryDTC" key here. It's a bit difficult to test against - * W2k3, as it does not allow schannel binds against SAMR and LSA - * anymore. - */ - - ret = session_info_set_session_key(p->session_info, generic_session_key()); - - if (!ret) { - DEBUG(0, ("session_info_set_session_key failed\n")); - return false; - } - - /*** SCHANNEL verifier ***/ - - reply.MessageType = NL_NEGOTIATE_RESPONSE; - reply.Flags = 0; - reply.Buffer.dummy = 5; /* ??? actually I don't think - * this has any meaning - * here - gd */ - - ndr_err = ndr_push_struct_blob(response, mem_ctx, &reply, - (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n")); - return false; - } - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &reply); - } - - DEBUG(10,("pipe_schannel_auth_bind: schannel auth: domain [%s] myname [%s]\n", - neg.oem_netbios_domain.a, neg.oem_netbios_computer.a)); - - /* We're finished with this bind - no more packets. */ - p->auth.auth_ctx = schannel_auth; - p->auth.auth_type = DCERPC_AUTH_TYPE_SCHANNEL; - - p->pipe_bound = True; - - return True; -} - -/******************************************************************* Handle an NTLMSSP bind auth. *******************************************************************/ -- 1.9.3 From 68fbdf567cb7d0bc3550b826204c0708a771a4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Mon, 12 Aug 2013 17:22:15 +0200 Subject: [PATCH 105/249] librpc/ndr: call ndr_table_list() from all ndr_X functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit 88c1dbf722889a2d7379cdcbac1ce9b140a42356) --- librpc/ndr/ndr_table.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/librpc/ndr/ndr_table.c b/librpc/ndr/ndr_table.c index 7ca0417..01d9094 100644 --- a/librpc/ndr/ndr_table.c +++ b/librpc/ndr/ndr_table.c @@ -73,7 +73,7 @@ const char *ndr_interface_name(const struct GUID *uuid, uint32_t if_version) int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version) { const struct ndr_interface_list *l; - for (l=ndr_interfaces;l;l=l->next){ + for (l=ndr_table_list();l;l=l->next){ if (GUID_equal(&l->table->syntax_id.uuid, uuid) && l->table->syntax_id.if_version == if_version) { return l->table->num_calls; @@ -89,7 +89,7 @@ int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version) const struct ndr_interface_table *ndr_table_by_name(const char *name) { const struct ndr_interface_list *l; - for (l=ndr_interfaces;l;l=l->next) { + for (l=ndr_table_list();l;l=l->next) { if (strcasecmp(l->table->name, name) == 0) { return l->table; } @@ -103,7 +103,7 @@ const struct ndr_interface_table *ndr_table_by_name(const char *name) const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid) { const struct ndr_interface_list *l; - for (l=ndr_interfaces;l;l=l->next) { + for (l=ndr_table_list();l;l=l->next) { if (GUID_equal(&l->table->syntax_id.uuid, uuid)) { return l->table; } -- 1.9.3 From c936c80f7e567bab6fc749fb35e60176fca020af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 8 Aug 2013 17:34:56 +0200 Subject: [PATCH 106/249] librpc/ndr: make sure ndr_table_list() always calls ndr_init_table() first. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit 21200b12dc14673f9a610c5798635b6052370dbe) --- librpc/ndr/ndr_table.c | 1 + 1 file changed, 1 insertion(+) diff --git a/librpc/ndr/ndr_table.c b/librpc/ndr/ndr_table.c index 01d9094..f73b9fc 100644 --- a/librpc/ndr/ndr_table.c +++ b/librpc/ndr/ndr_table.c @@ -116,6 +116,7 @@ const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid) */ const struct ndr_interface_list *ndr_table_list(void) { + ndr_table_init(); return ndr_interfaces; } -- 1.9.3 From 2ced3243b3589b673967452a6401d665dd514525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 8 Aug 2013 17:40:22 +0200 Subject: [PATCH 107/249] s3-rpc: use table->name directly in DEBUG contexts. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit a94e278883c58b35d383753e86135ff6a1d14ec7) --- source3/lib/netapi/cm.c | 2 +- source3/rpc_client/cli_pipe.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index 1cfdccf..bb5d6b2 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -254,7 +254,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, status = pipe_cm_open(ctx, ipc, table, &result); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", - get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), + table->name, get_friendly_nt_error_msg(status)); return WERR_DEST_NOT_FOUND; } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index b73f2f2..64e7f1c 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2692,8 +2692,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, } DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe " "%s failed with error %s\n", - get_pipe_name_from_syntax(talloc_tos(), - &table->syntax_id), + table->name, nt_errstr(status) )); TALLOC_FREE(result); return status; @@ -2701,7 +2700,7 @@ NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli, DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine " "%s and bound anonymously.\n", - get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), + table->name, result->desthost)); *presult = result; @@ -2946,7 +2945,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, done: DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " "for domain %s and bound using schannel.\n", - get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id), + table->name, rpccli->desthost, domain)); *_rpccli = rpccli; -- 1.9.3 From cd864f1a3748c219df78600fc826a6e1d81fa07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 10:58:16 +0200 Subject: [PATCH 108/249] s3-rpc: use ndr_interface_name() instead of get_pipe_name_from_syntax() in DEBUG. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit 3135533710b2a1b64aaf6b10d30b86f3c004657d) --- source3/rpc_server/rpc_handles.c | 15 +++++++++------ source3/rpc_server/srv_pipe.c | 22 ++++++++++++++-------- source3/rpc_server/srv_pipe_hnd.c | 16 +++++++++++----- source3/wscript_build | 3 ++- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/source3/rpc_server/rpc_handles.c b/source3/rpc_server/rpc_handles.c index 70c3919..409299a 100644 --- a/source3/rpc_server/rpc_handles.c +++ b/source3/rpc_server/rpc_handles.c @@ -27,6 +27,7 @@ #include "rpc_server/rpc_pipes.h" #include "../libcli/security/security.h" #include "lib/tsocket/tsocket.h" +#include "librpc/ndr/ndr_table.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -218,7 +219,8 @@ bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *synta DEBUG(10,("init_pipe_handle_list: created handle list for " "pipe %s\n", - get_pipe_name_from_syntax(talloc_tos(), syntax))); + ndr_interface_name(&syntax->uuid, + syntax->if_version))); } /* @@ -235,7 +237,7 @@ bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *synta DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for " "pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count, - get_pipe_name_from_syntax(talloc_tos(), syntax))); + ndr_interface_name(&syntax->uuid, syntax->if_version))); return True; } @@ -412,8 +414,8 @@ void close_policy_by_pipe(struct pipes_struct *p) TALLOC_FREE(p->pipe_handles); DEBUG(10,("Deleted handle list for RPC connection %s\n", - get_pipe_name_from_syntax(talloc_tos(), - &p->contexts->syntax))); + ndr_interface_name(&p->contexts->syntax.uuid, + p->contexts->syntax.if_version))); } } @@ -456,8 +458,9 @@ void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n", (int) p->pipe_handles->count, - get_pipe_name_from_syntax(talloc_tos(), - &p->contexts->syntax))); + ndr_interface_name(&p->contexts->syntax.uuid, + p->contexts->syntax.if_version))); + *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 06752a8..19dbc37 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -41,6 +41,7 @@ #include "rpc_server/srv_pipe.h" #include "rpc_server/rpc_contexts.h" #include "lib/param/param.h" +#include "librpc/ndr/ndr_table.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -336,7 +337,8 @@ static bool check_bind_req(struct pipes_struct *p, bool ok; DEBUG(3,("check_bind_req for %s\n", - get_pipe_name_from_syntax(talloc_tos(), abstract))); + ndr_interface_name(&abstract->uuid, + abstract->if_version))); /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ if (rpc_srv_pipe_exists_by_id(abstract) && @@ -580,7 +582,8 @@ static bool api_pipe_bind_req(struct pipes_struct *p, if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("api_pipe_bind_req: Unknown rpc service name " "%s in bind request.\n", - get_pipe_name_from_syntax(talloc_tos(), &id))); + ndr_interface_name(&id.uuid, + id.if_version))); return setup_bind_nak(p, pkt); } @@ -595,8 +598,10 @@ static bool api_pipe_bind_req(struct pipes_struct *p, } else { DEBUG(0, ("module %s doesn't provide functions for " "pipe %s!\n", - get_pipe_name_from_syntax(talloc_tos(), &id), - get_pipe_name_from_syntax(talloc_tos(), &id))); + ndr_interface_name(&id.uuid, + id.if_version), + ndr_interface_name(&id.uuid, + id.if_version))); return setup_bind_nak(p, pkt); } } @@ -1206,7 +1211,8 @@ static bool api_pipe_request(struct pipes_struct *p, TALLOC_CTX *frame = talloc_stackframe(); DEBUG(5, ("Requested %s rpc service\n", - get_pipe_name_from_syntax(talloc_tos(), &pipe_fns->syntax))); + ndr_interface_name(&pipe_fns->syntax.uuid, + pipe_fns->syntax.if_version))); ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds, &pipe_fns->syntax); @@ -1237,7 +1243,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, /* interpret the command */ DEBUG(4,("api_rpcTNP: %s op 0x%x - ", - get_pipe_name_from_syntax(talloc_tos(), syntax), + ndr_interface_name(&syntax->uuid, syntax->if_version), pkt->u.request.opnum)); if (DEBUGLEVEL >= 50) { @@ -1276,7 +1282,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, /* do the actual command */ if(!api_rpc_cmds[fn_num].fn(p)) { DEBUG(0,("api_rpcTNP: %s: %s failed.\n", - get_pipe_name_from_syntax(talloc_tos(), syntax), + ndr_interface_name(&syntax->uuid, syntax->if_version), api_rpc_cmds[fn_num].name)); data_blob_free(&p->out_data.rdata); return False; @@ -1299,7 +1305,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, } DEBUG(5,("api_rpcTNP: called %s successfully\n", - get_pipe_name_from_syntax(talloc_tos(), syntax))); + ndr_interface_name(&syntax->uuid, syntax->if_version))); /* Check for buffer underflow in rpc parsing */ if ((DEBUGLEVEL >= 10) && diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 3f8ff44..fcbfa77 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -30,6 +30,7 @@ #include "rpc_server/rpc_config.h" #include "../lib/tsocket/tsocket.h" #include "../lib/util/tevent_ntstatus.h" +#include "librpc/ndr/ndr_table.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -281,7 +282,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, } DEBUG(6,(" name: %s len: %u\n", - get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), + ndr_interface_name(&p->contexts->syntax.uuid, + p->contexts->syntax.if_version), (unsigned int)n)); /* @@ -299,7 +301,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, DEBUG(5,("read_from_pipe: too large read (%u) requested on " "pipe %s. We can only service %d sized reads.\n", (unsigned int)n, - get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), + ndr_interface_name(&p->contexts->syntax.uuid, + p->contexts->syntax.if_version), RPC_MAX_PDU_FRAG_LEN )); n = RPC_MAX_PDU_FRAG_LEN; } @@ -320,7 +323,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, " "current_pdu_sent = %u returning %d bytes.\n", - get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), + ndr_interface_name(&p->contexts->syntax.uuid, + p->contexts->syntax.if_version), (unsigned int)p->out_data.frag.length, (unsigned int)p->out_data.current_pdu_sent, (int)data_returned)); @@ -341,7 +345,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length " "= %u, p->out_data.rdata.length = %u.\n", - get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax), + ndr_interface_name(&p->contexts->syntax.uuid, + p->contexts->syntax.if_version), (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)p->out_data.rdata.length)); @@ -363,7 +368,8 @@ static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, if(!create_next_pdu(p)) { DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", - get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax))); + ndr_interface_name(&p->contexts->syntax.uuid, + p->contexts->syntax.if_version))); return -1; } diff --git a/source3/wscript_build b/source3/wscript_build index 0bf84e2..bb2e928 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -672,7 +672,8 @@ bld.SAMBA3_LIBRARY('msrpc3', deps='''ndr ndr-standard RPC_NDR_EPMAPPER NTLMSSP_COMMON COMMON_SCHANNEL LIBCLI_AUTH LIBTSOCKET gse dcerpc-binding - libsmb''', + libsmb + ndr-table''', vars=locals(), private_library=True) -- 1.9.3 From 6e6ba9bb34ac4e1d55056ef82e4bad8ab2d65b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Thu, 8 Aug 2013 17:33:29 +0200 Subject: [PATCH 109/249] librpc: add dcerpc_default_transport_endpoint() function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit 40ee3d8a5f7439b90f1ebf5e40535fad51038fe6) --- librpc/rpc/dcerpc_util.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ librpc/rpc/rpc_common.h | 3 +++ 2 files changed, 58 insertions(+) diff --git a/librpc/rpc/dcerpc_util.c b/librpc/rpc/dcerpc_util.c index 0b9cca3..4046f32 100644 --- a/librpc/rpc/dcerpc_util.c +++ b/librpc/rpc/dcerpc_util.c @@ -332,3 +332,58 @@ NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req, tevent_req_received(req); return NT_STATUS_OK; } + +const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx, + enum dcerpc_transport_t transport, + const struct ndr_interface_table *table) +{ + NTSTATUS status; + const char *p = NULL; + const char *endpoint = NULL; + int i; + struct dcerpc_binding *default_binding = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + /* Find one of the default pipes for this interface */ + + for (i = 0; i < table->endpoints->count; i++) { + + status = dcerpc_parse_binding(frame, table->endpoints->names[i], + &default_binding); + if (NT_STATUS_IS_OK(status)) { + if (transport == NCA_UNKNOWN && + default_binding->endpoint != NULL) { + p = default_binding->endpoint; + break; + } + if (default_binding->transport == transport && + default_binding->endpoint != NULL) { + p = default_binding->endpoint; + break; + } + } + } + + if (i == table->endpoints->count || p == NULL) { + goto done; + } + + /* + * extract the pipe name without \\pipe from for example + * ncacn_np:[\\pipe\\epmapper] + */ + if (default_binding->transport == NCACN_NP) { + if (strncasecmp(p, "\\pipe\\", 6) == 0) { + p += 6; + } + if (strncmp(p, "\\", 1) == 0) { + p += 1; + } + } + + endpoint = talloc_strdup(mem_ctx, p); + + done: + talloc_free(frame); + return endpoint; +} diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h index e2b3755..d2816f5 100644 --- a/librpc/rpc/rpc_common.h +++ b/librpc/rpc/rpc_common.h @@ -143,6 +143,9 @@ void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v); uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob); void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v); uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob); +const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx, + enum dcerpc_transport_t transport, + const struct ndr_interface_table *table); /** * @brief Pull a dcerpc_auth structure, taking account of any auth -- 1.9.3 From a71f6912117ef5054cba4346f8bfd555d70d7837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 18 Sep 2013 10:59:14 +0200 Subject: [PATCH 110/249] s3-rpc: use dcerpc_default_transport_endpoint function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher (cherry picked from commit b73e2d927b2221cb3fde8776789c8ca085cf2b8f) --- source3/rpc_client/rpc_transport_np.c | 4 +++- source3/rpc_server/rpc_ncacn_np.c | 12 ++++++++++-- source3/rpc_server/srv_pipe.c | 28 +++++++++++++++++++++------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/source3/rpc_client/rpc_transport_np.c b/source3/rpc_client/rpc_transport_np.c index c0f313e..91943f4 100644 --- a/source3/rpc_client/rpc_transport_np.c +++ b/source3/rpc_client/rpc_transport_np.c @@ -22,6 +22,7 @@ #include "rpc_client/rpc_transport.h" #include "libsmb/cli_np_tstream.h" #include "client.h" +#include "librpc/ndr/ndr_table.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_CLI @@ -55,7 +56,8 @@ struct tevent_req *rpc_transport_np_init_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->cli = cli; state->abs_timeout = timeval_current_ofs_msec(cli->timeout); - state->pipe_name = get_pipe_name_from_syntax(state, &table->syntax_id); + state->pipe_name = dcerpc_default_transport_endpoint(state, NCACN_NP, + table); if (tevent_req_nomem(state->pipe_name, req)) { return tevent_req_post(req, ev); } diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c index 7389b3e..46b77fd 100644 --- a/source3/rpc_server/rpc_ncacn_np.c +++ b/source3/rpc_server/rpc_ncacn_np.c @@ -36,6 +36,7 @@ #include "../lib/util/tevent_ntstatus.h" #include "rpc_contexts.h" #include "rpc_server/rpc_config.h" +#include "librpc/ndr/ndr_table.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -54,8 +55,15 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, struct pipe_rpc_fns *context_fns; const char *pipe_name; int ret; + const struct ndr_interface_table *table; - pipe_name = get_pipe_name_from_syntax(talloc_tos(), syntax); + table = ndr_table_by_uuid(&syntax->uuid); + if (table == NULL) { + DEBUG(0,("unknown interface\n")); + return NULL; + } + + pipe_name = dcerpc_default_transport_endpoint(mem_ctx, NCACN_NP, table); DEBUG(4,("Create pipe requested %s\n", pipe_name)); @@ -783,7 +791,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - pipe_name = get_pipe_name_from_syntax(tmp_ctx, &table->syntax_id); + pipe_name = dcerpc_default_transport_endpoint(mem_ctx, NCACN_NP, table); if (pipe_name == NULL) { status = NT_STATUS_INVALID_PARAMETER; goto done; diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 19dbc37..5f834fb 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -552,6 +552,7 @@ static bool api_pipe_bind_req(struct pipes_struct *p, struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; + const struct ndr_interface_table *table; /* No rebinds on a bound pipe - use alter context. */ if (p->pipe_bound) { @@ -569,15 +570,21 @@ static bool api_pipe_bind_req(struct pipes_struct *p, * that this is a pipe name we support. */ id = pkt->u.bind.ctx_list[0].abstract_syntax; + + table = ndr_table_by_uuid(&id.uuid); + if (table == NULL) { + DEBUG(0,("unknown interface\n")); + return false; + } + if (rpc_srv_pipe_exists_by_id(&id)) { DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", rpc_srv_get_pipe_cli_name(&id), rpc_srv_get_pipe_srv_name(&id))); } else { status = smb_probe_module( - "rpc", get_pipe_name_from_syntax( - talloc_tos(), - &id)); + "rpc", dcerpc_default_transport_endpoint(pkt, + NCACN_NP, table)); if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("api_pipe_bind_req: Unknown rpc service name " @@ -589,8 +596,8 @@ static bool api_pipe_bind_req(struct pipes_struct *p, } if (rpc_srv_get_pipe_interface_by_cli_name( - get_pipe_name_from_syntax(talloc_tos(), - &id), + dcerpc_default_transport_endpoint(pkt, + NCACN_NP, table), &id)) { DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n", rpc_srv_get_pipe_cli_name(&id), @@ -1240,16 +1247,23 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, { int fn_num; uint32_t offset1; + const struct ndr_interface_table *table; /* interpret the command */ DEBUG(4,("api_rpcTNP: %s op 0x%x - ", ndr_interface_name(&syntax->uuid, syntax->if_version), pkt->u.request.opnum)); + table = ndr_table_by_uuid(&syntax->uuid); + if (table == NULL) { + DEBUG(0,("unknown interface\n")); + return false; + } + if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "in_%s", - get_pipe_name_from_syntax(talloc_tos(), syntax)); + dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); dump_pdu_region(name, pkt->u.request.opnum, &p->in_data.data, 0, p->in_data.data.length); @@ -1298,7 +1312,7 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "out_%s", - get_pipe_name_from_syntax(talloc_tos(), syntax)); + dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); dump_pdu_region(name, pkt->u.request.opnum, &p->out_data.rdata, offset1, p->out_data.rdata.length); -- 1.9.3 From 8bb6f177b210159ea6317b20e2cc12732b4d273a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 7 Aug 2013 17:43:08 +0200 Subject: [PATCH 111/249] s3-rpc: remove unused source3/librpc/rpc/rpc_common.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Stefan Metzmacher Autobuild-User(master): Günther Deschner Autobuild-Date(master): Fri Sep 20 14:57:06 CEST 2013 on sn-devel-104 (cherry picked from commit 807628ecac445999e75ec9ea1abdc5f2fde356d6) --- source3/librpc/rpc/dcerpc.h | 8 -- source3/librpc/rpc/rpc_common.c | 209 ---------------------------------------- source3/wscript_build | 1 - 3 files changed, 218 deletions(-) delete mode 100644 source3/librpc/rpc/rpc_common.c diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index 38d59cd..b18b7ba 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -85,12 +85,4 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, DATA_BLOB *raw_pkt, size_t *pad_len); -/* The following definitions come from librpc/rpc/rpc_common.c */ - -bool smb_register_ndr_interface(const struct ndr_interface_table *interface); -const struct ndr_interface_table *get_iface_from_syntax( - const struct ndr_syntax_id *syntax); -const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax); - #endif /* __S3_DCERPC_H__ */ diff --git a/source3/librpc/rpc/rpc_common.c b/source3/librpc/rpc/rpc_common.c deleted file mode 100644 index 1219b2d..0000000 --- a/source3/librpc/rpc/rpc_common.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Largely rewritten by Jeremy Allison 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 - * (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 "includes.h" -#include "librpc/rpc/dcerpc.h" -#include "../librpc/gen_ndr/ndr_lsa.h" -#include "../librpc/gen_ndr/ndr_dssetup.h" -#include "../librpc/gen_ndr/ndr_samr.h" -#include "../librpc/gen_ndr/ndr_netlogon.h" -#include "../librpc/gen_ndr/ndr_srvsvc.h" -#include "../librpc/gen_ndr/ndr_wkssvc.h" -#include "../librpc/gen_ndr/ndr_winreg.h" -#include "../librpc/gen_ndr/ndr_spoolss.h" -#include "../librpc/gen_ndr/ndr_dfs.h" -#include "../librpc/gen_ndr/ndr_echo.h" -#include "../librpc/gen_ndr/ndr_initshutdown.h" -#include "../librpc/gen_ndr/ndr_svcctl.h" -#include "../librpc/gen_ndr/ndr_eventlog.h" -#include "../librpc/gen_ndr/ndr_ntsvcs.h" -#include "../librpc/gen_ndr/ndr_epmapper.h" -#include "../librpc/gen_ndr/ndr_drsuapi.h" -#include "../librpc/gen_ndr/ndr_fsrvp.h" - -static const char *get_pipe_name_from_iface( - TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface) -{ - int i; - const struct ndr_interface_string_array *ep = interface->endpoints; - char *p; - - for (i=0; icount; i++) { - if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) { - break; - } - } - if (i == ep->count) { - return NULL; - } - - /* - * extract the pipe name without \\pipe from for example - * ncacn_np:[\\pipe\\epmapper] - */ - p = strchr(ep->names[i]+15, ']'); - if (p == NULL) { - return "PIPE"; - } - return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15); -} - -static const struct ndr_interface_table **interfaces; - -bool smb_register_ndr_interface(const struct ndr_interface_table *interface) -{ - int num_interfaces = talloc_array_length(interfaces); - const struct ndr_interface_table **tmp; - int i; - - for (i=0; isyntax_id, - &interface->syntax_id)) { - return true; - } - } - - tmp = talloc_realloc(NULL, interfaces, - const struct ndr_interface_table *, - num_interfaces + 1); - if (tmp == NULL) { - DEBUG(1, ("smb_register_ndr_interface: talloc failed\n")); - return false; - } - interfaces = tmp; - interfaces[num_interfaces] = interface; - return true; -} - -static bool initialize_interfaces(void) -{ - if (!smb_register_ndr_interface(&ndr_table_lsarpc)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_dssetup)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_samr)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_netlogon)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_srvsvc)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_wkssvc)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_winreg)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_spoolss)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_netdfs)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_rpcecho)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_initshutdown)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_svcctl)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_eventlog)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_epmapper)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_drsuapi)) { - return false; - } - if (!smb_register_ndr_interface(&ndr_table_FileServerVssAgent)) { - return false; - } - return true; -} - -const struct ndr_interface_table *get_iface_from_syntax( - const struct ndr_syntax_id *syntax) -{ - int num_interfaces; - int i; - - if (interfaces == NULL) { - if (!initialize_interfaces()) { - return NULL; - } - } - num_interfaces = talloc_array_length(interfaces); - - for (i=0; isyntax_id, syntax)) { - return interfaces[i]; - } - } - - return NULL; -} - -/**************************************************************************** - Return the pipe name from the interface. - ****************************************************************************/ - -const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax) -{ - const struct ndr_interface_table *interface; - char *guid_str; - const char *result; - - interface = get_iface_from_syntax(syntax); - if (interface != NULL) { - result = get_pipe_name_from_iface(mem_ctx, interface); - if (result != NULL) { - return result; - } - } - - /* - * Here we should ask \\epmapper, but for now our code is only - * interested in the known pipes mentioned in pipe_names[] - */ - - guid_str = GUID_string(talloc_tos(), &syntax->uuid); - if (guid_str == NULL) { - return NULL; - } - result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str, - (int)syntax->if_version); - TALLOC_FREE(guid_str); - - if (result == NULL) { - return "PIPE"; - } - return result; -} - diff --git a/source3/wscript_build b/source3/wscript_build index bb2e928..8126cf6 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -141,7 +141,6 @@ LIBSMB_SRC = '''libsmb/clientgen.c libsmb/cliconnect.c libsmb/clifile.c LIBMSRPC_SRC = ''' rpc_client/cli_pipe.c - librpc/rpc/rpc_common.c rpc_client/rpc_transport_np.c rpc_client/rpc_transport_sock.c rpc_client/rpc_transport_tstream.c -- 1.9.3 From 2b2d978bd97299371a1fd7798d69ab377a76d389 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 14 Aug 2013 09:27:59 +0000 Subject: [PATCH 112/249] winbind3: Fix an invalid free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a warning I've never seen before :-) ../source3/winbindd/winbindd_cm.c:781:59: warning: attempt to free a non-heap object ‘machine_krb5_principal’ [-Wfree-nonheap-object] Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Aug 14 14:04:16 CEST 2013 on sn-devel-104 (cherry picked from commit 5f75814586f2d6f7c2dc8fd9342cb045c1f7e68c) --- source3/winbindd/winbindd_cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index facef64..d868826 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -840,7 +840,7 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain, } if (!strupper_m(*machine_krb5_principal)) { - SAFE_FREE(machine_krb5_principal); + SAFE_FREE(*machine_krb5_principal); return NT_STATUS_INVALID_PARAMETER; } } -- 1.9.3 From 1b88903c4f5931397e22874b3751dd05a03a2dea Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 11 Oct 2013 13:34:13 +1300 Subject: [PATCH 113/249] s3-winbindd: Remove undocumented winbindd:socket dir parameter This uses the documeted "winbindd socket directory" parameter instead. This came about due to the merge of the two smb.conf tables in s3 and s4 for the Samba 4.0 release. The s4 code used a real parameter, which caused this to be documented, whereas no automatic procedure existed to notice the parametric option and the need to document that. The fact that this was not used consistently in both codebases is one of the many areas of technical debt we still need to pay off here. Andrew Bartlett Signed-off-by: Andrew Bartlett Reviewed-by: Andreas Schneider (cherry picked from commit e512491552d9ed0dc1005a23ffc8f77ba237f863) --- selftest/target/Samba3.pm | 2 +- source3/include/proto.h | 1 + source3/param/loadparm.c | 1 + source3/winbindd/winbindd.c | 9 ++------- source3/winbindd/winbindd_proto.h | 1 - 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index ba01154..d8f0c27 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -972,7 +972,7 @@ sub provision($$$$$$) printing = bsd printcap name = /dev/null - winbindd:socket dir = $wbsockdir + winbindd socket directory = $wbsockdir nmbd:socket dir = $nmbdsockdir idmap config * : range = 100000-200000 winbind enum users = yes diff --git a/source3/include/proto.h b/source3/include/proto.h index cbad7ac..53cd59d 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1069,6 +1069,7 @@ char *lp_wins_hook(TALLOC_CTX *ctx); const char *lp_template_homedir(void); const char *lp_template_shell(void); const char *lp_winbind_separator(void); +const char *lp_winbindd_socket_directory(void); bool lp_winbind_enum_users(void); bool lp_winbind_enum_groups(void); bool lp_winbind_use_default_domain(void); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 4b31023..b2804ae 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -961,6 +961,7 @@ static void init_globals(bool reinit_globals) string_set(&Globals.szTemplateShell, "/bin/false"); string_set(&Globals.szTemplateHomedir, "/home/%D/%U"); string_set(&Globals.szWinbindSeparator, "\\"); + string_set(&Globals.szWinbinddSocketDirectory, dyn_WINBINDD_SOCKET_DIR); string_set(&Globals.szCupsServer, ""); string_set(&Globals.szIPrintServer, ""); diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index f101e52..69a17bf 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -189,7 +189,7 @@ static void terminate(bool is_parent) char *path = NULL; if (asprintf(&path, "%s/%s", - get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME) > 0) { + lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME) > 0) { unlink(path); SAFE_FREE(path); } @@ -1067,11 +1067,6 @@ static void winbindd_listen_fde_handler(struct tevent_context *ev, * Winbindd socket accessor functions */ -const char *get_winbind_pipe_dir(void) -{ - return lp_parm_const_string(-1, "winbindd", "socket dir", get_dyn_WINBINDD_SOCKET_DIR()); -} - char *get_winbind_priv_pipe_dir(void) { return state_path(WINBINDD_PRIV_SOCKET_SUBDIR); @@ -1092,7 +1087,7 @@ static bool winbindd_setup_listeners(void) pub_state->privileged = false; pub_state->fd = create_pipe_sock( - get_winbind_pipe_dir(), WINBINDD_SOCKET_NAME, 0755); + lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755); if (pub_state->fd == -1) { goto failed; } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 3df7d7c..cfc19d0 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -34,7 +34,6 @@ bool winbindd_setup_stdin_handler(bool parent, bool foreground); bool winbindd_setup_sig_hup_handler(const char *lfile); bool winbindd_use_idmap_cache(void); bool winbindd_use_cache(void); -const char *get_winbind_pipe_dir(void); char *get_winbind_priv_pipe_dir(void); struct tevent_context *winbind_event_context(void); int main(int argc, char **argv, char **envp); -- 1.9.3 From d0ae2d10385dea4b8fae3d8932d40f546ff8905b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Oct 2013 15:33:20 +1300 Subject: [PATCH 114/249] lib/param: lp_magicchar takes a const struct share_params *p so should be FN_LOCAL_PARM_CHAR This was found when trying to autogenerate prototypes for lp_ functions again. Andrew Bartlett Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- lib/param/loadparm.c | 2 +- lib/param/param_functions.c | 2 +- source3/param/loadparm.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 455c5e6..4497dbf 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -314,7 +314,7 @@ static struct loadparm_context *global_loadparm_context; #define FN_LOCAL_PARM_INTEGER(fn_name, val) FN_LOCAL_INTEGER(fn_name, val) -#define FN_LOCAL_CHAR(fn_name,val) \ +#define FN_LOCAL_PARM_CHAR(fn_name,val) \ _PUBLIC_ char lpcfg_ ## fn_name(struct loadparm_service *service, \ struct loadparm_service *sDefault) { \ return((service != NULL)? service->val : sDefault->val); \ diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c index d9d5df6..60f9c07 100644 --- a/lib/param/param_functions.c +++ b/lib/param/param_functions.c @@ -147,7 +147,7 @@ FN_LOCAL_INTEGER(aio_write_size, iAioWriteSize) FN_LOCAL_INTEGER(map_readonly, iMap_readonly) FN_LOCAL_INTEGER(directory_name_cache_size, iDirectoryNameCacheSize) FN_LOCAL_INTEGER(smb_encrypt, ismb_encrypt) -FN_LOCAL_CHAR(magicchar, magic_char) +FN_LOCAL_PARM_CHAR(magicchar, magic_char) FN_LOCAL_STRING(cups_options, szCupsOptions) FN_LOCAL_PARM_BOOL(change_notify, bChangeNotify) FN_LOCAL_PARM_BOOL(kernel_change_notify, bKernelChangeNotify) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index b2804ae..40f3242 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -1116,7 +1116,7 @@ char *lp_ ## fn_name(TALLOC_CTX *ctx,int i) {return(lp_string((ctx), (LP_SNUM_OK bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} #define FN_LOCAL_PARM_INTEGER(fn_name,val) \ int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} -#define FN_LOCAL_CHAR(fn_name,val) \ +#define FN_LOCAL_PARM_CHAR(fn_name,val) \ char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} -- 1.9.3 From bf5cb3b6c6e2d3171b70fff5deb9a7767d6609a8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Oct 2013 13:47:27 +1300 Subject: [PATCH 115/249] build: Move loadparm-related build rules to source3/param/wscript_build Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- source3/param/wscript_build | 32 ++++++++++++++++++++++++++++++++ source3/wscript_build | 36 ++---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 source3/param/wscript_build diff --git a/source3/param/wscript_build b/source3/param/wscript_build new file mode 100644 index 0000000..278d5f5 --- /dev/null +++ b/source3/param/wscript_build @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +bld.SAMBA3_SUBSYSTEM('PARAM_UTIL', + source='util.c', + deps='talloc') + +bld.SAMBA3_SUBSYSTEM('LOADPARM_CTX', + source='loadparm_ctx.c', + deps='''talloc s3_param_h param''') + +bld.SAMBA_GENERATOR('s3_param_global_h', + source= '../../script/mkparamdefs.pl loadparm.c ../../lib/param/param_functions.c', + target='param_global.h', + rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT} --generate-scope=GLOBAL') + +bld.SAMBA3_PYTHON('pys3param', + source='pyparam.c', + deps='param', + public_deps='samba-hostconfig pytalloc-util talloc', + realname='samba/samba3/param.so') + +bld.SAMBA3_SUBSYSTEM('param_service', + source='service.c', + deps = 'USER_UTIL param PRINTING') + +bld.SAMBA3_BINARY('test_lp_load', + source='test_lp_load.c', + deps=''' + talloc + param + popt_samba3''', + install=False) diff --git a/source3/wscript_build b/source3/wscript_build index 8126cf6..13d15c3 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -751,33 +751,9 @@ bld.SAMBA3_SUBSYSTEM('SERVER_MUTEX', source=SERVER_MUTEX_SRC, deps='talloc') -bld.SAMBA3_SUBSYSTEM('PARAM_UTIL', - source=PARAM_UTIL_SRC, - deps='talloc') - -bld.SAMBA3_SUBSYSTEM('LOADPARM_CTX', - source='param/loadparm_ctx.c', - deps='''talloc s3_param_h param''', - vars=locals()) - -bld.SAMBA_GENERATOR('param/param_global_h', - source= '../script/mkparamdefs.pl param/loadparm.c ../lib/param/param_functions.c', - target='param/param_global.h', - rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT} --generate-scope=GLOBAL') - bld.SAMBA3_SUBSYSTEM('param', source=PARAM_WITHOUT_REG_SRC, - deps='samba-util PARAM_UTIL ldap lber LOADPARM_CTX samba3core smbconf param_local_h param/param_global_h cups''') - -bld.SAMBA3_PYTHON('pys3param', - source='param/pyparam.c', - deps='param', - public_deps='samba-hostconfig pytalloc-util talloc', - realname='samba/samba3/param.so') - -bld.SAMBA3_SUBSYSTEM('param_service', - source='param/service.c', - deps = 'USER_UTIL param PRINTING') + deps='samba-util PARAM_UTIL ldap lber LOADPARM_CTX samba3core smbconf param_local_h s3_param_global_h cups''') bld.SAMBA3_SUBSYSTEM('REGFIO', source=REGFIO_SRC, @@ -1566,15 +1542,6 @@ bld.SAMBA3_BINARY('rpc_open_tcp', install=False, vars=locals()) -bld.SAMBA3_BINARY('test_lp_load', - source=TEST_LP_LOAD_SRC, - deps=''' - talloc - param - popt_samba3''', - install=False, - vars=locals()) - bld.SAMBA3_BINARY('dbwrap_tool', source=DBWRAP_TOOL_SRC, deps=''' @@ -1638,6 +1605,7 @@ bld.RECURSE('librpc/idl') bld.RECURSE('libsmb') bld.RECURSE('modules') bld.RECURSE('pam_smbpass') +bld.RECURSE('param') bld.RECURSE('passdb') bld.RECURSE('rpc_server') bld.RECURSE('script') -- 1.9.3 From 281cb415404f7044a4bdbc93a21b2f755cbc74ee Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Oct 2013 15:34:40 +1300 Subject: [PATCH 116/249] lib/param: Do not attempt to access the s3 function for allocated and subbed string parameters This allows us not to generate array entries for these, which in turn allows us to avoid initialising them. The issue is that we do not have the % macro sub context nor a talloc context handy (yet). Andrew Bartlett Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- lib/param/loadparm.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 4497dbf..23b45e2 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -232,7 +232,16 @@ static struct loadparm_context *global_loadparm_context; #define lpcfg_default_service global_loadparm_context->sDefault #define lpcfg_global_service(i) global_loadparm_context->services[i] -#define FN_GLOBAL_STRING(fn_name,var_name) \ +#define FN_GLOBAL_STRING(fn_name,var_name) \ + _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\ + if (lp_ctx == NULL) return NULL; \ + if (lp_ctx->s3_fns) { \ + smb_panic( __location__ ": " #fn_name " not implemented because it is an allocated and substiuted string"); \ + } \ + return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \ +} + +#define FN_GLOBAL_CONST_STRING(fn_name,var_name) \ _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \ if (lp_ctx == NULL) return NULL; \ if (lp_ctx->s3_fns) { \ @@ -242,16 +251,6 @@ static struct loadparm_context *global_loadparm_context; return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \ } -#define FN_GLOBAL_CONST_STRING(fn_name,var_name) \ - _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\ - if (lp_ctx == NULL) return NULL; \ - if (lp_ctx->s3_fns) { \ - SMB_ASSERT(lp_ctx->s3_fns->fn_name); \ - return lp_ctx->s3_fns->fn_name(); \ - } \ - return lp_ctx->globals->var_name ? lp_string(lp_ctx->globals->var_name) : ""; \ - } - #define FN_GLOBAL_LIST(fn_name,var_name) \ _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \ if (lp_ctx == NULL) return NULL; \ -- 1.9.3 From e610d185d26910e6cb96ddf8507c31c5f1503271 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Oct 2013 15:36:18 +1300 Subject: [PATCH 117/249] param: Skip generating hooks for local and string parameters Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- script/mks3param.pl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/script/mks3param.pl b/script/mks3param.pl index 4222ca5..799958c 100644 --- a/script/mks3param.pl +++ b/script/mks3param.pl @@ -108,7 +108,14 @@ sub handle_loadparm($$) { my ($file,$line) = @_; - if ($line =~ /^FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) { + # Local parameters don't need the ->s3_fns because the struct + # loadparm_service is shared and lpcfg_service() checks the ->s3_fns + # hook + # + # STRING isn't handled as we do not yet have a way to pass in a memory context nor + # do we have a good way of dealing with the % macros yet. + + if ($line =~ /^FN_(GLOBAL)_(CONST_STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) { my $scope = $1; my $type = $2; my $name = $3; -- 1.9.3 From 970290dc75404ab366617210edfca718fe21864b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Oct 2013 15:39:10 +1300 Subject: [PATCH 118/249] s3/param: Autogenerate parameters prototypes again after proto.h was frozen This autogenerates the parameters so that we can keep everything in sync easier, particularly when adding new parameters. This will also make it easier to move to a fully autogenerated system in the future, as it reduces special cases. Andrew Bartlett Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- script/mks3param_proto.pl | 199 ++++++++++++++++++++++++++++++++++++++++++++ source3/include/proto.h | 2 + source3/param/wscript_build | 5 ++ 3 files changed, 206 insertions(+) create mode 100644 script/mks3param_proto.pl diff --git a/script/mks3param_proto.pl b/script/mks3param_proto.pl new file mode 100644 index 0000000..446e343 --- /dev/null +++ b/script/mks3param_proto.pl @@ -0,0 +1,199 @@ +#!/usr/bin/perl +# Generate loadparm interfaces tables for Samba3/Samba4 integration +# by Andrew Bartlett +# based on mkproto.pl Written by Jelmer Vernooij +# based on the original mkproto.sh by Andrew Tridgell + +use strict; + +# don't use warnings module as it is not portable enough +# use warnings; + +use Getopt::Long; +use File::Basename; +use File::Path; + +##################################################################### +# read a file into a string + +my $file = undef; +my $public_define = undef; +my $_public = ""; +my $_private = ""; +my $public_data = \$_public; +my $builddir = "."; +my $srcdir = "."; + +sub public($) +{ + my ($d) = @_; + $$public_data .= $d; +} + +sub usage() +{ + print "Usage: mks3param.pl [options] [c files]\n"; + print "OPTIONS:\n"; + print " --srcdir=path Read files relative to this directory\n"; + print " --builddir=path Write file relative to this directory\n"; + print " --help Print this help message\n\n"; + exit 0; +} + +GetOptions( + 'file=s' => sub { my ($f,$v) = @_; $file = $v; }, + 'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; }, + 'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; }, + 'help' => \&usage +) or exit(1); + +sub normalize_define($$) +{ + my ($define, $file) = @_; + + if (not defined($define) and defined($file)) { + $define = "__" . uc($file) . "__"; + $define =~ tr{./}{__}; + $define =~ tr{\-}{_}; + } elsif (not defined($define)) { + $define = '_S3_PARAM_PROTO_H_'; + } + + return $define; +} + +$public_define = normalize_define($public_define, $file); + +sub file_load($) +{ + my($filename) = @_; + local(*INPUTFILE); + open(INPUTFILE, $filename) or return undef; + my($saved_delim) = $/; + undef $/; + my($data) = ; + close(INPUTFILE); + $/ = $saved_delim; + return $data; +} + +sub print_header($$) +{ + my ($file, $header_name) = @_; + $file->("#ifndef $header_name\n"); + $file->("#define $header_name\n\n"); + $file->("/* This file was automatically generated by mks3param_proto.pl. DO NOT EDIT */\n\n"); +} + +sub print_footer($$) +{ + my ($file, $header_name) = @_; + $file->("\n#endif /* $header_name */\n\n"); +} + +sub handle_loadparm($$) +{ + my ($file,$line) = @_; + + my $scope; + my $type; + my $name; + my $var; + my $param; + + if ($line =~ /^FN_(GLOBAL|LOCAL)_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),(.*)\)/o) { + $scope = $1; + $type = $2; + $name = $3; + $var = $4; + $param = "int"; + } elsif ($line =~ /^FN_(GLOBAL|LOCAL)_PARM_(CONST_STRING|STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),(.*)\)/o) { + $scope = $1; + $type = $2; + $name = $3; + $var = $4; + $param = "const struct share_params *p"; + } else { + return; + } + + my %tmap = ( + "BOOL" => "bool ", + "CONST_STRING" => "const char *", + "STRING" => "char *", + "INTEGER" => "int ", + "CHAR" => "char ", + "LIST" => "const char **", + ); + + my %smap = ( + "GLOBAL" => "void", + "LOCAL" => "$param" + ); + + if (($type eq "STRING") and ($scope eq "GLOBAL")) { + $file->("$tmap{$type}lp_$name(TALLOC_CTX *ctx);\n"); + } elsif (($type eq "STRING") and ($scope eq "LOCAL")) { + $file->("$tmap{$type}lp_$name(TALLOC_CTX *ctx, $smap{$scope});\n"); + } else { + $file->("$tmap{$type}lp_$name($smap{$scope});\n"); + } +} + +sub process_file($$) +{ + my ($file, $filename) = @_; + + $filename =~ s/\.o$/\.c/g; + + if ($filename =~ /^\//) { + open(FH, "<$filename") or die("Failed to open $filename"); + } elsif (!open(FH, "< $builddir/$filename")) { + open(FH, "< $srcdir/$filename") || die "Failed to open $filename"; + } + + my $comment = undef; + my $incomment = 0; + while (my $line = ) { + if ($line =~ /^\/\*\*/) { + $comment = ""; + $incomment = 1; + } + + if ($incomment) { + $comment .= $line; + if ($line =~ /\*\//) { + $incomment = 0; + } + } + + # these are ordered for maximum speed + next if ($line =~ /^\s/); + + next unless ($line =~ /\(/); + + next if ($line =~ /^\/|[;]/); + + if ($line =~ /^FN_/) { + handle_loadparm($file, $line); + } + next; + } + + close(FH); +} + + +print_header(\&public, $public_define); + +process_file(\&public, $_) foreach (@ARGV); +print_footer(\&public, $public_define); + +if (not defined($file)) { + print STDOUT $$public_data; +} + +mkpath(dirname($file), 0, 0755); +open(PUBLIC, ">$file") or die("Can't open `$file': $!"); +print PUBLIC "$$public_data"; +close(PUBLIC); diff --git a/source3/include/proto.h b/source3/include/proto.h index 53cd59d..614baa4 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -993,6 +993,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m /* The following definitions come from param/loadparm.c */ +#include "source3/param/param_proto.h" + const char **lp_smb_ports(void); const char *lp_dos_charset(void); const char *lp_unix_charset(void); diff --git a/source3/param/wscript_build b/source3/param/wscript_build index 278d5f5..643c27e 100644 --- a/source3/param/wscript_build +++ b/source3/param/wscript_build @@ -13,6 +13,11 @@ bld.SAMBA_GENERATOR('s3_param_global_h', target='param_global.h', rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT} --generate-scope=GLOBAL') +bld.SAMBA_GENERATOR('s3_param_proto_h', + source= '../../script/mks3param_proto.pl loadparm.c ../../lib/param/param_functions.c', + target='param_proto.h', + rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') + bld.SAMBA3_PYTHON('pys3param', source='pyparam.c', deps='param', -- 1.9.3 From 4f87a4ca65b386e90cca479aabdf9051de2c67e3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Oct 2013 15:46:43 +1300 Subject: [PATCH 119/249] param: Autogenerate s3 lp_ctx glue table This allows us to use more lpcfg_ functions without adding them manually. Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- lib/param/wscript_build | 1 + script/mks3param_ctx_table.pl | 139 ++++++++++++++++++++++++++++++++++++++++++ source3/param/loadparm_ctx.c | 64 +------------------ source3/param/wscript_build | 5 ++ 4 files changed, 146 insertions(+), 63 deletions(-) create mode 100644 script/mks3param_ctx_table.pl diff --git a/lib/param/wscript_build b/lib/param/wscript_build index 10e05a3..0e1a2e0 100644 --- a/lib/param/wscript_build +++ b/lib/param/wscript_build @@ -11,6 +11,7 @@ bld.SAMBA_GENERATOR('s3_param_h', target='s3_param.h', rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') + bld.SAMBA_GENERATOR('param_global_h', source= '../../script/mkparamdefs.pl loadparm.c param_functions.c', target='param_global.h', diff --git a/script/mks3param_ctx_table.pl b/script/mks3param_ctx_table.pl new file mode 100644 index 0000000..cfd6e02 --- /dev/null +++ b/script/mks3param_ctx_table.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl +# Generate loadparm interfaces tables for Samba3/Samba4 integration +# by Andrew Bartlett +# based on mkproto.pl Written by Jelmer Vernooij +# based on the original mkproto.sh by Andrew Tridgell + +use strict; + +# don't use warnings module as it is not portable enough +# use warnings; + +use Getopt::Long; +use File::Basename; +use File::Path; + +##################################################################### +# read a file into a string + +my $file = undef; +my $public_define = undef; +my $_public = ""; +my $_private = ""; +my $public_data = \$_public; +my $builddir = "."; +my $srcdir = "."; + +sub public($) +{ + my ($d) = @_; + $$public_data .= $d; +} + +sub usage() +{ + print "Usage: mks3param.pl [options] [c files]\n"; + print "OPTIONS:\n"; + print " --srcdir=path Read files relative to this directory\n"; + print " --builddir=path Write file relative to this directory\n"; + print " --help Print this help message\n\n"; + exit 0; +} + +GetOptions( + 'file=s' => sub { my ($f,$v) = @_; $file = $v; }, + 'srcdir=s' => sub { my ($f,$v) = @_; $srcdir = $v; }, + 'builddir=s' => sub { my ($f,$v) = @_; $builddir = $v; }, + 'help' => \&usage +) or exit(1); + +sub file_load($) +{ + my($filename) = @_; + local(*INPUTFILE); + open(INPUTFILE, $filename) or return undef; + my($saved_delim) = $/; + undef $/; + my($data) = ; + close(INPUTFILE); + $/ = $saved_delim; + return $data; +} + +sub print_header($) +{ + my ($file) = @_; + $file->("/* This file was automatically generated by mks3param_ctx.pl. DO NOT EDIT */\n\n"); + $file->("static const struct loadparm_s3_helpers s3_fns = \n"); + $file->("{\n"); + $file->("\t.get_parametric = lp_parm_const_string_service,\n"); + $file->("\t.get_parm_struct = lp_get_parameter,\n"); + $file->("\t.get_parm_ptr = lp_parm_ptr,\n"); + $file->("\t.get_service = lp_service_for_s4_ctx,\n"); + $file->("\t.get_servicebynum = lp_servicebynum_for_s4_ctx,\n"); + $file->("\t.get_default_loadparm_service = lp_default_loadparm_service,\n"); + $file->("\t.get_numservices = lp_numservices,\n"); + $file->("\t.load = lp_load_for_s4_ctx,\n"); + $file->("\t.set_cmdline = lp_set_cmdline,\n"); + $file->("\t.dump = lp_dump,\n"); +} + +sub print_footer($) +{ + my ($file) = @_; + $file->("};"); +} + +sub handle_loadparm($$) +{ + my ($file,$line) = @_; + + # STRING isn't handled here, as we still don't know what to do with the substituted vars */ + # LOCAL also isn't handled here + if ($line =~ /^FN_(GLOBAL)_(CONST_STRING|BOOL|bool|CHAR|INTEGER|LIST)\((\w+),.*\)/o) { + my $scope = $1; + my $type = $2; + my $name = $3; + + $file->(".$name = lp_$name,\n"); + } +} + +sub process_file($$) +{ + my ($file, $filename) = @_; + + $filename =~ s/\.o$/\.c/g; + + if ($filename =~ /^\//) { + open(FH, "<$filename") or die("Failed to open $filename"); + } elsif (!open(FH, "< $builddir/$filename")) { + open(FH, "< $srcdir/$filename") || die "Failed to open $filename"; + } + + my $comment = undef; + my $incomment = 0; + while (my $line = ) { + if ($line =~ /^FN_/) { + handle_loadparm($file, $line); + } + next; + } + + close(FH); +} + + +print_header(\&public); + +process_file(\&public, $_) foreach (@ARGV); +print_footer(\&public); + +if (not defined($file)) { + print STDOUT $$public_data; +} + +mkpath(dirname($file), 0, 0755); +open(PUBLIC, ">$file") or die("Can't open `$file': $!"); +print PUBLIC "$$public_data"; +close(PUBLIC); diff --git a/source3/param/loadparm_ctx.c b/source3/param/loadparm_ctx.c index 63ead53..5cbc920 100644 --- a/source3/param/loadparm_ctx.c +++ b/source3/param/loadparm_ctx.c @@ -56,69 +56,7 @@ static bool lp_load_for_s4_ctx(const char *filename) return status; } -/* These are in the order that they appear in the s4 loadparm file. - * All of the s4 loadparm functions should be here eventually, once - * they are implemented in the s3 loadparm, have the same format (enum - * values in particular) and defaults. */ -static const struct loadparm_s3_helpers s3_fns = -{ - .get_parametric = lp_parm_const_string_service, - .get_parm_struct = lp_get_parameter, - .get_parm_ptr = lp_parm_ptr, - .get_service = lp_service_for_s4_ctx, - .get_servicebynum = lp_servicebynum_for_s4_ctx, - .get_default_loadparm_service = lp_default_loadparm_service, - .get_numservices = lp_numservices, - .load = lp_load_for_s4_ctx, - .set_cmdline = lp_set_cmdline, - .dump = lp_dump, - - ._server_role = lp__server_role, - ._security = lp__security, - ._domain_master = lp__domain_master, - ._domain_logons = lp__domain_logons, - - .winbind_separator = lp_winbind_separator, - .template_homedir = lp_template_homedir, - .template_shell = lp_template_shell, - - .dos_charset = lp_dos_charset, - .unix_charset = lp_unix_charset, - - .realm = lp_realm, - .dnsdomain = lp_dnsdomain, - .socket_options = lp_socket_options, - .workgroup = lp_workgroup, - - .netbios_name = lp_netbios_name, - .netbios_scope = lp_netbios_scope, - .netbios_aliases = lp_netbios_aliases, - - .lanman_auth = lp_lanman_auth, - .ntlm_auth = lp_ntlm_auth, - - .client_plaintext_auth = lp_client_plaintext_auth, - .client_lanman_auth = lp_client_lanman_auth, - .client_ntlmv2_auth = lp_client_ntlmv2_auth, - .client_use_spnego_principal = lp_client_use_spnego_principal, - - .private_dir = lp_private_dir, - .ncalrpc_dir = lp_ncalrpc_dir, - .lockdir = lp_lockdir, - - .passdb_backend = lp_passdb_backend, - - .host_msdfs = lp_host_msdfs, - .unix_extensions = lp_unix_extensions, - .use_spnego = lp_use_spnego, - .use_mmap = lp_use_mmap, - .use_ntdb = lp_use_ntdb, - - .srv_minprotocol = lp_srv_minprotocol, - .srv_maxprotocol = lp_srv_maxprotocol, - - .passwordserver = lp_passwordserver -}; +#include "loadparm_ctx_table.c" const struct loadparm_s3_helpers *loadparm_s3_helpers(void) { diff --git a/source3/param/wscript_build b/source3/param/wscript_build index 643c27e..673cb4d 100644 --- a/source3/param/wscript_build +++ b/source3/param/wscript_build @@ -18,6 +18,11 @@ bld.SAMBA_GENERATOR('s3_param_proto_h', target='param_proto.h', rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') +bld.SAMBA_GENERATOR('s3_loadparm_ctx_table_c', + source= ' ../../script/mks3param_ctx_table.pl ../../lib/param/loadparm.c ../../lib/param/param_functions.c', + target='loadparm_ctx_table.c', + rule='${PERL} ${SRC[0].abspath(env)} ${SRC[1].abspath(env)} ${SRC[2].abspath(env)} --file ${TGT}') + bld.SAMBA3_PYTHON('pys3param', source='pyparam.c', deps='param', -- 1.9.3 From 0046f49e1c690cf5b119859650f06559697fd103 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Oct 2013 15:49:25 +1300 Subject: [PATCH 120/249] proto: Remove manually written lp_ prototypes This also ensures we remove prototypes from parameters we remove or rename, and easily see how many special cases we have left. Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- source3/include/proto.h | 361 +----------------------------------------------- 1 file changed, 1 insertion(+), 360 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 614baa4..5e068d2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -995,379 +995,20 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m #include "source3/param/param_proto.h" -const char **lp_smb_ports(void); -const char *lp_dos_charset(void); -const char *lp_unix_charset(void); -char *lp_logfile(TALLOC_CTX *ctx); -char *lp_configfile(TALLOC_CTX *ctx); -const char *lp_smb_passwd_file(void); -const char *lp_private_dir(void); -char *lp_serverstring(TALLOC_CTX *ctx); -int lp_printcap_cache_time(void); -char *lp_addport_cmd(TALLOC_CTX *ctx); -char *lp_enumports_cmd(TALLOC_CTX *ctx); -char *lp_addprinter_cmd(TALLOC_CTX *ctx); -char *lp_deleteprinter_cmd(TALLOC_CTX *ctx); -char *lp_os2_driver_map(TALLOC_CTX *ctx); -const char *lp_lockdir(void); const char *lp_statedir(void); const char *lp_cachedir(void); -const char *lp_piddir(void); -char *lp_mangling_method(TALLOC_CTX *ctx); -int lp_mangle_prefix(void); -const char *lp_utmpdir(void); -const char *lp_wtmpdir(void); -bool lp_utmp(void); -char *lp_rootdir(TALLOC_CTX *ctx); -char *lp_defaultservice(TALLOC_CTX *ctx); -char *lp_msg_command(TALLOC_CTX *ctx); -char *lp_get_quota_command(TALLOC_CTX *ctx); -char *lp_set_quota_command(TALLOC_CTX *ctx); -char *lp_auto_services(TALLOC_CTX *ctx); -char *lp_passwd_program(TALLOC_CTX *ctx); -char *lp_passwd_chat(TALLOC_CTX *ctx); -const char *lp_passwordserver(void); -const char **lp_name_resolve_order(void); -const char *lp_netbios_scope(void); -const char *lp_netbios_name(void); -const char *lp_workgroup(void); -const char *lp_realm(void); -const char *lp_dnsdomain(void); -const char *lp_afs_username_map(void); -int lp_afs_token_lifetime(void); -char *lp_log_nt_token_command(TALLOC_CTX *ctx); -char *lp_username_map(TALLOC_CTX *ctx); -const char *lp_logon_script(void); -const char *lp_logon_path(void); -const char *lp_logon_drive(void); -const char *lp_logon_home(void); -char *lp_remote_announce(TALLOC_CTX *ctx); -char *lp_remote_browse_sync(TALLOC_CTX *ctx); -bool lp_nmbd_bind_explicit_broadcast(void); -const char **lp_wins_server_list(void); -const char **lp_interfaces(void); -const char *lp_nbt_client_socket_address(void); -char *lp_nis_home_map_name(TALLOC_CTX *ctx); -const char **lp_netbios_aliases(void); -const char *lp_passdb_backend(void); -const char **lp_preload_modules(void); -char *lp_panic_action(TALLOC_CTX *ctx); -char *lp_adduser_script(TALLOC_CTX *ctx); -char *lp_renameuser_script(TALLOC_CTX *ctx); -char *lp_deluser_script(TALLOC_CTX *ctx); -const char *lp_guestaccount(void); -char *lp_addgroup_script(TALLOC_CTX *ctx); -char *lp_delgroup_script(TALLOC_CTX *ctx); -char *lp_addusertogroup_script(TALLOC_CTX *ctx); -char *lp_deluserfromgroup_script(TALLOC_CTX *ctx); -char *lp_setprimarygroup_script(TALLOC_CTX *ctx); -char *lp_addmachine_script(TALLOC_CTX *ctx); -char *lp_shutdown_script(TALLOC_CTX *ctx); -char *lp_abort_shutdown_script(TALLOC_CTX *ctx); -char *lp_username_map_script(TALLOC_CTX *ctx); -int lp_username_map_cache_time(void); -char *lp_check_password_script(TALLOC_CTX *ctx); -char *lp_wins_hook(TALLOC_CTX *ctx); -const char *lp_template_homedir(void); -const char *lp_template_shell(void); -const char *lp_winbind_separator(void); -const char *lp_winbindd_socket_directory(void); -bool lp_winbind_enum_users(void); -bool lp_winbind_enum_groups(void); -bool lp_winbind_use_default_domain(void); -bool lp_winbind_trusted_domains_only(void); -bool lp_winbind_nested_groups(void); -int lp_winbind_expand_groups(void); -bool lp_winbind_refresh_tickets(void); -bool lp_winbind_offline_logon(void); -bool lp_winbind_normalize_names(void); -bool lp_winbind_rpc_only(void); -bool lp_create_krb5_conf(void); int lp_winbind_max_domain_connections(void); -int lp_idmap_cache_time(void); -int lp_idmap_negative_cache_time(void); bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high); bool lp_idmap_default_range(uint32_t *low, uint32_t *high); const char *lp_idmap_backend(const char *domain_name); const char *lp_idmap_default_backend (void); -int lp_keepalive(void); -bool lp_passdb_expand_explicit(void); -char *lp_ldap_suffix(TALLOC_CTX *ctx); -char *lp_ldap_admin_dn(TALLOC_CTX *ctx); -int lp_ldap_ssl(void); -bool lp_ldap_ssl_ads(void); -int lp_ldap_deref(void); -int lp_ldap_follow_referral(void); -int lp_ldap_passwd_sync(void); -bool lp_ldap_delete_dn(void); -int lp_ldap_replication_sleep(void); -int lp_ldap_timeout(void); -int lp_ldap_connection_timeout(void); -int lp_ldap_page_size(void); -int lp_ldap_debug_level(void); -int lp_ldap_debug_threshold(void); -char *lp_add_share_cmd(TALLOC_CTX *ctx); -char *lp_change_share_cmd(TALLOC_CTX *ctx); -char *lp_delete_share_cmd(TALLOC_CTX *ctx); -char *lp_usershare_path(TALLOC_CTX *ctx); -const char **lp_usershare_prefix_allow_list(void); -const char **lp_usershare_prefix_deny_list(void); -const char **lp_eventlog_list(void); -bool lp_registry_shares(void); -bool lp_usershare_allow_guests(void); -bool lp_usershare_owner_only(void); -bool lp_disable_netbios(void); -bool lp_reset_on_zero_vc(void); -bool lp_log_writeable_files_on_exit(void); -bool lp_ms_add_printer_wizard(void); -bool lp_wins_dns_proxy(void); -bool lp_we_are_a_wins_server(void); -bool lp_wins_proxy(void); -bool lp_local_master(void); -const char **lp_init_logon_delayed_hosts(void); -int lp_init_logon_delay(void); -bool lp_load_printers(void); bool lp_readraw(void); -bool lp_large_readwrite(void); bool lp_writeraw(void); -bool lp_null_passwords(void); -bool lp_obey_pam_restrictions(void); -bool lp_encrypted_passwords(void); -int lp_client_schannel(void); -int lp_server_schannel(void); -bool lp_syslog_only(void); -bool lp_timestamp_logs(void); -bool lp_debug_prefix_timestamp(void); -bool lp_debug_hires_timestamp(void); -bool lp_debug_pid(void); -bool lp_debug_uid(void); -bool lp_debug_class(void); -bool lp_enable_core_files(void); -bool lp_browse_list(void); -bool lp_nis_home_map(void); -bool lp_bind_interfaces_only(void); -bool lp_pam_password_change(void); -bool lp_unix_password_sync(void); -bool lp_passwd_chat_debug(void); -int lp_passwd_chat_timeout(void); -bool lp_nt_pipe_support(void); -bool lp_nt_status_support(void); -bool lp_stat_cache(void); -int lp_max_stat_cache_size(void); -bool lp_allow_trusted_domains(void); -bool lp_map_untrusted_to_domain(void); -int lp_restrict_anonymous(void); -bool lp_lanman_auth(void); -bool lp_ntlm_auth(void); -bool lp_client_plaintext_auth(void); -bool lp_client_lanman_auth(void); -bool lp_client_ntlmv2_auth(void); -bool lp_host_msdfs(void); -bool lp_enhanced_browsing(void); -bool lp_use_mmap(void); -bool lp_use_ntdb(void); -bool lp_unix_extensions(void); -bool lp_unicode(void); -bool lp_use_spnego(void); -bool lp_client_use_spnego(void); -bool lp_client_use_spnego_principal(void); -bool lp_hostname_lookups(void); -bool lp_change_notify(const struct share_params *p ); -bool lp_kernel_change_notify(const struct share_params *p ); -const char * lp_dedicated_keytab_file(void); -int lp_kerberos_method(void); -bool lp_defer_sharing_violations(void); -bool lp_enable_privileges(void); -bool lp_enable_asu_support(void); -int lp_os_level(void); -int lp_max_ttl(void); -int lp_max_wins_ttl(void); -int lp_min_wins_ttl(void); -int lp_max_log_size(void); -int lp_max_open_files(void); -int lp_open_files_db_hash_size(void); -int lp_max_xmit(void); -int lp_maxmux(void); -int lp_passwordlevel(void); -int lp_usernamelevel(void); -int lp_deadtime(void); -bool lp_getwd_cache(void); -int lp_srv_maxprotocol(void); -int lp_srv_minprotocol(void); -int lp_cli_maxprotocol(void); -int lp_cli_minprotocol(void); int lp_security(void); -int lp__server_role(void); -int lp__security(void); -int lp__domain_master(void); -bool lp__domain_logons(void); -const char **lp_auth_methods(void); -bool lp_paranoid_server_security(void); -int lp_maxdisksize(void); -int lp_lpqcachetime(void); -int lp_max_smbd_processes(void); -bool lp__disable_spoolss(void); -int lp_syslog(void); -int lp_lm_announce(void); -int lp_lm_interval(void); -int lp_machine_password_timeout(void); -int lp_map_to_guest(void); -int lp_oplock_break_wait_time(void); -int lp_lock_spin_time(void); -int lp_usershare_max_shares(void); -const char *lp_socket_options(void); -int lp_config_backend(void); -int lp_smb2_max_read(void); -int lp_smb2_max_write(void); -int lp_smb2_max_trans(void); int lp_smb2_max_credits(void); -char *lp_preexec(TALLOC_CTX *ctx, int ); -char *lp_postexec(TALLOC_CTX *ctx, int ); -char *lp_rootpreexec(TALLOC_CTX *ctx, int ); -char *lp_rootpostexec(TALLOC_CTX *ctx, int ); -char *lp_servicename(TALLOC_CTX *ctx, int ); -const char *lp_const_servicename(int ); -char *lp_pathname(TALLOC_CTX *ctx, int ); -char *lp_dontdescend(TALLOC_CTX *ctx, int ); -char *lp_username(TALLOC_CTX *ctx, int ); -const char **lp_invalid_users(int ); -const char **lp_valid_users(int ); -const char **lp_admin_users(int ); -const char **lp_svcctl_list(void); -char *lp_cups_options(TALLOC_CTX *ctx, int ); -char *lp_cups_server(TALLOC_CTX *ctx); int lp_cups_encrypt(void); -char *lp_iprint_server(TALLOC_CTX *ctx); -int lp_cups_connection_timeout(void); -const char *lp_ctdbd_socket(void); -const char *_lp_ctdbd_socket(void); -const char **lp_cluster_addresses(void); -bool lp_clustering(void); -int lp_ctdb_timeout(void); -int lp_ctdb_locktime_warn_threshold(void); -char *lp_printcommand(TALLOC_CTX *ctx, int ); -char *lp_lpqcommand(TALLOC_CTX *ctx, int ); -char *lp_lprmcommand(TALLOC_CTX *ctx, int ); -char *lp_lppausecommand(TALLOC_CTX *ctx, int ); -char *lp_lpresumecommand(TALLOC_CTX *ctx, int ); -char *lp_queuepausecommand(TALLOC_CTX *ctx, int ); -char *lp_queueresumecommand(TALLOC_CTX *ctx, int ); -const char *lp_printjob_username(int ); -const char **lp_hostsallow(int ); -const char **lp_hostsdeny(int ); -char *lp_magicscript(TALLOC_CTX *ctx, int ); -char *lp_magicoutput(TALLOC_CTX *ctx, int ); -char *lp_comment(TALLOC_CTX *ctx, int ); -char *lp_force_user(TALLOC_CTX *ctx, int ); -char *lp_force_group(TALLOC_CTX *ctx, int ); -const char **lp_readlist(int ); -const char **lp_writelist(int ); -char *lp_fstype(TALLOC_CTX *ctx, int ); -const char **lp_vfs_objects(int ); -char *lp_msdfs_proxy(TALLOC_CTX *ctx, int ); -char *lp_veto_files(TALLOC_CTX *ctx, int ); -char *lp_hide_files(TALLOC_CTX *ctx, int ); -char *lp_veto_oplocks(TALLOC_CTX *ctx, int ); -bool lp_msdfs_root(int ); -char *lp_aio_write_behind(TALLOC_CTX *ctx, int ); -char *lp_dfree_command(TALLOC_CTX *ctx, int ); -bool lp_autoloaded(int ); -bool lp_preexec_close(int ); -bool lp_rootpreexec_close(int ); -int lp_casesensitive(int ); -bool lp_preservecase(int ); -bool lp_shortpreservecase(int ); -bool lp_hide_dot_files(int ); -bool lp_hide_special_files(int ); -bool lp_hideunreadable(int ); -bool lp_hideunwriteable_files(int ); -bool lp_browseable(int ); -bool lp_access_based_share_enum(int ); -bool lp_readonly(int ); -bool lp_guest_ok(int ); -bool lp_guest_only(int ); -bool lp_administrative_share(int ); -bool lp_print_ok(int ); -bool lp_print_notify_backchannel(int ); -bool lp_map_hidden(int ); -bool lp_map_archive(int ); -bool lp_store_dos_attributes(int ); -bool lp_dmapi_support(int ); -bool lp_locking(const struct share_params *p ); -int lp_strict_locking(const struct share_params *p ); -bool lp_posix_locking(const struct share_params *p ); -bool lp_oplocks(int ); -bool lp_kernel_oplocks(int ); -bool lp_level2_oplocks(int ); -bool lp_kernel_share_modes(int); -bool lp_onlyuser(int ); -bool lp_manglednames(const struct share_params *p ); -bool lp_allow_insecure_widelinks(void); bool lp_widelinks(int ); -bool lp_symlinks(int ); -bool lp_syncalways(int ); -bool lp_strict_allocate(int ); -bool lp_strict_sync(int ); -bool lp_map_system(int ); -bool lp_delete_readonly(int ); -bool lp_fake_oplocks(int ); -bool lp_recursive_veto_delete(int ); -bool lp_dos_filemode(int ); -bool lp_dos_filetimes(int ); -bool lp_dos_filetime_resolution(int ); -bool lp_fake_dir_create_times(int); -bool lp_async_smb_echo_handler(void); -bool lp_multicast_dns_register(void); -bool lp_blocking_locks(int ); -bool lp_inherit_perms(int ); -bool lp_inherit_acls(int ); -bool lp_inherit_owner(int ); -bool lp_use_client_driver(int ); -bool lp_default_devmode(int ); -bool lp_force_printername(int ); -bool lp_nt_acl_support(int ); -bool lp_force_unknown_acl_user(int ); -bool lp_ea_support(int ); -bool lp__use_sendfile(int ); -bool lp_profile_acls(int ); -bool lp_map_acl_inherit(int ); -bool lp_afs_share(int ); -bool lp_acl_check_permissions(int ); -bool lp_acl_group_control(int ); -bool lp_acl_map_full_control(int ); -bool lp_acl_allow_execute_always(int); -bool lp_durable_handles(int); -int lp_create_mask(int ); -int lp_force_create_mode(int ); -int lp_dir_mask(int ); -int lp_force_dir_mode(int ); -int lp_max_connections(int ); -int lp_defaultcase(int ); -int lp_minprintspace(int ); -int lp_printing(int ); -int lp_max_reported_jobs(int ); -int lp_oplock_contention_limit(int ); -int lp_csc_policy(int ); -int lp_write_cache_size(int ); -int lp_block_size(int ); -int lp_dfree_cache_time(int ); -int lp_allocation_roundup_size(int ); -int lp_aio_read_size(int ); -int lp_aio_write_size(int ); -int lp_map_readonly(int ); -int lp_directory_name_cache_size(int ); -int lp_smb_encrypt(int ); -char lp_magicchar(const struct share_params *p ); -int lp_winbind_cache_time(void); -int lp_winbind_reconnect_delay(void); -int lp_winbind_request_timeout(void); -int lp_winbind_max_clients(void); -const char **lp_winbind_nss_info(void); -int lp_algorithmic_rid_base(void); -int lp_name_cache_timeout(void); -int lp_client_signing(void); -int lp_server_signing(void); -int lp_client_ldap_sasl_wrapping(void); + char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def); const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def); struct loadparm_service; -- 1.9.3 From 5d2278756b5a7372106cbdf9b8d66fb8a0cf5033 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 16 Oct 2013 14:45:31 +1300 Subject: [PATCH 121/249] lib/param: Add documentation on how loadparm works Signed-off-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher Reviewed-by: Volker Lendecke --- lib/param/README | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/lib/param/README b/lib/param/README index 403a217..b567d71 100644 --- a/lib/param/README +++ b/lib/param/README @@ -1,4 +1,73 @@ +libsamba-hostconfig +------------------- + This directory contains "libsamba-hostconfig". The libsamba-hostconfig library provides access to all host-wide configuration such as the configured shares, default parameter values and host secret keys. + + +Adding a parameter +------------------ + +To add or change an smb.conf option, you only have to modify +lib/param/param_table.c and lib/param/param_functions.c. The rest is +generated for you. + + +Using smb.conf parameters in the code +------------------------------------- + +Call the lpcfg_*() function. To get the lp_ctx, have the caller pass +it to you. To get a lp_ctx for the source3/param loadparm system, use: + +struct loadparm_context *lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_helpers()); + +Remember to talloc_unlink(tmp_ctx, lp_ctx) the result when you are done! + +To get a lp_ctx for the lib/param loadparm system, typically the +pointer is already set up by popt at startup, and is passed down from +cmdline_lp_ctx. + +In pure source3/ code, you may use lp_*() functions, but are +encouraged to use the lpcfg_*() functions so that code can be made +common. + + +How does loadparm_init_s3() work? +--------------------------------- + +loadparm_s3_helpers() returns a initialised table of function +pointers, pointing at all global lp_*() functions, except for those +that return substituted strings (% macros). The lpcfg_*() function +then calls this plugged in function, allowing the one function and +pattern to use either loadparm system. + + +There is a lot of generated code, here, what generates what? +------------------------------------------------------------ + +The regular format of the CPP macros in param_functions.c is used to +generate up the prototypes (mkproto.pl, mks3param_proto.pl), the service +and globals table (mkparamdefs.pl), the glue table (mmks3param.pl) and +the initilisation of the glue table (mks3param_ctx_table.pl). + +I have tried combining some of these, but it just makes the scripts more +complex. + +The CPP macros are defined in and expand in lib/param/loadparm.c and +source3/param/loadparm.c to read the values from the generated +stuctures. They are CPP #included into these files so that the same +macro has two definitions, depending on the system it is loading into. + + +Why was this done, rather than a 'proper' fix, or just using one system or the other? +------------------------------------------------------------------------------------- + +This was done to allow merging from both ends - merging more parts of +the loadparm handling, and merging code that needs to read the +smb.conf, without having to do it all at once. Ideally +param_functions.c would be generated from param_table.c or (even +better) our XML manpage source, and the CPP macros would instead be +generated expanded as generated C files, but this is a task nobody has +taken on yet. -- 1.9.3 From 7734a867500f5b7415f818077229f74486101c51 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 12 Aug 2013 08:19:08 +0200 Subject: [PATCH 122/249] librpc/rpc: add dcerpc_binding_handle_auth_info() Signed-off-by: Stefan Metzmacher --- librpc/rpc/binding_handle.c | 25 +++++++++++++++++++++++++ librpc/rpc/rpc_common.h | 8 ++++++++ 2 files changed, 33 insertions(+) diff --git a/librpc/rpc/binding_handle.c b/librpc/rpc/binding_handle.c index 9354bbd..714baa7 100644 --- a/librpc/rpc/binding_handle.c +++ b/librpc/rpc/binding_handle.c @@ -98,6 +98,31 @@ uint32_t dcerpc_binding_handle_set_timeout(struct dcerpc_binding_handle *h, return h->ops->set_timeout(h, timeout); } +void dcerpc_binding_handle_auth_info(struct dcerpc_binding_handle *h, + enum dcerpc_AuthType *auth_type, + enum dcerpc_AuthLevel *auth_level) +{ + enum dcerpc_AuthType _auth_type; + enum dcerpc_AuthLevel _auth_level; + + if (auth_type == NULL) { + auth_type = &_auth_type; + } + + if (auth_level == NULL) { + auth_level = &_auth_level; + } + + *auth_type = DCERPC_AUTH_TYPE_NONE; + *auth_level = DCERPC_AUTH_LEVEL_NONE; + + if (h->ops->auth_info == NULL) { + return; + } + + h->ops->auth_info(h, auth_type, auth_level); +} + struct dcerpc_binding_handle_raw_call_state { const struct dcerpc_binding_handle_ops *ops; uint8_t *out_data; diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h index d2816f5..978229e 100644 --- a/librpc/rpc/rpc_common.h +++ b/librpc/rpc/rpc_common.h @@ -189,6 +189,10 @@ struct dcerpc_binding_handle_ops { uint32_t (*set_timeout)(struct dcerpc_binding_handle *h, uint32_t timeout); + void (*auth_info)(struct dcerpc_binding_handle *h, + enum dcerpc_AuthType *auth_type, + enum dcerpc_AuthLevel *auth_level); + struct tevent_req *(*raw_call_send)(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct dcerpc_binding_handle *h, @@ -259,6 +263,10 @@ bool dcerpc_binding_handle_is_connected(struct dcerpc_binding_handle *h); uint32_t dcerpc_binding_handle_set_timeout(struct dcerpc_binding_handle *h, uint32_t timeout); +void dcerpc_binding_handle_auth_info(struct dcerpc_binding_handle *h, + enum dcerpc_AuthType *auth_type, + enum dcerpc_AuthLevel *auth_level); + struct tevent_req *dcerpc_binding_handle_raw_call_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct dcerpc_binding_handle *h, -- 1.9.3 From 04a9531474630c62c3f717e251d9f1469013f5ae Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 12 Aug 2013 08:19:35 +0200 Subject: [PATCH 123/249] s3:rpc_client: implement dcerpc_binding_handle_auth_info() Signed-off-by: Stefan Metzmacher --- source3/rpc_client/cli_pipe.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 64e7f1c..a343997 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1867,6 +1867,25 @@ static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h, return rpccli_set_timeout(hs->rpc_cli, timeout); } +static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h, + enum dcerpc_AuthType *auth_type, + enum dcerpc_AuthLevel *auth_level) +{ + struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h, + struct rpccli_bh_state); + + if (hs->rpc_cli == NULL) { + return; + } + + if (hs->rpc_cli->auth == NULL) { + return; + } + + *auth_type = hs->rpc_cli->auth->auth_type; + *auth_level = hs->rpc_cli->auth->auth_level; +} + struct rpccli_bh_raw_call_state { DATA_BLOB in_data; DATA_BLOB out_data; @@ -2046,6 +2065,7 @@ static const struct dcerpc_binding_handle_ops rpccli_bh_ops = { .name = "rpccli", .is_connected = rpccli_bh_is_connected, .set_timeout = rpccli_bh_set_timeout, + .auth_info = rpccli_bh_auth_info, .raw_call_send = rpccli_bh_raw_call_send, .raw_call_recv = rpccli_bh_raw_call_recv, .disconnect_send = rpccli_bh_disconnect_send, -- 1.9.3 From 1db891bac30bb6c3bb0a022c5d1529a9f001237d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 12 Aug 2013 08:19:57 +0200 Subject: [PATCH 124/249] s4:librpc: implement dcerpc_binding_handle_auth_info() Signed-off-by: Stefan Metzmacher --- source4/librpc/rpc/dcerpc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 2826160..56b821e 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -200,6 +200,29 @@ static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h, return old; } +static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h, + enum dcerpc_AuthType *auth_type, + enum dcerpc_AuthLevel *auth_level) +{ + struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h, + struct dcerpc_bh_state); + + if (hs->p == NULL) { + return; + } + + if (hs->p->conn == NULL) { + return; + } + + if (hs->p->conn->security_state.auth_info == NULL) { + return; + } + + *auth_type = hs->p->conn->security_state.auth_info->auth_type; + *auth_level = hs->p->conn->security_state.auth_info->auth_level; +} + struct dcerpc_bh_raw_call_state { struct tevent_context *ev; struct dcerpc_binding_handle *h; @@ -552,6 +575,7 @@ static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = { .name = "dcerpc", .is_connected = dcerpc_bh_is_connected, .set_timeout = dcerpc_bh_set_timeout, + .auth_info = dcerpc_bh_auth_info, .raw_call_send = dcerpc_bh_raw_call_send, .raw_call_recv = dcerpc_bh_raw_call_recv, .disconnect_send = dcerpc_bh_disconnect_send, -- 1.9.3 From 76304ed57d561eb89dceb3881236a78209dd592c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Sep 2013 04:25:39 +0200 Subject: [PATCH 125/249] s3:winbindd: don't hide the error in cm_connect_lsa() We should not overwrite the error with NT_STATUS_PIPE_NOT_AVAILABLE. Signed-off-by: Stefan Metzmacher --- source3/winbindd/winbindd_cm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index d868826..c4f59d3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2677,7 +2677,6 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, &ndr_table_lsarpc, &conn->lsa_pipe); if (!NT_STATUS_IS_OK(result)) { - result = NT_STATUS_PIPE_NOT_AVAILABLE; goto done; } -- 1.9.3 From 9948366e88b1d11127317008c79a2f7182a34d65 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Sep 2013 09:24:42 +0200 Subject: [PATCH 126/249] s3:include: add forward declaration for struct messaging_context; in g_lock.h Signed-off-by: Stefan Metzmacher --- source3/include/g_lock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/include/g_lock.h b/source3/include/g_lock.h index 004c452..f513349 100644 --- a/source3/include/g_lock.h +++ b/source3/include/g_lock.h @@ -23,6 +23,7 @@ #include "dbwrap/dbwrap.h" struct g_lock_ctx; +struct messaging_context; enum g_lock_type { G_LOCK_READ = 0, -- 1.9.3 From 4c30267e3c26cb065b908ff396ca21937fc870c4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Sep 2013 19:29:05 +0200 Subject: [PATCH 127/249] s3:include: fix messaging_send_buf() protype in messages.h The function already used 'uint8_t' instead of 'uint8'. Signed-off-by: Stefan Metzmacher --- source3/include/messages.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/include/messages.h b/source3/include/messages.h index 09c39cc..50b2a84 100644 --- a/source3/include/messages.h +++ b/source3/include/messages.h @@ -139,7 +139,7 @@ NTSTATUS messaging_send(struct messaging_context *msg_ctx, NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx, struct server_id server, uint32_t msg_type, - const uint8 *buf, size_t len); + const uint8_t *buf, size_t len); void messaging_dispatch_rec(struct messaging_context *msg_ctx, struct messaging_rec *rec); -- 1.9.3 From ff45e4d1ca6cff9b2f329d18e98ebd4883639ed9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Aug 2013 12:09:51 +0200 Subject: [PATCH 128/249] s3:auth_domain: remove dead code in check_trustdomain_security() Signed-off-by: Stefan Metzmacher --- source3/auth/auth_domain.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 06078e2..9f88c4a 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -378,8 +378,6 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte struct auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - unsigned char trust_md4_password[16]; - char *trust_password; fstring dc_name; struct sockaddr_storage dc_ss; @@ -408,26 +406,6 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte if ( !is_trusted_domain( user_info->mapped.domain_name ) ) return NT_STATUS_NOT_IMPLEMENTED; - /* - * Get the trusted account password for the trusted domain - * No need to become_root() as secrets_init() is done at startup. - */ - - if (!pdb_get_trusteddom_pw(user_info->mapped.domain_name, &trust_password, - NULL, NULL)) { - DEBUG(0, ("check_trustdomain_security: could not fetch trust " - "account password for domain %s\n", - user_info->mapped.domain_name)); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("Trust password for domain %s is %s\n", user_info->mapped.domain_name, - trust_password)); -#endif - E_md4hash(trust_password, trust_md4_password); - SAFE_FREE(trust_password); - /* use get_dc_name() for consistency even through we know that it will be a netbios name */ -- 1.9.3 From d9160b0834f74508b711eeec0354aa43d5a1b215 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Sep 2013 20:18:39 +0200 Subject: [PATCH 129/249] s3:libsmb: remove unused change_trust_account_password() Signed-off-by: Stefan Metzmacher --- source3/include/proto.h | 1 - source3/libsmb/trusts_util.c | 72 -------------------------------------------- 2 files changed, 73 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 5e068d2..a40d3c1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -989,7 +989,6 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *domain) ; -NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine); /* The following definitions come from param/loadparm.c */ diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 6156ba0..8a0e53d 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -135,75 +135,3 @@ NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, sec_channel_type); } -NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct sockaddr_storage pdc_ss; - fstring dc_name; - struct cli_state *cli = NULL; - struct rpc_pipe_client *netlogon_pipe = NULL; - - DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n", - domain)); - - if (remote_machine == NULL || !strcmp(remote_machine, "*")) { - /* Use the PDC *only* for this */ - - if ( !get_pdc_ip(domain, &pdc_ss) ) { - DEBUG(0,("Can't get IP for PDC for domain %s\n", domain)); - goto failed; - } - - if ( !name_status_find( domain, 0x1b, 0x20, &pdc_ss, dc_name) ) - goto failed; - } else { - /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ - fstrcpy( dc_name, remote_machine ); - } - - /* if this next call fails, then give up. We can't do - password changes on BDC's --jerry */ - - if (!NT_STATUS_IS_OK(cli_full_connection(&cli, lp_netbios_name(), dc_name, - NULL, 0, - "IPC$", "IPC", - "", "", - "", 0, SMB_SIGNING_DEFAULT))) { - DEBUG(0,("modify_trust_password: Connection to %s failed!\n", dc_name)); - nt_status = NT_STATUS_UNSUCCESSFUL; - goto failed; - } - - /* - * Ok - we have an anonymous connection to the IPC$ share. - * Now start the NT Domain stuff :-). - */ - - /* Shouldn't we open this with schannel ? JRA. */ - - nt_status = cli_rpc_pipe_open_noauth( - cli, &ndr_table_netlogon, &netlogon_pipe); - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", - dc_name, nt_errstr(nt_status))); - cli_shutdown(cli); - cli = NULL; - goto failed; - } - - nt_status = trust_pw_find_change_and_store_it( - netlogon_pipe, netlogon_pipe, domain); - - cli_shutdown(cli); - cli = NULL; - -failed: - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", - current_timestring(talloc_tos(), False), domain)); - } - else - DEBUG(5,("change_trust_account_password: sucess!\n")); - - return nt_status; -} -- 1.9.3 From c6b50a3d8c382f19a8ae16428d557928438be464 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Sep 2013 20:19:28 +0200 Subject: [PATCH 130/249] s3:libsmb: inline trust_pw_change_and_store_it() into trust_pw_find_change_and_store_it() Signed-off-by: Stefan Metzmacher --- source3/include/proto.h | 5 ----- source3/libsmb/trusts_util.c | 50 +++++++++++++------------------------------- 2 files changed, 15 insertions(+), 40 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index a40d3c1..216a377 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -981,11 +981,6 @@ void update_trustdom_cache( void ); /* The following definitions come from libsmb/trusts_util.c */ -NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, - const char *domain, - const char *account_name, - unsigned char orig_trust_passwd_hash[16], - enum netr_SchannelType sec_channel_type); NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *domain) ; diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 8a0e53d..428e0c1 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -29,20 +29,27 @@ /********************************************************* Change the domain password on the PDC. - Store the password ourselves, but use the supplied password - Caller must have already setup the connection to the NETLOGON pipe + Do most of the legwork ourselfs. Caller must have + already setup the connection to the NETLOGON pipe **********************************************************/ -NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, - const char *domain, - const char *account_name, - unsigned char orig_trust_passwd_hash[16], - enum netr_SchannelType sec_channel_type) +NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *domain) { + unsigned char old_trust_passwd_hash[16]; unsigned char new_trust_passwd_hash[16]; + enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; + const char *account_name; char *new_trust_passwd; NTSTATUS nt_status; + if (!get_trust_pw_hash(domain, old_trust_passwd_hash, &account_name, + &sec_channel_type)) { + DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); + return NT_STATUS_UNSUCCESSFUL; + } + switch (sec_channel_type) { case SEC_CHAN_WKSTA: case SEC_CHAN_DOMAIN: @@ -64,7 +71,7 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx, account_name, - orig_trust_passwd_hash, + old_trust_passwd_hash, new_trust_passwd, new_trust_passwd_hash, sec_channel_type); @@ -108,30 +115,3 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m return nt_status; } - -/********************************************************* - Change the domain password on the PDC. - Do most of the legwork ourselfs. Caller must have - already setup the connection to the NETLOGON pipe -**********************************************************/ - -NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - const char *domain) -{ - unsigned char old_trust_passwd_hash[16]; - enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; - const char *account_name; - - if (!get_trust_pw_hash(domain, old_trust_passwd_hash, &account_name, - &sec_channel_type)) { - DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); - return NT_STATUS_UNSUCCESSFUL; - } - - return trust_pw_change_and_store_it(cli, mem_ctx, domain, - account_name, - old_trust_passwd_hash, - sec_channel_type); -} - -- 1.9.3 From fdac5d6b0ed96f262830a3a923b9d2a42d7fd98d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Sep 2013 04:14:00 +0200 Subject: [PATCH 131/249] s4:librpc: make dcerpc_schannel_key_send/recv static Signed-off-by: Stefan Metzmacher --- source4/librpc/rpc/dcerpc_schannel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index 130ebeb..cd62508 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -306,7 +306,7 @@ static void continue_srv_auth2(struct tevent_req *subreq) Initiate establishing a schannel key using netlogon challenge on a secondary pipe */ -struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, +static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p, struct cli_credentials *credentials, struct loadparm_context *lp_ctx) @@ -369,7 +369,7 @@ struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, /* Receive result of schannel key request */ -NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c) +static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c) { NTSTATUS status = composite_wait(c); -- 1.9.3 From de42a3f8b1a69a5abd5fb1a95e1c5f80ee68430e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Sep 2013 04:16:00 +0200 Subject: [PATCH 132/249] s4:librpc: let dcerpc_schannel_key_recv() return netlogon_creds_CredentialState cli_credentials_set_netlogon_creds() should only be used directly before a DCERPC bind in order to pass the session information to the gensec layer. Signed-off-by: Stefan Metzmacher --- source4/librpc/rpc/dcerpc_schannel.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index cd62508..c4bedfa 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -296,9 +296,6 @@ static void continue_srv_auth2(struct tevent_req *subreq) return; } - /* setup current netlogon credentials */ - cli_credentials_set_netlogon_creds(s->credentials, s->creds); - composite_done(c); } @@ -369,10 +366,19 @@ static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx, /* Receive result of schannel key request */ -static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c) +static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **creds) { NTSTATUS status = composite_wait(c); - + + if (NT_STATUS_IS_OK(status)) { + struct schannel_key_state *s = + talloc_get_type_abort(c->private_data, + struct schannel_key_state); + *creds = talloc_move(mem_ctx, &s->creds); + } + talloc_free(c); return status; } @@ -410,13 +416,15 @@ static void continue_schannel_key(struct composite_context *ctx) NTSTATUS status; /* receive schannel key */ - status = c->status = dcerpc_schannel_key_recv(ctx); + status = c->status = dcerpc_schannel_key_recv(ctx, s, &s->creds_state); if (!composite_is_ok(c)) { DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status))); return; } /* send bind auth request with received creds */ + cli_credentials_set_netlogon_creds(s->credentials, s->creds_state); + auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, lpcfg_gensec_settings(c, s->lp_ctx), DCERPC_AUTH_TYPE_SCHANNEL, s->auth_level, @@ -447,9 +455,6 @@ static void continue_bind_auth(struct composite_context *ctx) &ndr_table_netlogon.syntax_id)) { ZERO_STRUCT(s->return_auth); - s->creds_state = cli_credentials_get_netlogon_creds(s->credentials); - if (composite_nomem(s->creds_state, c)) return; - s->save_creds_state = *s->creds_state; netlogon_creds_client_authenticator(&s->save_creds_state, &s->auth); @@ -528,6 +533,7 @@ static void continue_get_capabilities(struct tevent_req *subreq) } *s->creds_state = s->save_creds_state; + cli_credentials_set_netlogon_creds(s->credentials, s->creds_state); if (!NT_STATUS_IS_OK(s->c.out.result)) { composite_error(c, s->c.out.result); -- 1.9.3 From f6a6e4e91b676461dc8b6dd5abca4120d9bf920a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Sep 2013 04:33:07 +0200 Subject: [PATCH 133/249] auth:credentials: avoid talloc_reference in cli_credentials_set_netlogon_creds() Typically cli_credentials_set_netlogon_creds() should be used directly before the DCERPC bind. And cli_credentials_get_netlogon_creds() should be only used by the gensec layer, which only needs a copy. Signed-off-by: Stefan Metzmacher --- auth/credentials/credentials.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/auth/credentials/credentials.c b/auth/credentials/credentials.c index 57a7c0b..9ce38d0 100644 --- a/auth/credentials/credentials.c +++ b/auth/credentials/credentials.c @@ -814,7 +814,11 @@ _PUBLIC_ void cli_credentials_guess(struct cli_credentials *cred, _PUBLIC_ void cli_credentials_set_netlogon_creds(struct cli_credentials *cred, struct netlogon_creds_CredentialState *netlogon_creds) { - cred->netlogon_creds = talloc_reference(cred, netlogon_creds); + TALLOC_FREE(cred->netlogon_creds); + if (netlogon_creds == NULL) { + return; + } + cred->netlogon_creds = netlogon_creds_copy(cred, netlogon_creds); } /** -- 1.9.3 From 14b9bb276a798ad71776ebcb698afeeb44aa173a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 9 Nov 2013 19:14:15 +0100 Subject: [PATCH 134/249] libsmb: Fix CID 1127343 Dead default in switch We have checked sec_channel_type a few lines above already Signed-off-by: Volker Lendecke Reviewed-by: Ira Cooper (cherry picked from commit 1cae867f72b79995a02eed96265fe9f69ce945da) --- source3/libsmb/trusts_util.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 428e0c1..52fb481 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -108,8 +108,6 @@ NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, } break; } - default: - break; } } -- 1.9.3 From efb32bbe25d534f69aca03e0945220cb5049c366 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 29 Nov 2013 09:46:01 +0100 Subject: [PATCH 135/249] s3:rpc_server: use make_session_info_guest() directly This removes the useless static auth_anonymous_session_info() wrapper. auth_anonymous_session_info() is also a public function in source4. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit ae6720117ae5fb3c922486ce46e2b0d51e020301) --- source3/rpc_server/rpc_server.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c index de54ddc..c3a7f28 100644 --- a/source3/rpc_server/rpc_server.c +++ b/source3/rpc_server/rpc_server.c @@ -37,19 +37,6 @@ #define SERVER_TCP_LOW_PORT 1024 #define SERVER_TCP_HIGH_PORT 1300 -static NTSTATUS auth_anonymous_session_info(TALLOC_CTX *mem_ctx, - struct auth_session_info **session_info) -{ - NTSTATUS status; - - status = make_session_info_guest(mem_ctx, session_info); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} - /* Creates a pipes_struct and initializes it with the information * sent from the client */ static int make_server_pipes_struct(TALLOC_CTX *mem_ctx, @@ -1067,11 +1054,14 @@ void dcerpc_ncacn_accept(struct tevent_context *ev_ctx, } if (ncacn_conn->session_info == NULL) { - status = auth_anonymous_session_info(ncacn_conn, - &ncacn_conn->session_info); + /* + * TODO: use auth_anonymous_session_info() here? + */ + status = make_session_info_guest(ncacn_conn, + &ncacn_conn->session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("Failed to create " - "auth_anonymous_session_info - %s\n", + "make_session_info_guest - %s\n", nt_errstr(status))); talloc_free(ncacn_conn); return; -- 1.9.3 From 215d591403e63b785308ff5d6b2e3c87ad9ee408 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Fri, 29 Nov 2013 16:51:08 +1300 Subject: [PATCH 136/249] selftest: add new rpc client test Pair-programmed-with: Andrew Bartlett Signed-off-by: Garming Sam Signed-off-by: Andrew Bartlett Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher (cherry picked from commit 0e46205ff83d137ca486868e4376b258b6dfa1a2) --- source3/script/tests/test_rpcclient_samlogon.sh | 27 +++++++++++++++++++++++++ source3/selftest/tests.py | 2 ++ 2 files changed, 29 insertions(+) create mode 100755 source3/script/tests/test_rpcclient_samlogon.sh diff --git a/source3/script/tests/test_rpcclient_samlogon.sh b/source3/script/tests/test_rpcclient_samlogon.sh new file mode 100755 index 0000000..01af7f8 --- /dev/null +++ b/source3/script/tests/test_rpcclient_samlogon.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +if [ $# -lt 3 ]; then +cat < +EOF +exit 1; +fi + +USERNAME="$1" +PASSWORD="$2" +shift 2 +ADDARGS="$*" + +rpcclient_samlogon() +{ + $VALGRIND $BINDIR/rpcclient -U% -c "samlogon $USERNAME $PASSWORD;samlogon $USERNAME $PASSWORD" $@ +} + + +incdir=`dirname $0`/../../../testprogs/blackbox +. $incdir/subunit.sh +testit "rpcclient dsenumdomtrusts" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "dsenumdomtrusts" || failed=`expr $failed + 1` +testit "rpcclient getdcsitecoverage" $VALGRIND $BINDIR/rpcclient $ADDARGS -U% -c "getdcsitecoverage" || failed=`expr $failed + 1` +testit "rpcclient samlogon" rpcclient_samlogon $ADDARGS || failed=`expr $failed +1` + +testok $0 $failed diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 85d67d6..f9cc3d1 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -394,6 +394,8 @@ for s in signseal_options: plantestsuite("samba3.blackbox.rpcclient krb5 ncacn_np with [%s%s%s] " % (a, s, e), "ktest:local", [os.path.join(samba3srcdir, "script/tests/test_rpcclient.sh"), "$PREFIX/ktest/krb5_ccache-3", binding_string, "-k", configuration]) +plantestsuite("samba3.blackbox.rpcclient_samlogon", "s3member:local", [os.path.join(samba3srcdir, "script/tests/test_rpcclient_samlogon.sh"), + "$DC_USERNAME", "$DC_PASSWORD", "ncacn_np:$DC_SERVER", configuration]) options_list = ["", "-e"] for options in options_list: -- 1.9.3 From 05251d449931c29a0bb0c0b8ad194253dc5b66cb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 29 Nov 2013 08:45:38 +0100 Subject: [PATCH 137/249] s3:rpcclient: close the connection if setting up the netlogon secure channel fails This is based on a patch from Garming Sam . Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 2fae806550f3355298541a344b217bf810bf92e4) --- source3/rpcclient/rpcclient.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index cb7b70f..0cbec20 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -768,6 +768,10 @@ static NTSTATUS do_cmd(struct cli_state *cli, trust_password, &machine_account, &sec_channel_type)) { + DEBUG(0, ("Failed to fetch trust password for %s to connect to %s.\n", + get_cmdline_auth_info_domain(auth_info), + cmd_entry->table->name)); + TALLOC_FREE(cmd_entry->rpc_pipe); talloc_free(mem_ctx); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -784,6 +788,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, if (!NT_STATUS_IS_OK(ntresult)) { DEBUG(0, ("Could not initialise credentials for %s.\n", cmd_entry->table->name)); + TALLOC_FREE(cmd_entry->rpc_pipe); talloc_free(mem_ctx); return ntresult; } -- 1.9.3 From 8d3336b9a61a185a4194313fec338321fed6b151 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Mon, 2 Dec 2013 13:20:39 +1300 Subject: [PATCH 138/249] selftest: add new credential change test Signed-off-by: Garming Sam Reviewed-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 48820b95285f7dffd827143ba56f432f3e283a6f) --- source3/script/tests/test_net_cred_change.sh | 16 ++++++++++++++++ source3/selftest/tests.py | 3 +++ 2 files changed, 19 insertions(+) create mode 100755 source3/script/tests/test_net_cred_change.sh diff --git a/source3/script/tests/test_net_cred_change.sh b/source3/script/tests/test_net_cred_change.sh new file mode 100755 index 0000000..9013d07 --- /dev/null +++ b/source3/script/tests/test_net_cred_change.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +if [ $# -lt 1 ]; then +cat < Date: Mon, 23 Dec 2013 17:12:39 +1300 Subject: [PATCH 139/249] selftest: add rodc and other env tests for wbinfo Pair-programmed-with: Andrew Bartlett Signed-off-by: Garming Sam Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Mon Dec 23 17:17:39 CET 2013 on sn-devel-104 (cherry picked from commit 819e1f561df5074ae21db77c6558b34f4b0e1351) --- source4/selftest/tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index e738d1d9..c3a33c7 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -309,8 +309,8 @@ plantestsuite("samba4.blackbox.locktest(dc)", "dc", [os.path.join(samba4srcdir, plantestsuite("samba4.blackbox.masktest", "dc", [os.path.join(samba4srcdir, "torture/tests/test_masktest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', '$PREFIX']) plantestsuite("samba4.blackbox.gentest(dc)", "dc", [os.path.join(samba4srcdir, "torture/tests/test_gentest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', "$PREFIX"]) plantestsuite("samba4.blackbox.rfc2307_mapping(dc:local)", "dc:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_rfc2307_mapping.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "$SERVER", "$UID_RFC2307TEST", "$GID_RFC2307TEST", configuration]) -plantestsuite("samba4.blackbox.wbinfo(dc:local)", "dc:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "dc"]) -plantestsuite("samba4.blackbox.wbinfo(s4member:local)", "s4member:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', "s4member"]) +for env in ["dc", "s4member", "rodc", "promoted_dc"]: + plantestsuite("samba4.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', "CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX', "aes256-cts-hmac-sha1-96", '$SELFTEST_PREFIX/chgdcpass', smbclient4]) plantestsuite("samba4.blackbox.samba_upgradedns(chgdcpass:local)", "chgdcpass:local", [os.path.join(bbdir, "test_samba_upgradedns.sh"), '$SERVER', '$REALM', '$PREFIX', '$SELFTEST_PREFIX/chgdcpass']) plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "dc", [valgrindify(smbtorture4), "$LISTOPT", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) -- 1.9.3 From 689deff949e8ce9b6aa900e7b0c714d5a025d516 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Dec 2013 19:35:37 +0100 Subject: [PATCH 140/249] libcli/auth: set the return_authenticator->timestamp = 0 This is what windows returns, the value is ignored by the client anyway. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 202bcf9096e53d94b294936d6144ae77f1536b72) --- libcli/auth/credentials.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 1f664d3..197db86 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -479,7 +479,7 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState netlogon_creds_step(creds); if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) { return_authenticator->cred = creds->server; - return_authenticator->timestamp = creds->sequence; + return_authenticator->timestamp = 0; return NT_STATUS_OK; } else { ZERO_STRUCTP(return_authenticator); -- 1.9.3 From fe8a979787c9528bb3b403272be3dc6a313bbebd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Dec 2013 19:40:15 +0100 Subject: [PATCH 141/249] libcli/auth: remove bogus comment regarding replay attacks creds->sequence (timestamp) is the value that is used to increment the internal state, it's not a real sequence number. The sequence comes from adding all timestamps of the whole session. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 636daac3b7b08ccb8845dab060157918d296ef67) --- libcli/auth/credentials.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 197db86..afb4a04 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -473,8 +473,6 @@ NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState return NT_STATUS_ACCESS_DENIED; } - /* TODO: this may allow the a replay attack on a non-signed - connection. Should we check that this is increasing? */ creds->sequence = received_authenticator->timestamp; netlogon_creds_step(creds); if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) { -- 1.9.3 From 1f6a52bb1f756be05e28dc9e16725ac73b005d00 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Dec 2013 19:55:12 +0100 Subject: [PATCH 142/249] libcli/auth: try to use the current timestamp creds->sequence If the last usage of netlogon_creds_client_authenticator() is in the past try to use the current timestamp and increment more than just 2. If we use netlogon_creds_client_authenticator() a lot within a second, we increment keep incrementing by 2. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Tue Dec 24 13:18:18 CET 2013 on sn-devel-104 (cherry picked from commit e6afeae69537f55ed187b28b60ad29b9e237ec6e) --- libcli/auth/credentials.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index afb4a04..f52538a 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -344,7 +344,29 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TA void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds, struct netr_Authenticator *next) { + uint32_t t32n = (uint32_t)time(NULL); + + /* + * we always increment and ignore an overflow here + */ creds->sequence += 2; + + if (t32n > creds->sequence) { + /* + * we may increment more + */ + creds->sequence = t32n; + } else { + uint32_t d = creds->sequence - t32n; + + if (d >= INT32_MAX) { + /* + * got an overflow of time_t vs. uint32_t + */ + creds->sequence = t32n; + } + } + netlogon_creds_step(creds); next->cred = creds->client; -- 1.9.3 From 1cc32f5bf176a6daba93603a5b9aa4fc4fe42479 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 12:56:38 +0100 Subject: [PATCH 143/249] s4:selftest: run wbinfo tests at the end... This avoids flakey crashes in the promoted_dc environment. See the examples below, we had up to 50% of the daily build failing... Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett https://git.samba.org/autobuild.flakey/2013-12-23-1942/samba.stdout [1586/1594 in 1h39m20s] samba4.drs.fsmo.python(promoted_dc) Testing for schema role transfer from localdc.samba.example.com to PROMOTEDVDC.samba.example.com FSMO transfer of 'schema' role successful Testing for schema role transfer from PROMOTEDVDC.samba.example.com to localdc.samba.example.com ERROR: Failed to initiate transfer of 'schema' role: LDAP error 52 LDAP_UNAVAILABLE - <> UNEXPECTED(failure): samba4.drs.fsmo.python(promoted_dc).fsmo.DrsFsmoTestCase.test_SchemaMasterTransfer(promoted_dc) REASON: _StringException: _StringException: Content-Type: text/x-traceback;charset=utf8,language=python traceback 380 https://git.samba.org/autobuild.flakey/2013-12-24-1546/samba.stdout [1583/1594 in 1h36m4s] samba.tests.blackbox.samba_tool_drs ERROR: Testsuite[samba.tests.blackbox.samba_tool_drs] REASON: unable to set up environment promoted_dc - exiting https://git.samba.org/autobuild.flakey/2013-12-24-1546/samba.stderr Unable to convert 1.2.840.86419.1.5.9939 to an attid, and can_change_pfm=false! Unable to convert governsID on CN=test-class30318,CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com to DRS object - WERR_NOT_FOUND ../source4/rpc_server/drsuapi/getncchanges.c:1646: DsGetNCChanges 2nd replication on different DN CN=Configuration,DC=samba,DC=example,DC=com CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com (last_dn CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com) =============================================================== INTERNAL ERROR: Signal 11 in pid 884274 (4.2.0pre1-DEVELOPERBUILD) Please read the Trouble-Shooting section of the Samba HOWTO =============================================================== smb_panic(): calling panic action [/memdisk/autobuild/fl/b302436/samba/selftest/gdb_backtrace 884274] [Thread debugging using libthread_db enabled] 0x00002af6b5c1977e in __libc_waitpid (pid=, stat_loc=0x7fff67c7709c, options=) at ../sysdeps/unix/sysv/linux/waitpid.c:32 32 ../sysdeps/unix/sysv/linux/waitpid.c: No such file or directory. in ../sysdeps/unix/sysv/linux/waitpid.c #0 0x00002af6b5c1977e in __libc_waitpid (pid=, stat_loc=0x7fff67c7709c, options=) at ../sysdeps/unix/sysv/linux/waitpid.c:32 oldtype = result = #1 0x00002af6b5baeb39 in do_system (line=) at ../sysdeps/posix/system.c:149 __result = -512 _buffer = {__routine = 0x2af6b5baee90 , __arg = 0x7fff67c77098, __canceltype = 0, __prev = 0x0} _avail = 1 status = save = pid = 886733 sa = {__sigaction_handler = {sa_handler = 0x1, sa_sigaction = 0x1}, sa_mask = {__val = {65536, 0 }}, sa_flags = 0, sa_restorer = 0x2af6b5b730f0} omask = {__val = {7808, 4294967295, 140734934511616, 1, 2195512, 0, 0, 0, 47239032274944, 47239027992529, 140733193388033, 0, 0, 47239099003120, 140734934511792, 47239558787328}} #2 0x00002af6b311821f in smb_panic_default ( why=0x2af6b312a875 "internal error") at ../lib/util/fault.c:134 result = 32767 pidstr = "884274\000\000\001\375\376\320\366*\000\000\260\377\377\377" cmdstring = "/memdisk/autobuild/fl/b302436/samba/selftest/gdb_backtrace 884274\000\307g\377\177\000\000\001\000\000\000\000\000\000\000\320\301#", '\000' "\240, \017\263\366*\000\000\321\247{\261\366*\000\000\001\000\000\000\005", '\000' "\260, \016\v\321\366*\000\000X\351\017\263\366*\000\000\260q\307g\377\177\000\000\000\361\036\321\366*\000\000\020r\307g\377\177\000\000\240\301z\326\366*\000\000\000Z\304\320\366*\000" __FUNCTION__ = "smb_panic_default" #3 0x00002af6b31183b5 in smb_panic (why=0x2af6b312a875 "internal error") at ../lib/util/fault.c:162 No locals. #4 0x00002af6b311809f in fault_report (sig=11) at ../lib/util/fault.c:77 counter = 1 __FUNCTION__ = "fault_report" #5 0x00002af6b31180b4 in sig_fault (sig=11) at ../lib/util/fault.c:88 No locals. #6 No symbol table info available. #7 0x00002af6cabef930 in replmd_check_urgent_objectclass ( objectclass_el=0x0, situation=REPL_URGENT_ON_UPDATE) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:205 i = 2 j = 0 #8 0x00002af6cabf29b6 in replmd_update_rpmd (module=0x2af6b17f2c20, schema=0x2af6d05e5570, req=0x2af6d05e8ad0, rename_attrs=0x0, msg=0x2af6d11ef100, seq_num=0x2af6d0c315b8, t=1387895162, is_urgent=0x7fff67c778bf, rodc=0x7fff67c778be) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:1432 omd_value = 0x7fff67c77810 ndr_err = 3508465920 omd = {version = 1741125552, reserved = 32767, ctr = {ctr1 = { count = 3008684740, reserved = 10998, array = 0x7fff67c777b0}}} i = 10998 now = 130323687620000000 our_invocation_id = 0x2af6d1796390 ret = 0 attrs = 0x7fff67c77750 attrs1 = {0x2af6cabff775 "replPropertyMetaData", 0x2af6cabffc8b "*", 0x0} attrs2 = {0x2af6cabff76a "uSNChanged", 0x2af6cabffa98 "objectClass", 0x2af6cabffc8d "instanceType", 0x0} res = 0x2af6d10b0eb0 ldb = 0x2af6b17f2470 objectclass_el = 0x0 situation = REPL_URGENT_ON_UPDATE rmd_is_provided = false __FUNCTION__ = "replmd_update_rpmd" #9 0x00002af6cabf5a06 in replmd_modify (module=0x2af6b17f2c20, req=0x2af6d05e8ad0) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:2455 msds_intid_struct = 0x2af6d05e8ad0 ldb = 0x2af6b17f2470 ac = 0x2af6d0c31580 down_req = 0x2af6d0e6a100 msg = 0x2af6d11ef100 t = 1387895162 ret = 1741125936 is_urgent = false rodc = false functional_level = 3 guid_blob = 0x0 sd_propagation_control = 0x0 #10 0x00002af6bf69f94d in dsdb_module_modify (module=0x2af6b17f2c20, message=0x2af6d1183fe0, dsdb_flags=4194304, parent=0x2af6ce6ea980) at ../source4/dsdb/samdb/ldb_modules/util.c:460 ops = 0x2af6cae06b40 mod_req = 0x2af6d05e8ad0 ret = 0 ldb = 0x2af6b17f2470 tmp_ctx = 0x2af6d0ed62f0 res = 0x2af6d0e6a100 __FUNCTION__ = "dsdb_module_modify" #11 0x00002af6cabf7ebc in replmd_delete_internals (module=0x2af6b17f2c20, req=0x2af6ce6ea980, re_delete=true) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:3309 ret = 0 retb = true disallow_move_on_delete = false old_dn = 0x2af6d6a2a010 new_dn = 0x2af6d0794a90 rdn_name = 0x2af6d0885c10 "CN" rdn_value = 0x2af6d10d7368 new_rdn_value = 0x2af6d0c45a00 guid = {time_low = 48, time_mid = 0, time_hi_and_version = 0, clock_seq = "\200\251", node = "n\316\366*\000"} ldb = 0x2af6b17f2470 schema = 0x2af6d05e5570 msg = 0x2af6d1183fe0 old_msg = 0x2af6d1902800 el = 0x2af6d0874900 tmp_ctx = 0x2af6d0b77560 res = 0x2af6d0d57980 parent_res = 0x30 preserved_attrs = {0x2af6cac00fe1 "nTSecurityDescriptor", 0x2af6cac055c3 "attributeID", 0x2af6cac055cf "attributeSyntax", 0x2af6cac055df "dNReferenceUpdate", 0x2af6cac055f1 "dNSHostName", 0x2af6cac055fd "flatName", 0x2af6cac05606 "governsID", 0x2af6cac05610 "groupType", 0x2af6cabffc8d "instanceType", 0x2af6cac0561a "lDAPDisplayName", 0x2af6cac0562a "legacyExchangeDN", 0x2af6cabfe94d "isDeleted", 0x2af6cabfe957 "isRecycled", 0x2af6cac020f8 "lastKnownParent", 0x2af6cac021e8 "msDS-LastKnownRDN", 0x2af6cac0563b "mS-DS-CreatorSID", 0x2af6cac0564c "mSMQOwnerID", 0x2af6cac05658 "nCName", 0x2af6cabffa98 "objectClass", 0x2af6cac0565f "distinguishedName", 0x2af6cabff5b5 "objectGUID", 0x2af6cac05671 "objectSid", 0x2af6cac0567b "oMSyntax", 0x2af6cac05684 "proxiedObjectName", 0x2af6cac014d8 "name", 0x2af6cabff775 "replPropertyMetaData", 0x2af6cac05696 "sAMAccountName", 0x2af6cac056a5 "securityIdentifier", 0x2af6cac056b8 "sIDHistory", 0x2af6cac056c3 "subClassOf", 0x2af6cac01ba8 "systemFlags", 0x2af6cac056ce "trustPartner", 0x2af6cac056db "trustDirection", 0x2af6cac056ea "trustType", 0x2af6cac056f4 "trustAttributes", 0x2af6cabfe9b8 "userAccountControl", 0x2af6cabff76a "uSNChanged", 0x2af6cabff75f "uSNCreated", 0x2af6cabff747 "whenCreated", 0x2af6cabff753 "whenChanged", 0x0} i = 12 el_count = 1 deletion_state = OBJECT_TOMBSTONE next_deletion_state = OBJECT_TOMBSTONE __FUNCTION__ = "replmd_delete_internals" #12 0x00002af6cabfbbe3 in replmd_replicated_apply_isDeleted ( ar=0x2af6d74c0b40) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:4718 del_req = 0x2af6ce6ea980 res = 0x2af6d0cdebf0 tmp_ctx = 0x2af6d0949230 deleted_objects_dn = 0x2af6d1a49f00 msg = 0x2af6d0a39620 ret = 0 #13 0x00002af6cabf0766 in replmd_op_callback (req=0x2af6d05a21e0, ares=0x2af6d0d715c0) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:526 ret = 10998 ac = 0x2af6d74c0b40 replmd_private = 0x2af6b188c7c0 modified_partition = 0x2af6d141b670 partition_ctrl = 0x2af6d1905f40 partition = 0x2af6ce6bdbe0 controls = 0x0 __FUNCTION__ = "replmd_op_callback" #14 0x00002af6b1df7ca2 in ldb_module_done (req=0x2af6d05a21e0, ctrls=0x2af6d1629aa0, response=0x0, error=0) at ../lib/ldb/common/ldb_modules.c:832 ares = 0x2af6d0d715c0 #15 0x00002af6cabf896b in replmd_op_possible_conflict_callback ( req=0x2af6d05a21e0, ares=0x2af6b1883eb0, callback=0x2af6cabf0334 ) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:3606 conflict_dn = 0x2af6cac03470 ar = 0x2af6d74c0b40 res = 0x2af6b354f89b attrs = {0x2af6cabff775 "replPropertyMetaData", 0x2af6cabff5b5 "objectGUID", 0x0} ret = -682882240 omd_value = 0x7fff67c77e20 omd = {version = 1741127104, reserved = 32767, ctr = {ctr1 = { count = 0, reserved = 0, array = 0x28}}} rmd = 0x2af6d74c0ae0 ndr_err = 10998 rename_incoming_record = false rodc = false rmd_name = 0x7fff67c77e10 omd_name = 0x2af6d74c0b40 msg = 0x2af6b1883e50 __FUNCTION__ = "replmd_op_possible_conflict_callback" #16 0x00002af6cabf93fb in replmd_op_add_callback (req=0x2af6d05a21e0, ares=0x2af6b1883eb0) at ../source4/dsdb/samdb/ldb_modules/repl_meta_data.c:3802 ar = 0x2af6d74c0b40 #17 0x00002af6b1df7ca2 in ldb_module_done (req=0x2af6d05a21e0, ctrls=0x2af6d1629aa0, response=0x0, error=0) at ../lib/ldb/common/ldb_modules.c:832 ares = 0x2af6b1883eb0 #18 0x00002af6ca3c8b6a in partition_req_callback (req=0x2af6d087a1e0, ares=0x2af6d05a1fa0) at ../source4/dsdb/samdb/ldb_modules/partition.c:213 ac = 0x2af6d0949370 module = 0x2af6cd27bf12 nreq = 0x2af6d05b67b0 ret = 0 partition_ctrl = 0x2af6d0d71740 #19 0x00002af6cd2752ab in ltdb_request_done (ctx=0x2af6d1cd7ed0, error=0) at ../lib/ldb/ldb_tdb/ldb_tdb.c:1280 ldb = 0x2af6b17f2470 req = 0x2af6d087a1e0 ares = 0x2af6d05a1fa0 #20 0x00002af6cd275597 in ltdb_callback (ev=0x2af6b17ef8c0, te=0x2af6d17f75d0, t=..., private_data=0x2af6d1cd7ed0) at ../lib/ldb/ldb_tdb/ldb_tdb.c:1390 ctx = 0x2af6d1cd7ed0 ret = 0 #21 0x00002af6b3343259 in tevent_common_loop_timer_delay (ev=0x2af6b17ef8c0) at ../lib/tevent/tevent_timed.c:341 current_time = {tv_sec = 0, tv_usec = 0} te = 0x2af6d17f75d0 #22 0x00002af6b334558a in epoll_event_loop_once (ev=0x2af6b17ef8c0, location=0x2af6b1e1eef8 "../lib/ldb/common/ldb.c:621") at ../lib/tevent/tevent_epoll.c:912 epoll_ev = 0x2af6b17efb00 tval = {tv_sec = 47239056876603, tv_usec = 47239028210096} panic_triggered = false #23 0x00002af6b3342363 in std_event_loop_once (ev=0x2af6b17ef8c0, location=0x2af6b1e1eef8 "../lib/ldb/common/ldb.c:621") at ../lib/tevent/tevent_standard.c:112 glue_ptr = 0x2af6b17ef9b0 glue = 0x2af6b17ef9b0 ret = 10998 #24 0x00002af6b333c799 in _tevent_loop_once (ev=0x2af6b17ef8c0, location=0x2af6b1e1eef8 "../lib/ldb/common/ldb.c:621") at ../lib/tevent/tevent.c:530 ret = 0 nesting_stack_ptr = 0x0 #25 0x00002af6b1e154c4 in ldb_wait (handle=0x2af6d67624c0, type=LDB_WAIT_ALL) at ../lib/ldb/common/ldb.c:621 ev = 0x2af6b17ef8c0 ret = 0 #26 0x00002af6b1e1786b in ldb_extended (ldb=0x2af6b17f2470, oid=0x2af6b4c4f9ce "1.3.6.1.4.1.7165.4.4.1", data=0x2af6d0e2bc60, _res=0x7fff67c78240) at ../lib/ldb/common/ldb.c:1506 req = 0x2af6d0c45a00 ret = 0 res = 0x2af6d69238f0 #27 0x00002af6b4c4a0d6 in dsdb_replicated_objects_commit (ldb=0x2af6b17f2470, working_schema=0x0, objects=0x2af6d0e2bc60, notify_uSN=0x2af6d14a65f0) at ../source4/dsdb/repl/replicated_objects.c:773 werr = {w = 0} ext_res = 0x0 cur_schema = 0x0 new_schema = 0x0 ret = 0 seq_num1 = 5554 seq_num2 = 47239626746464 used_global_schema = false tmp_ctx = 0x2af6d03c5860 __FUNCTION__ = "dsdb_replicated_objects_commit" #28 0x00002af6c1c6babb in dreplsrv_op_pull_source_apply_changes_trigger ( req=0x2af6d17daed0, r=0x2af6d17db0d0, ctr_level=6, ctr1=0x0, ctr6=0x2af6d1b02bb0) at ../source4/dsdb/repl/drepl_out_helpers.c:717 state = 0x2af6d17db050 rf1 = {blobsize = 274, consecutive_sync_failures = 0, last_success = 130323684670000000, last_attempt = 130323687610000000, result_last_attempt = {w = 0}, other_info = 0x2af6d0949910, other_info_length = 66, replica_flags = 112, schedule = '\021' , reserved = 0, highwatermark = {tmp_highest_usn = 12398, reserved_usn = 0, highest_usn = 12398}, source_dsa_obj_guid = { time_low = 984092159, time_mid = 850, time_hi_and_version = 18870, clock_seq = "\251X", node = "UF\324\223\205\241"}, source_dsa_invocation_id = { time_low = 1460694408, time_mid = 52035, time_hi_and_version = 18738, clock_seq = "\204}", node = "\264\365\276\372\256\303"}, transport_guid = { time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\000", node = "\000\000\000\000\000"}} service = 0x2af6d0ff6b00 partition = 0x2af6d0b6f220 drsuapi = 0x2af6d1c8d480 schema = 0x2af6d05e5570 working_schema = 0x0 mapping_ctr = 0x2af6d1b02c10 object_count = 50 first_object = 0x2af6d0571800 linked_attributes_count = 0 linked_attributes = 0x2af6d5212140 uptodateness_vector = 0x2af6d1a741c0 objects = 0x2af6d0e2bc60 more_data = false status = {w = 0} nt_status = {v = 3006553120} dsdb_repl_flags = 0 __FUNCTION__ = "dreplsrv_op_pull_source_apply_changes_trigger" #29 0x00002af6c1c6b3e7 in dreplsrv_op_pull_source_get_changes_done ( subreq=0x0) at ../source4/dsdb/repl/drepl_out_helpers.c:599 req = 0x2af6d17daed0 state = 0x2af6d17db050 status = {v = 0} r = 0x2af6d17db0d0 ctr_level = 6 ctr1 = 0x0 ctr6 = 0x2af6d1b02bb0 extended_ret = DRSUAPI_EXOP_ERR_NONE #30 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d1a73f70, location=0x2af6c1c7d5f8 "default/librpc/gen_ndr/ndr_drsuapi_c.c:712") at ../lib/tevent/tevent_req.c:102 No locals. #31 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d1a73f70, state=TEVENT_REQ_DONE, location=0x2af6c1c7d5f8 "default/librpc/gen_ndr/ndr_drsuapi_c.c:712") at ../lib/tevent/tevent_req.c:117 No locals. #32 0x00002af6b333e374 in _tevent_req_done (req=0x2af6d1a73f70, location=0x2af6c1c7d5f8 "default/librpc/gen_ndr/ndr_drsuapi_c.c:712") at ../lib/tevent/tevent_req.c:123 No locals. #33 0x00002af6c1c708df in dcerpc_drsuapi_DsGetNCChanges_r_done ( subreq=0x2af6d122f4c0) at default/librpc/gen_ndr/ndr_drsuapi_c.c:712 req = 0x2af6d1a73f70 status = {v = 0} #34 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d122f4c0, location=0x2af6b575b688 "../librpc/rpc/binding_handle.c:517") at ../lib/tevent/tevent_req.c:102 No locals. #35 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d122f4c0, state=TEVENT_REQ_DONE, location=0x2af6b575b688 "../librpc/rpc/binding_handle.c:517") at ../lib/tevent/tevent_req.c:117 No locals. #36 0x00002af6b333e374 in _tevent_req_done (req=0x2af6d122f4c0, location=0x2af6b575b688 "../librpc/rpc/binding_handle.c:517") at ../lib/tevent/tevent_req.c:123 No locals. #37 0x00002af6b5757ede in dcerpc_binding_handle_call_done (subreq=0x0) at ../librpc/rpc/binding_handle.c:517 req = 0x2af6d122f4c0 state = 0x2af6d122f640 h = 0x2af6d0959d10 error = {v = 0} out_flags = 0 ndr_err = NDR_ERR_SUCCESS #38 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d522f7a0, location=0x2af6b575b1d0 "../librpc/rpc/binding_handle.c:188") at ../lib/tevent/tevent_req.c:102 No locals. #39 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d522f7a0, state=TEVENT_REQ_DONE, location=0x2af6b575b1d0 "../librpc/rpc/binding_handle.c:188") at ../lib/tevent/tevent_req.c:117 No locals. #40 0x00002af6b333e374 in _tevent_req_done (req=0x2af6d522f7a0, location=0x2af6b575b1d0 "../librpc/rpc/binding_handle.c:188") at ../lib/tevent/tevent_req.c:123 No locals. #41 0x00002af6b5757398 in dcerpc_binding_handle_raw_call_done (subreq=0x0) at ../librpc/rpc/binding_handle.c:188 req = 0x2af6d522f7a0 state = 0x2af6d522f920 error = {v = 0} #42 0x00002af6b333e2f8 in _tevent_req_notify_callback (req=0x2af6d0712430, location=0x2af6b44b8810 "../source4/librpc/rpc/dcerpc.c:322") at ../lib/tevent/tevent_req.c:102 No locals. #43 0x00002af6b333e34d in tevent_req_finish (req=0x2af6d0712430, state=TEVENT_REQ_DONE, location=0x2af6b44b8810 "../source4/librpc/rpc/dcerpc.c:322") at ../lib/tevent/tevent_req.c:117 No locals. #44 0x00002af6b333e472 in tevent_req_trigger (ev=0x2af6b17ef8c0, im=0x2af6d0712500, private_data=0x2af6d0712430) at ../lib/tevent/tevent_req.c:174 req = 0x2af6d0712430 #45 0x00002af6b333d6d4 in tevent_common_loop_immediate (ev=0x2af6b17ef8c0) at ../lib/tevent/tevent_immediate.c:135 im = 0x2af6d0712500 handler = 0x2af6b333e423 private_data = 0x2af6d0712430 #46 0x00002af6b3345570 in epoll_event_loop_once (ev=0x2af6b17ef8c0, location=0x2af6b15a7b9f "../source4/smbd/server.c:503") at ../lib/tevent/tevent_epoll.c:907 epoll_ev = 0x2af6b17efb00 tval = {tv_sec = 47239056876603, tv_usec = 47239028210096} panic_triggered = false #47 0x00002af6b3342363 in std_event_loop_once (ev=0x2af6b17ef8c0, location=0x2af6b15a7b9f "../source4/smbd/server.c:503") at ../lib/tevent/tevent_standard.c:112 glue_ptr = 0x2af6b17ef9b0 glue = 0x2af6b17ef9b0 ret = 10998 #48 0x00002af6b333c799 in _tevent_loop_once (ev=0x2af6b17ef8c0, location=0x2af6b15a7b9f "../source4/smbd/server.c:503") at ../lib/tevent/tevent.c:530 ret = 0 nesting_stack_ptr = 0x0 #49 0x00002af6b333ca11 in tevent_common_loop_wait (ev=0x2af6b17ef8c0, location=0x2af6b15a7b9f "../source4/smbd/server.c:503") at ../lib/tevent/tevent.c:634 ret = 0 #50 0x00002af6b3342405 in std_event_loop_wait (ev=0x2af6b17ef8c0, location=0x2af6b15a7b9f "../source4/smbd/server.c:503") at ../lib/tevent/tevent_standard.c:138 glue_ptr = 0x2af6b17ef9b0 glue = 0x2af6b17ef9b0 ret = 10998 #51 0x00002af6b333cadc in _tevent_loop_wait (ev=0x2af6b17ef8c0, location=0x2af6b15a7b9f "../source4/smbd/server.c:503") at ../lib/tevent/tevent.c:653 No locals. #52 0x00002af6b15a37bc in binary_smbd_main ( binary_name=0x2af6b15a737b "samba", argc=6, argv=0x7fff67c78de8) at ../source4/smbd/server.c:503 opt_daemon = false opt_interactive = true opt = -1 pc = 0x2af6b17d5040 static_init = {0x2af6b2ac7d8c , 0x2af6b2aca9e7 , 0} shared_init = 0x2af6b18143b0 event_ctx = 0x2af6b17ef8c0 stdin_event_flags = 1 status = {v = 0} model = 0x2af6b17d5b90 "single" max_runtime = 7500 Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Mon Jan 6 01:16:13 CET 2014 on sn-devel-104 (cherry picked from commit 056008df62cb66090b3e30cb09c0edacfbdb5720) --- source4/selftest/tests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index c3a33c7..9567a8e 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -309,8 +309,6 @@ plantestsuite("samba4.blackbox.locktest(dc)", "dc", [os.path.join(samba4srcdir, plantestsuite("samba4.blackbox.masktest", "dc", [os.path.join(samba4srcdir, "torture/tests/test_masktest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', '$PREFIX']) plantestsuite("samba4.blackbox.gentest(dc)", "dc", [os.path.join(samba4srcdir, "torture/tests/test_gentest.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$DOMAIN', "$PREFIX"]) plantestsuite("samba4.blackbox.rfc2307_mapping(dc:local)", "dc:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_rfc2307_mapping.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "$SERVER", "$UID_RFC2307TEST", "$GID_RFC2307TEST", configuration]) -for env in ["dc", "s4member", "rodc", "promoted_dc"]: - plantestsuite("samba4.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', "CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX', "aes256-cts-hmac-sha1-96", '$SELFTEST_PREFIX/chgdcpass', smbclient4]) plantestsuite("samba4.blackbox.samba_upgradedns(chgdcpass:local)", "chgdcpass:local", [os.path.join(bbdir, "test_samba_upgradedns.sh"), '$SERVER', '$REALM', '$PREFIX', '$SELFTEST_PREFIX/chgdcpass']) plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "dc", [valgrindify(smbtorture4), "$LISTOPT", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) @@ -502,6 +500,10 @@ for env in ['vampire_dc', 'promoted_dc']: extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD']) plantestsuite("samba4.blackbox.samba_tool_demote(%s)" % env, env, [os.path.join(samba4srcdir, "utils/tests/test_demote.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$DOMAIN', '$DC_SERVER', '$PREFIX/%s' % env, smbclient4]) + +for env in ["dc", "s4member", "rodc", "promoted_dc"]: + plantestsuite("samba4.blackbox.wbinfo(%s:local)" % env, "%s:local" % env, [os.path.join(samba4srcdir, "../nsswitch/tests/test_wbinfo.sh"), '$DOMAIN', '$DC_USERNAME', '$DC_PASSWORD', env]) + # TODO: Verifying the databases really should be a part of the # environment teardown. # check the databases are all OK. PLEASE LEAVE THIS AS THE LAST TEST -- 1.9.3 From 3e44e7485dbfea37cb84034c4d13c96059bd9687 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 08:35:27 +0100 Subject: [PATCH 144/249] s4:librpc: always try to negotiate DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN If the gensec backend supports it there's no reason not sign the header. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 7db1dc13b0149441a2beebca65b75f6e11af13a3) --- librpc/rpc/binding.c | 1 - librpc/rpc/rpc_common.h | 5 ++++- source4/librpc/rpc/dcerpc.c | 12 ++---------- source4/librpc/rpc/dcerpc_auth.c | 14 ++++++++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/librpc/rpc/binding.c b/librpc/rpc/binding.c index 49651e8..52122cf 100644 --- a/librpc/rpc/binding.c +++ b/librpc/rpc/binding.c @@ -88,7 +88,6 @@ static const struct { {"padcheck", DCERPC_DEBUG_PAD_CHECK}, {"bigendian", DCERPC_PUSH_BIGENDIAN}, {"smb2", DCERPC_SMB2}, - {"hdrsign", DCERPC_HEADER_SIGNING}, {"ndr64", DCERPC_NDR64}, {"localaddress", DCERPC_LOCALADDRESS} }; diff --git a/librpc/rpc/rpc_common.h b/librpc/rpc/rpc_common.h index 978229e..93d3bb4 100644 --- a/librpc/rpc/rpc_common.h +++ b/librpc/rpc/rpc_common.h @@ -98,7 +98,7 @@ struct dcerpc_binding { /* this triggers the DCERPC_PFC_FLAG_CONC_MPX flag in the bind request */ #define DCERPC_CONCURRENT_MULTIPLEX (1<<19) -/* this triggers the DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag in the bind request */ +/* this indicates DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag was negotiated */ #define DCERPC_HEADER_SIGNING (1<<20) /* use NDR64 transport */ @@ -113,6 +113,9 @@ struct dcerpc_binding { /* use aes schannel with hmac-sh256 session key */ #define DCERPC_SCHANNEL_AES (1<<24) +/* this triggers the DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN flag in the bind request */ +#define DCERPC_PROPOSE_HEADER_SIGNING (1<<25) + /* The following definitions come from ../librpc/rpc/dcerpc_error.c */ const char *dcerpc_errstr(TALLOC_CTX *mem_ctx, uint32_t fault_code); diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 56b821e..2f6c8dd 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -1162,7 +1162,7 @@ struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx, pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; } - if (p->binding->flags & DCERPC_HEADER_SIGNING) { + if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) { pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; } @@ -1304,7 +1304,7 @@ static void dcerpc_bind_recv_handler(struct rpc_request *subreq, conn->flags |= DCERPC_CONCURRENT_MULTIPLEX; } - if ((state->p->binding->flags & DCERPC_HEADER_SIGNING) && + if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) && (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) { conn->flags |= DCERPC_HEADER_SIGNING; } @@ -1352,10 +1352,6 @@ NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; } - if (p->binding->flags & DCERPC_HEADER_SIGNING) { - pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; - } - /* construct the NDR form of the packet */ status = ncacn_push_auth(&blob, mem_ctx, &pkt, @@ -2046,10 +2042,6 @@ struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx, pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX; } - if (p->binding->flags & DCERPC_HEADER_SIGNING) { - pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; - } - pkt.u.alter.max_xmit_frag = 5840; pkt.u.alter.max_recv_frag = 5840; pkt.u.alter.assoc_group_id = p->binding->assoc_group_id; diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index d5e5620..9a5d04d 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -173,10 +173,6 @@ static void bind_auth_next_step(struct composite_context *c) if (!composite_is_ok(c)) return; - if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) { - gensec_want_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER); - } - if (state->credentials.length == 0) { composite_done(c); return; @@ -234,6 +230,12 @@ static void bind_auth_recv_bindreply(struct tevent_req *subreq) TALLOC_FREE(subreq); if (!composite_is_ok(c)) return; + if (state->pipe->conn->flags & DCERPC_HEADER_SIGNING) { + struct dcecli_security *sec = &state->pipe->conn->security_state; + + gensec_want_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER); + } + if (!state->more_processing) { /* The first gensec_update has not requested a second run, so * we're done here. */ @@ -395,6 +397,10 @@ struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx, sec->auth_info->credentials = state->credentials; + if (gensec_have_feature(sec->generic_state, GENSEC_FEATURE_SIGN_PKT_HEADER)) { + state->pipe->conn->flags |= DCERPC_PROPOSE_HEADER_SIGNING; + } + /* The first request always is a dcerpc_bind. The subsequent ones * depend on gensec results */ subreq = dcerpc_bind_send(state, p->conn->event_ctx, p, -- 1.9.3 From 6bdc135a63647fbbc31c7b2e673396231541641d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 08:39:12 +0100 Subject: [PATCH 145/249] s4:rpc_server: support DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN by default If the gensec backend supports it there's no reason to disable it. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 661fe3cf890b91f8750872b0f5a09da536f76ae2) --- source4/rpc_server/dcerpc_server.c | 6 ------ source4/rpc_server/dcesrv_auth.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index ad53685..3b35703 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -610,12 +610,6 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) call->conn->cli_max_recv_frag = MIN(0x2000, call->pkt.u.bind.max_recv_frag); } - if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) && - lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", false)) { - call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING; - extra_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; - } - /* handle any authentication that is being requested */ if (!dcesrv_auth_bind(call)) { talloc_free(call->context); diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c index c891cc6..152715b 100644 --- a/source4/rpc_server/dcesrv_auth.c +++ b/source4/rpc_server/dcesrv_auth.c @@ -92,10 +92,6 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call) return false; } - if (call->conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) { - gensec_want_feature(auth->gensec_security, GENSEC_FEATURE_SIGN_PKT_HEADER); - } - return true; } @@ -107,11 +103,20 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe { struct dcesrv_connection *dce_conn = call->conn; NTSTATUS status; + bool want_header_signing = false; if (!call->conn->auth_state.gensec_security) { return NT_STATUS_OK; } + if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) { + want_header_signing = true; + } + + if (!lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", true)) { + want_header_signing = false; + } + status = gensec_update(dce_conn->auth_state.gensec_security, call, call->event_ctx, dce_conn->auth_state.auth_info->credentials, @@ -126,9 +131,17 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe return status; } - if (dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) { + if (!gensec_have_feature(dce_conn->auth_state.gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER)) + { + want_header_signing = false; + } + + if (want_header_signing) { gensec_want_feature(dce_conn->auth_state.gensec_security, GENSEC_FEATURE_SIGN_PKT_HEADER); + call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING; + pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; } /* Now that we are authenticated, go back to the generic session key... */ @@ -137,6 +150,20 @@ NTSTATUS dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct ncacn_packe } else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { dce_conn->auth_state.auth_info->auth_pad_length = 0; dce_conn->auth_state.auth_info->auth_reserved = 0; + + if (!gensec_have_feature(dce_conn->auth_state.gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER)) + { + want_header_signing = false; + } + + if (want_header_signing) { + gensec_want_feature(dce_conn->auth_state.gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER); + call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING; + pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + return NT_STATUS_OK; } else { DEBUG(4, ("GENSEC mech rejected the incoming authentication at bind_ack: %s\n", -- 1.9.3 From 868676160bb3bcfb4145a5c4b47fbb513c0bfac4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 31 Dec 2013 09:53:55 +0100 Subject: [PATCH 146/249] auth/ntlmssp: GENSEC_FEATURE_SIGN_PKT_HEADER is always supported Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 64fc015a85f9b5ed74f3dabe05dbdff185093278) --- auth/ntlmssp/gensec_ntlmssp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/auth/ntlmssp/gensec_ntlmssp.c b/auth/ntlmssp/gensec_ntlmssp.c index 654c0e3..5672589 100644 --- a/auth/ntlmssp/gensec_ntlmssp.c +++ b/auth/ntlmssp/gensec_ntlmssp.c @@ -102,6 +102,10 @@ bool gensec_ntlmssp_have_feature(struct gensec_security *gensec_security, return true; } } + if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) { + return true; + } + return false; } -- 1.9.3 From e486316c74d3781413e66e451b51737fc194bdc2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 31 Dec 2013 09:54:54 +0100 Subject: [PATCH 147/249] s4:auth/gensec_gssapi: handle GENSEC_FEATURE_SIGN_PKT_HEADER in have_feature() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 14f6c41754960d73f46aca1bade2266b7e934d03) --- source4/auth/gensec/gensec_gssapi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 63a53bf..ffdefcf 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -1275,6 +1275,18 @@ static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security, if (feature & GENSEC_FEATURE_ASYNC_REPLIES) { return true; } + if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) { + if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { + /* TODO: implement this using gss_wrap_iov() */ + return false; + } + + if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { + return true; + } + + return false; + } return false; } -- 1.9.3 From fa8d0a7726240f8fc6648424d9724bcd65949bfd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 15:30:46 +0100 Subject: [PATCH 148/249] s4:gensec_gssapi: make sure gensec_gssapi_[un]seal_packet() rejects header signing If header signing is requested we should error out instead of silently ignoring it, our peer would hopefully reject it, but we should also do that. TODO: we should implement header signing using gss_wrap_iov(). Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 54b5b3067f5b7a0eb6dd9f1326c903f9fe4a5592) --- source4/auth/gensec/gensec_gssapi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index ffdefcf..b8f007d 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -1028,6 +1028,12 @@ static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_securit int conf_state; ssize_t sig_length; + if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { + DEBUG(1, ("gensec_gssapi_seal_packet: " + "GENSEC_FEATURE_SIGN_PKT_HEADER not supported\n")); + return NT_STATUS_ACCESS_DENIED; + } + input_token.length = length; input_token.value = data; @@ -1082,6 +1088,12 @@ static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_secur dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig->data, sig->length); + if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { + DEBUG(1, ("gensec_gssapi_unseal_packet: " + "GENSEC_FEATURE_SIGN_PKT_HEADER not supported\n")); + return NT_STATUS_ACCESS_DENIED; + } + in = data_blob_talloc(gensec_security, NULL, sig->length + length); memcpy(in.data, sig->data, sig->length); -- 1.9.3 From 2b1f62e3d99047e2981dcdd32c6820346917dc04 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 31 Dec 2013 09:42:36 +0100 Subject: [PATCH 149/249] auth/gensec: move libcli/auth/schannel_sign.c into schannel.c Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 616cd009955b1722e6749019e2c1cac8bbb94e52) --- auth/gensec/schannel.c | 380 ++++++++++++++++++++++++++++++++++++++++ libcli/auth/schannel_proto.h | 14 -- libcli/auth/schannel_sign.c | 404 ------------------------------------------- libcli/auth/wscript_build | 2 +- 4 files changed, 381 insertions(+), 419 deletions(-) delete mode 100644 libcli/auth/schannel_sign.c diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c index eb2e100..c60ab4f 100644 --- a/auth/gensec/schannel.c +++ b/auth/gensec/schannel.c @@ -31,6 +31,386 @@ #include "librpc/gen_ndr/dcerpc.h" #include "param/param.h" #include "auth/gensec/gensec_toplevel_proto.h" +#include "lib/crypto/crypto.h" + +struct schannel_state { + uint64_t seq_num; + bool initiator; + struct netlogon_creds_CredentialState *creds; +}; + +#define SETUP_SEQNUM(state, buf, initiator) do { \ + uint8_t *_buf = buf; \ + uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ + uint32_t _seq_num_high = (state)->seq_num >> 32; \ + if (initiator) { \ + _seq_num_high |= 0x80000000; \ + } \ + RSIVAL(_buf, 0, _seq_num_low); \ + RSIVAL(_buf, 4, _seq_num_high); \ +} while(0) + +static struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds, + bool initiator) +{ + struct schannel_state *state; + + state = talloc(mem_ctx, struct schannel_state); + if (state == NULL) { + return NULL; + } + + state->initiator = initiator; + state->seq_num = 0; + state->creds = netlogon_creds_copy(state, creds); + if (state->creds == NULL) { + talloc_free(state); + return NULL; + } + + return state; +} + +static void netsec_offset_and_sizes(struct schannel_state *state, + bool do_seal, + uint32_t *_min_sig_size, + uint32_t *_used_sig_size, + uint32_t *_checksum_length, + uint32_t *_confounder_ofs) +{ + uint32_t min_sig_size; + uint32_t used_sig_size; + uint32_t checksum_length; + uint32_t confounder_ofs; + + if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + min_sig_size = 48; + used_sig_size = 56; + /* + * Note: windows has a bug here and uses the old values... + * + * checksum_length = 32; + * confounder_ofs = 48; + */ + checksum_length = 8; + confounder_ofs = 24; + } else { + min_sig_size = 24; + used_sig_size = 32; + checksum_length = 8; + confounder_ofs = 24; + } + + if (do_seal) { + min_sig_size += 8; + } + + if (_min_sig_size) { + *_min_sig_size = min_sig_size; + } + + if (_used_sig_size) { + *_used_sig_size = used_sig_size; + } + + if (_checksum_length) { + *_checksum_length = checksum_length; + } + + if (_confounder_ofs) { + *_confounder_ofs = confounder_ofs; + } +} + +/******************************************************************* + Encode or Decode the sequence number (which is symmetric) + ********************************************************************/ +static void netsec_do_seq_num(struct schannel_state *state, + const uint8_t *checksum, + uint32_t checksum_length, + uint8_t seq_num[8]) +{ + if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + AES_KEY key; + uint8_t iv[AES_BLOCK_SIZE]; + + AES_set_encrypt_key(state->creds->session_key, 128, &key); + ZERO_STRUCT(iv); + memcpy(iv+0, checksum, 8); + memcpy(iv+8, checksum, 8); + + aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT); + } else { + static const uint8_t zeros[4]; + uint8_t sequence_key[16]; + uint8_t digest1[16]; + + hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); + hmac_md5(digest1, checksum, checksum_length, sequence_key); + arcfour_crypt(seq_num, sequence_key, 8); + } + + state->seq_num++; +} + +static void netsec_do_seal(struct schannel_state *state, + const uint8_t seq_num[8], + uint8_t confounder[8], + uint8_t *data, uint32_t length, + bool forward) +{ + if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + AES_KEY key; + uint8_t iv[AES_BLOCK_SIZE]; + uint8_t sess_kf0[16]; + int i; + + for (i = 0; i < 16; i++) { + sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; + } + + AES_set_encrypt_key(sess_kf0, 128, &key); + ZERO_STRUCT(iv); + memcpy(iv+0, seq_num, 8); + memcpy(iv+8, seq_num, 8); + + if (forward) { + aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT); + aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT); + } else { + aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT); + aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT); + } + } else { + uint8_t sealing_key[16]; + static const uint8_t zeros[4]; + uint8_t digest2[16]; + uint8_t sess_kf0[16]; + int i; + + for (i = 0; i < 16; i++) { + sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; + } + + hmac_md5(sess_kf0, zeros, 4, digest2); + hmac_md5(digest2, seq_num, 8, sealing_key); + + arcfour_crypt(confounder, sealing_key, 8); + arcfour_crypt(data, sealing_key, length); + } +} + +/******************************************************************* + Create a digest over the entire packet (including the data), and + MD5 it with the session key. + ********************************************************************/ +static void netsec_do_sign(struct schannel_state *state, + const uint8_t *confounder, + const uint8_t *data, size_t length, + uint8_t header[8], + uint8_t *checksum) +{ + if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + struct HMACSHA256Context ctx; + + hmac_sha256_init(state->creds->session_key, + sizeof(state->creds->session_key), + &ctx); + + if (confounder) { + SSVAL(header, 0, NL_SIGN_HMAC_SHA256); + SSVAL(header, 2, NL_SEAL_AES128); + SSVAL(header, 4, 0xFFFF); + SSVAL(header, 6, 0x0000); + + hmac_sha256_update(header, 8, &ctx); + hmac_sha256_update(confounder, 8, &ctx); + } else { + SSVAL(header, 0, NL_SIGN_HMAC_SHA256); + SSVAL(header, 2, NL_SEAL_NONE); + SSVAL(header, 4, 0xFFFF); + SSVAL(header, 6, 0x0000); + + hmac_sha256_update(header, 8, &ctx); + } + + hmac_sha256_update(data, length, &ctx); + + hmac_sha256_final(checksum, &ctx); + } else { + uint8_t packet_digest[16]; + static const uint8_t zeros[4]; + MD5_CTX ctx; + + MD5Init(&ctx); + MD5Update(&ctx, zeros, 4); + if (confounder) { + SSVAL(header, 0, NL_SIGN_HMAC_MD5); + SSVAL(header, 2, NL_SEAL_RC4); + SSVAL(header, 4, 0xFFFF); + SSVAL(header, 6, 0x0000); + + MD5Update(&ctx, header, 8); + MD5Update(&ctx, confounder, 8); + } else { + SSVAL(header, 0, NL_SIGN_HMAC_MD5); + SSVAL(header, 2, NL_SEAL_NONE); + SSVAL(header, 4, 0xFFFF); + SSVAL(header, 6, 0x0000); + + MD5Update(&ctx, header, 8); + } + MD5Update(&ctx, data, length); + MD5Final(packet_digest, &ctx); + + hmac_md5(state->creds->session_key, + packet_digest, sizeof(packet_digest), + checksum); + } +} + +static NTSTATUS netsec_incoming_packet(struct schannel_state *state, + bool do_unseal, + uint8_t *data, size_t length, + const DATA_BLOB *sig) +{ + uint32_t min_sig_size = 0; + uint8_t header[8]; + uint8_t checksum[32]; + uint32_t checksum_length = sizeof(checksum_length); + uint8_t _confounder[8]; + uint8_t *confounder = NULL; + uint32_t confounder_ofs = 0; + uint8_t seq_num[8]; + int ret; + + netsec_offset_and_sizes(state, + do_unseal, + &min_sig_size, + NULL, + &checksum_length, + &confounder_ofs); + + if (sig->length < min_sig_size) { + return NT_STATUS_ACCESS_DENIED; + } + + if (do_unseal) { + confounder = _confounder; + memcpy(confounder, sig->data+confounder_ofs, 8); + } else { + confounder = NULL; + } + + SETUP_SEQNUM(state, seq_num, !state->initiator); + + if (do_unseal) { + netsec_do_seal(state, seq_num, + confounder, + data, length, + false); + } + + netsec_do_sign(state, confounder, + data, length, + header, checksum); + + ret = memcmp(checksum, sig->data+16, checksum_length); + if (ret != 0) { + dump_data_pw("calc digest:", checksum, checksum_length); + dump_data_pw("wire digest:", sig->data+16, checksum_length); + return NT_STATUS_ACCESS_DENIED; + } + + netsec_do_seq_num(state, checksum, checksum_length, seq_num); + + ret = memcmp(seq_num, sig->data+8, 8); + if (ret != 0) { + dump_data_pw("calc seq num:", seq_num, 8); + dump_data_pw("wire seq num:", sig->data+8, 8); + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; +} + +static uint32_t netsec_outgoing_sig_size(struct schannel_state *state) +{ + uint32_t sig_size = 0; + + netsec_offset_and_sizes(state, + true, + NULL, + &sig_size, + NULL, + NULL); + + return sig_size; +} + +static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, + TALLOC_CTX *mem_ctx, + bool do_seal, + uint8_t *data, size_t length, + DATA_BLOB *sig) +{ + uint32_t min_sig_size = 0; + uint32_t used_sig_size = 0; + uint8_t header[8]; + uint8_t checksum[32]; + uint32_t checksum_length = sizeof(checksum_length); + uint8_t _confounder[8]; + uint8_t *confounder = NULL; + uint32_t confounder_ofs = 0; + uint8_t seq_num[8]; + + netsec_offset_and_sizes(state, + do_seal, + &min_sig_size, + &used_sig_size, + &checksum_length, + &confounder_ofs); + + SETUP_SEQNUM(state, seq_num, state->initiator); + + if (do_seal) { + confounder = _confounder; + generate_random_buffer(confounder, 8); + } else { + confounder = NULL; + } + + netsec_do_sign(state, confounder, + data, length, + header, checksum); + + if (do_seal) { + netsec_do_seal(state, seq_num, + confounder, + data, length, + true); + } + + netsec_do_seq_num(state, checksum, checksum_length, seq_num); + + (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size); + + memcpy(sig->data, header, 8); + memcpy(sig->data+8, seq_num, 8); + memcpy(sig->data+16, checksum, checksum_length); + + if (confounder) { + memcpy(sig->data+confounder_ofs, confounder, 8); + } + + dump_data_pw("signature:", sig->data+ 0, 8); + dump_data_pw("seq_num :", sig->data+ 8, 8); + dump_data_pw("digest :", sig->data+16, checksum_length); + dump_data_pw("confound :", sig->data+confounder_ofs, 8); + + return NT_STATUS_OK; +} _PUBLIC_ NTSTATUS gensec_schannel_init(void); diff --git a/libcli/auth/schannel_proto.h b/libcli/auth/schannel_proto.h index da76559..bce37c8 100644 --- a/libcli/auth/schannel_proto.h +++ b/libcli/auth/schannel_proto.h @@ -28,18 +28,4 @@ struct schannel_state; struct db_context *open_schannel_session_store(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx); -struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState *creds, - bool initiator); -NTSTATUS netsec_incoming_packet(struct schannel_state *state, - bool do_unseal, - uint8_t *data, size_t length, - const DATA_BLOB *sig); -uint32_t netsec_outgoing_sig_size(struct schannel_state *state); -NTSTATUS netsec_outgoing_packet(struct schannel_state *state, - TALLOC_CTX *mem_ctx, - bool do_seal, - uint8_t *data, size_t length, - DATA_BLOB *sig); - #endif diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c deleted file mode 100644 index 9502cba..0000000 --- a/libcli/auth/schannel_sign.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - schannel library code - - Copyright (C) Andrew Tridgell 2004 - 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 - (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 "includes.h" -#include "../libcli/auth/schannel.h" -#include "../lib/crypto/crypto.h" - -struct schannel_state { - uint64_t seq_num; - bool initiator; - struct netlogon_creds_CredentialState *creds; -}; - -#define SETUP_SEQNUM(state, buf, initiator) do { \ - uint8_t *_buf = buf; \ - uint32_t _seq_num_low = (state)->seq_num & UINT32_MAX; \ - uint32_t _seq_num_high = (state)->seq_num >> 32; \ - if (initiator) { \ - _seq_num_high |= 0x80000000; \ - } \ - RSIVAL(_buf, 0, _seq_num_low); \ - RSIVAL(_buf, 4, _seq_num_high); \ -} while(0) - -struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState *creds, - bool initiator) -{ - struct schannel_state *state; - - state = talloc(mem_ctx, struct schannel_state); - if (state == NULL) { - return NULL; - } - - state->initiator = initiator; - state->seq_num = 0; - state->creds = netlogon_creds_copy(state, creds); - if (state->creds == NULL) { - talloc_free(state); - return NULL; - } - - return state; -} - -static void netsec_offset_and_sizes(struct schannel_state *state, - bool do_seal, - uint32_t *_min_sig_size, - uint32_t *_used_sig_size, - uint32_t *_checksum_length, - uint32_t *_confounder_ofs) -{ - uint32_t min_sig_size; - uint32_t used_sig_size; - uint32_t checksum_length; - uint32_t confounder_ofs; - - if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - min_sig_size = 48; - used_sig_size = 56; - /* - * Note: windows has a bug here and uses the old values... - * - * checksum_length = 32; - * confounder_ofs = 48; - */ - checksum_length = 8; - confounder_ofs = 24; - } else { - min_sig_size = 24; - used_sig_size = 32; - checksum_length = 8; - confounder_ofs = 24; - } - - if (do_seal) { - min_sig_size += 8; - } - - if (_min_sig_size) { - *_min_sig_size = min_sig_size; - } - - if (_used_sig_size) { - *_used_sig_size = used_sig_size; - } - - if (_checksum_length) { - *_checksum_length = checksum_length; - } - - if (_confounder_ofs) { - *_confounder_ofs = confounder_ofs; - } -} - -/******************************************************************* - Encode or Decode the sequence number (which is symmetric) - ********************************************************************/ -static void netsec_do_seq_num(struct schannel_state *state, - const uint8_t *checksum, - uint32_t checksum_length, - uint8_t seq_num[8]) -{ - if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - AES_KEY key; - uint8_t iv[AES_BLOCK_SIZE]; - - AES_set_encrypt_key(state->creds->session_key, 128, &key); - ZERO_STRUCT(iv); - memcpy(iv+0, checksum, 8); - memcpy(iv+8, checksum, 8); - - aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT); - } else { - static const uint8_t zeros[4]; - uint8_t sequence_key[16]; - uint8_t digest1[16]; - - hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1); - hmac_md5(digest1, checksum, checksum_length, sequence_key); - arcfour_crypt(seq_num, sequence_key, 8); - } - - state->seq_num++; -} - -static void netsec_do_seal(struct schannel_state *state, - const uint8_t seq_num[8], - uint8_t confounder[8], - uint8_t *data, uint32_t length, - bool forward) -{ - if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - AES_KEY key; - uint8_t iv[AES_BLOCK_SIZE]; - uint8_t sess_kf0[16]; - int i; - - for (i = 0; i < 16; i++) { - sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; - } - - AES_set_encrypt_key(sess_kf0, 128, &key); - ZERO_STRUCT(iv); - memcpy(iv+0, seq_num, 8); - memcpy(iv+8, seq_num, 8); - - if (forward) { - aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_ENCRYPT); - aes_cfb8_encrypt(data, data, length, &key, iv, AES_ENCRYPT); - } else { - aes_cfb8_encrypt(confounder, confounder, 8, &key, iv, AES_DECRYPT); - aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT); - } - } else { - uint8_t sealing_key[16]; - static const uint8_t zeros[4]; - uint8_t digest2[16]; - uint8_t sess_kf0[16]; - int i; - - for (i = 0; i < 16; i++) { - sess_kf0[i] = state->creds->session_key[i] ^ 0xf0; - } - - hmac_md5(sess_kf0, zeros, 4, digest2); - hmac_md5(digest2, seq_num, 8, sealing_key); - - arcfour_crypt(confounder, sealing_key, 8); - arcfour_crypt(data, sealing_key, length); - } -} - -/******************************************************************* - Create a digest over the entire packet (including the data), and - MD5 it with the session key. - ********************************************************************/ -static void netsec_do_sign(struct schannel_state *state, - const uint8_t *confounder, - const uint8_t *data, size_t length, - uint8_t header[8], - uint8_t *checksum) -{ - if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - struct HMACSHA256Context ctx; - - hmac_sha256_init(state->creds->session_key, - sizeof(state->creds->session_key), - &ctx); - - if (confounder) { - SSVAL(header, 0, NL_SIGN_HMAC_SHA256); - SSVAL(header, 2, NL_SEAL_AES128); - SSVAL(header, 4, 0xFFFF); - SSVAL(header, 6, 0x0000); - - hmac_sha256_update(header, 8, &ctx); - hmac_sha256_update(confounder, 8, &ctx); - } else { - SSVAL(header, 0, NL_SIGN_HMAC_SHA256); - SSVAL(header, 2, NL_SEAL_NONE); - SSVAL(header, 4, 0xFFFF); - SSVAL(header, 6, 0x0000); - - hmac_sha256_update(header, 8, &ctx); - } - - hmac_sha256_update(data, length, &ctx); - - hmac_sha256_final(checksum, &ctx); - } else { - uint8_t packet_digest[16]; - static const uint8_t zeros[4]; - MD5_CTX ctx; - - MD5Init(&ctx); - MD5Update(&ctx, zeros, 4); - if (confounder) { - SSVAL(header, 0, NL_SIGN_HMAC_MD5); - SSVAL(header, 2, NL_SEAL_RC4); - SSVAL(header, 4, 0xFFFF); - SSVAL(header, 6, 0x0000); - - MD5Update(&ctx, header, 8); - MD5Update(&ctx, confounder, 8); - } else { - SSVAL(header, 0, NL_SIGN_HMAC_MD5); - SSVAL(header, 2, NL_SEAL_NONE); - SSVAL(header, 4, 0xFFFF); - SSVAL(header, 6, 0x0000); - - MD5Update(&ctx, header, 8); - } - MD5Update(&ctx, data, length); - MD5Final(packet_digest, &ctx); - - hmac_md5(state->creds->session_key, - packet_digest, sizeof(packet_digest), - checksum); - } -} - -NTSTATUS netsec_incoming_packet(struct schannel_state *state, - bool do_unseal, - uint8_t *data, size_t length, - const DATA_BLOB *sig) -{ - uint32_t min_sig_size = 0; - uint8_t header[8]; - uint8_t checksum[32]; - uint32_t checksum_length = sizeof(checksum_length); - uint8_t _confounder[8]; - uint8_t *confounder = NULL; - uint32_t confounder_ofs = 0; - uint8_t seq_num[8]; - int ret; - - netsec_offset_and_sizes(state, - do_unseal, - &min_sig_size, - NULL, - &checksum_length, - &confounder_ofs); - - if (sig->length < min_sig_size) { - return NT_STATUS_ACCESS_DENIED; - } - - if (do_unseal) { - confounder = _confounder; - memcpy(confounder, sig->data+confounder_ofs, 8); - } else { - confounder = NULL; - } - - SETUP_SEQNUM(state, seq_num, !state->initiator); - - if (do_unseal) { - netsec_do_seal(state, seq_num, - confounder, - data, length, - false); - } - - netsec_do_sign(state, confounder, - data, length, - header, checksum); - - ret = memcmp(checksum, sig->data+16, checksum_length); - if (ret != 0) { - dump_data_pw("calc digest:", checksum, checksum_length); - dump_data_pw("wire digest:", sig->data+16, checksum_length); - return NT_STATUS_ACCESS_DENIED; - } - - netsec_do_seq_num(state, checksum, checksum_length, seq_num); - - ret = memcmp(seq_num, sig->data+8, 8); - if (ret != 0) { - dump_data_pw("calc seq num:", seq_num, 8); - dump_data_pw("wire seq num:", sig->data+8, 8); - return NT_STATUS_ACCESS_DENIED; - } - - return NT_STATUS_OK; -} - -uint32_t netsec_outgoing_sig_size(struct schannel_state *state) -{ - uint32_t sig_size = 0; - - netsec_offset_and_sizes(state, - true, - NULL, - &sig_size, - NULL, - NULL); - - return sig_size; -} - -NTSTATUS netsec_outgoing_packet(struct schannel_state *state, - TALLOC_CTX *mem_ctx, - bool do_seal, - uint8_t *data, size_t length, - DATA_BLOB *sig) -{ - uint32_t min_sig_size = 0; - uint32_t used_sig_size = 0; - uint8_t header[8]; - uint8_t checksum[32]; - uint32_t checksum_length = sizeof(checksum_length); - uint8_t _confounder[8]; - uint8_t *confounder = NULL; - uint32_t confounder_ofs = 0; - uint8_t seq_num[8]; - - netsec_offset_and_sizes(state, - do_seal, - &min_sig_size, - &used_sig_size, - &checksum_length, - &confounder_ofs); - - SETUP_SEQNUM(state, seq_num, state->initiator); - - if (do_seal) { - confounder = _confounder; - generate_random_buffer(confounder, 8); - } else { - confounder = NULL; - } - - netsec_do_sign(state, confounder, - data, length, - header, checksum); - - if (do_seal) { - netsec_do_seal(state, seq_num, - confounder, - data, length, - true); - } - - netsec_do_seq_num(state, checksum, checksum_length, seq_num); - - (*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size); - - memcpy(sig->data, header, 8); - memcpy(sig->data+8, seq_num, 8); - memcpy(sig->data+16, checksum, checksum_length); - - if (confounder) { - memcpy(sig->data+confounder_ofs, confounder, 8); - } - - dump_data_pw("signature:", sig->data+ 0, 8); - dump_data_pw("seq_num :", sig->data+ 8, 8); - dump_data_pw("digest :", sig->data+16, checksum_length); - dump_data_pw("confound :", sig->data+confounder_ofs, 8); - - return NT_STATUS_OK; -} diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build index df23058..ca2be2d 100755 --- a/libcli/auth/wscript_build +++ b/libcli/auth/wscript_build @@ -24,7 +24,7 @@ bld.SAMBA_SUBSYSTEM('LIBCLI_AUTH', bld.SAMBA_SUBSYSTEM('COMMON_SCHANNEL', - source='schannel_state_tdb.c schannel_sign.c', + source='schannel_state_tdb.c', deps='dbwrap util_tdb samba-hostconfig NDR_NETLOGON' ) -- 1.9.3 From 307627065568a259eb9e94953b872bf723477be6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 31 Dec 2013 10:11:18 +0100 Subject: [PATCH 150/249] auth/gensec: implement GENSEC_FEATURE_SIGN_PKT_HEADER in schannel.c Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 03006d0e4471465f071517097145806fbe46fdba) --- auth/gensec/schannel.c | 56 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/auth/gensec/schannel.c b/auth/gensec/schannel.c index c60ab4f..3d30e83 100644 --- a/auth/gensec/schannel.c +++ b/auth/gensec/schannel.c @@ -34,6 +34,7 @@ #include "lib/crypto/crypto.h" struct schannel_state { + struct gensec_security *gensec; uint64_t seq_num; bool initiator; struct netlogon_creds_CredentialState *creds; @@ -50,17 +51,19 @@ struct schannel_state { RSIVAL(_buf, 4, _seq_num_high); \ } while(0) -static struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, +static struct schannel_state *netsec_create_state( + struct gensec_security *gensec, struct netlogon_creds_CredentialState *creds, bool initiator) { struct schannel_state *state; - state = talloc(mem_ctx, struct schannel_state); + state = talloc(gensec, struct schannel_state); if (state == NULL) { return NULL; } + state->gensec = gensec; state->initiator = initiator; state->seq_num = 0; state->creds = netlogon_creds_copy(state, creds); @@ -69,6 +72,8 @@ static struct schannel_state *netsec_create_state(TALLOC_CTX *mem_ctx, return NULL; } + gensec->private_data = state; + return state; } @@ -273,6 +278,7 @@ static void netsec_do_sign(struct schannel_state *state, static NTSTATUS netsec_incoming_packet(struct schannel_state *state, bool do_unseal, uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, const DATA_BLOB *sig) { uint32_t min_sig_size = 0; @@ -284,6 +290,8 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state, uint32_t confounder_ofs = 0; uint8_t seq_num[8]; int ret; + const uint8_t *sign_data = NULL; + size_t sign_length = 0; netsec_offset_and_sizes(state, do_unseal, @@ -312,8 +320,16 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state, false); } + if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { + sign_data = whole_pdu; + sign_length = pdu_length; + } else { + sign_data = data; + sign_length = length; + } + netsec_do_sign(state, confounder, - data, length, + sign_data, sign_length, header, checksum); ret = memcmp(checksum, sig->data+16, checksum_length); @@ -353,6 +369,7 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, TALLOC_CTX *mem_ctx, bool do_seal, uint8_t *data, size_t length, + const uint8_t *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { uint32_t min_sig_size = 0; @@ -364,6 +381,8 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, uint8_t *confounder = NULL; uint32_t confounder_ofs = 0; uint8_t seq_num[8]; + const uint8_t *sign_data = NULL; + size_t sign_length = 0; netsec_offset_and_sizes(state, do_seal, @@ -381,8 +400,16 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state, confounder = NULL; } + if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { + sign_data = whole_pdu; + sign_length = pdu_length; + } else { + sign_data = data; + sign_length = length; + } + netsec_do_sign(state, confounder, - data, length, + sign_data, sign_length, header, checksum); if (do_seal) { @@ -457,7 +484,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ if (state == NULL) { return NT_STATUS_NO_MEMORY; } - gensec_security->private_data = state; bind_schannel.MessageType = NL_NEGOTIATE_REQUEST; #if 0 @@ -553,7 +579,6 @@ static NTSTATUS schannel_update(struct gensec_security *gensec_security, TALLOC_ if (state == NULL) { return NT_STATUS_NO_MEMORY; } - gensec_security->private_data = state; bind_schannel_ack.MessageType = NL_NEGOTIATE_RESPONSE; bind_schannel_ack.Flags = 0; @@ -608,6 +633,9 @@ static bool schannel_have_feature(struct gensec_security *gensec_security, if (feature & GENSEC_FEATURE_DCE_STYLE) { return true; } + if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) { + return true; + } return false; } @@ -625,7 +653,9 @@ static NTSTATUS schannel_unseal_packet(struct gensec_security *gensec_security, return netsec_incoming_packet(state, true, discard_const_p(uint8_t, data), - length, sig); + length, + whole_pdu, pdu_length, + sig); } /* @@ -642,7 +672,9 @@ static NTSTATUS schannel_check_packet(struct gensec_security *gensec_security, return netsec_incoming_packet(state, false, discard_const_p(uint8_t, data), - length, sig); + length, + whole_pdu, pdu_length, + sig); } /* seal a packet @@ -658,7 +690,9 @@ static NTSTATUS schannel_seal_packet(struct gensec_security *gensec_security, struct schannel_state); return netsec_outgoing_packet(state, mem_ctx, true, - data, length, sig); + data, length, + whole_pdu, pdu_length, + sig); } /* @@ -676,7 +710,9 @@ static NTSTATUS schannel_sign_packet(struct gensec_security *gensec_security, return netsec_outgoing_packet(state, mem_ctx, false, discard_const_p(uint8_t, data), - length, sig); + length, + whole_pdu, pdu_length, + sig); } static const struct gensec_security_ops gensec_schannel_security_ops = { -- 1.9.3 From 5b457559dfaeaf8f3d9227a93e5b75e0e7464c23 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 5 Jan 2014 06:16:03 +0100 Subject: [PATCH 151/249] s3:rpc_client: talloc_zero pipe_auth_data Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 5b39a351a8ceb3bec04236ceb4b2fe10651958a9) --- source3/rpc_client/cli_pipe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index a343997..7d1e347 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -2101,7 +2101,7 @@ NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx, { struct pipe_auth_data *result; - result = talloc(mem_ctx, struct pipe_auth_data); + result = talloc_zero(mem_ctx, struct pipe_auth_data); if (result == NULL) { return NT_STATUS_NO_MEMORY; } @@ -2125,7 +2125,7 @@ NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx, { struct pipe_auth_data *result; - result = talloc(mem_ctx, struct pipe_auth_data); + result = talloc_zero(mem_ctx, struct pipe_auth_data); if (result == NULL) { return NT_STATUS_NO_MEMORY; } @@ -2160,7 +2160,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, struct pipe_auth_data *result; NTSTATUS status; - result = talloc(mem_ctx, struct pipe_auth_data); + result = talloc_zero(mem_ctx, struct pipe_auth_data); if (result == NULL) { return NT_STATUS_NO_MEMORY; } -- 1.9.3 From dd35874efea280b91ccaadf14a9a18e8a9017ea4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 5 Jan 2014 06:31:44 +0100 Subject: [PATCH 152/249] s3:rpc_client: make rpc_api_pipe_req_send/recv static Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 946e29dbc148d40fadbee81d4d530a36c0f2f1e6) --- source3/rpc_client/cli_pipe.c | 4 ++-- source3/rpc_client/cli_pipe.h | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 7d1e347..3d12454 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1153,7 +1153,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq); static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, bool *is_last_frag); -struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, +static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct rpc_pipe_client *cli, uint8_t op_num, @@ -1366,7 +1366,7 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq) tevent_req_done(req); } -NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, +static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, DATA_BLOB *reply_pdu) { struct rpc_api_pipe_req_state *state = tevent_req_data( diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index ab99373..826f9bf 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -27,16 +27,6 @@ /* The following definitions come from rpc_client/cli_pipe.c */ -struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct rpc_pipe_client *cli, - uint8_t op_num, - DATA_BLOB *req_data); - -NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - DATA_BLOB *reply_pdu); - struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct rpc_pipe_client *cli, -- 1.9.3 From 9ea586bbac52bf17e6a1147420bfc9648e697706 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 5 Jan 2014 07:56:20 +0100 Subject: [PATCH 153/249] s3:rpc_client: add some const to rpc_api_pipe_req_send() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 4d3376e919b5c33f272b3a584d8172729a7468e0) --- source3/rpc_client/cli_pipe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 3d12454..6b7fee2 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1142,7 +1142,7 @@ struct rpc_api_pipe_req_state { struct rpc_pipe_client *cli; uint8_t op_num; uint32_t call_id; - DATA_BLOB *req_data; + const DATA_BLOB *req_data; uint32_t req_data_sent; DATA_BLOB rpc_out; DATA_BLOB reply_pdu; @@ -1157,7 +1157,7 @@ static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct rpc_pipe_client *cli, uint8_t op_num, - DATA_BLOB *req_data) + const DATA_BLOB *req_data) { struct tevent_req *req, *subreq; struct rpc_api_pipe_req_state *state; -- 1.9.3 From cc6303171f06ae26bce9d54013a63a6296563dd7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 5 Jan 2014 08:26:15 +0100 Subject: [PATCH 154/249] s3:rpc_client: handle DCERPC_AUTH_TYPE_SCHANNEL as any other gensec backend Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit f7bf7e705e704d2f1702e42a8e400baff9521066) --- source3/rpc_client/cli_pipe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 6b7fee2..b142774 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1627,11 +1627,11 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case DCERPC_AUTH_TYPE_NONE: case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: - case DCERPC_AUTH_TYPE_SCHANNEL: /* Bind complete. */ tevent_req_done(req); return; + case DCERPC_AUTH_TYPE_SCHANNEL: case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_SPNEGO: case DCERPC_AUTH_TYPE_KRB5: @@ -1666,11 +1666,11 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case DCERPC_AUTH_TYPE_NONE: case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: - case DCERPC_AUTH_TYPE_SCHANNEL: /* Bind complete. */ tevent_req_done(req); return; + case DCERPC_AUTH_TYPE_SCHANNEL: case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_SPNEGO: -- 1.9.3 From 044ca24f9d8a3bf57d6981c89e6dcc5e4477059d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 22:41:33 +0100 Subject: [PATCH 155/249] s3:rpc_client: implement DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 61bdbc23cd09a594a63f49ff8626934c85a8e51a) --- source3/librpc/rpc/dcerpc.h | 4 +++- source3/rpc_client/cli_pipe.c | 44 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index b18b7ba..aaf8d68 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -39,7 +39,9 @@ struct NL_AUTH_MESSAGE; struct pipe_auth_data { enum dcerpc_AuthType auth_type; enum dcerpc_AuthLevel auth_level; - + bool client_hdr_signing; + bool hdr_signing; + void *auth_ctx; /* Only the client code uses these 3 for now */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index b142774..1cab580 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1002,16 +1002,31 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, - DATA_BLOB *auth_token) + DATA_BLOB *auth_token, + bool *client_hdr_signing) { struct gensec_security *gensec_security; DATA_BLOB null_blob = data_blob_null; + NTSTATUS status; gensec_security = talloc_get_type_abort(cli->auth->auth_ctx, struct gensec_security); DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n")); - return gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token); + status = gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token); + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) + { + return status; + } + + if (client_hdr_signing != NULL) { + *client_hdr_signing = gensec_have_feature(gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER); + } + + return status; } /******************************************************************* @@ -1024,17 +1039,23 @@ static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *abstract, const struct ndr_syntax_id *transfer, const DATA_BLOB *auth_info, + bool client_hdr_signing, DATA_BLOB *blob) { uint16 auth_len = auth_info->length; NTSTATUS status; union dcerpc_payload u; struct dcerpc_ctx_list ctx_list; + uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; if (auth_len) { auth_len -= DCERPC_AUTH_TRAILER_LENGTH; } + if (client_hdr_signing) { + pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + ctx_list.context_id = 0; ctx_list.num_transfer_syntaxes = 1; ctx_list.abstract_syntax = *abstract; @@ -1048,9 +1069,7 @@ static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx, u.bind.auth_info = *auth_info; status = dcerpc_push_ncacn_packet(mem_ctx, - ptype, - DCERPC_PFC_FLAG_FIRST | - DCERPC_PFC_FLAG_LAST, + ptype, pfc_flags, auth_len, rpc_call_id, &u, @@ -1084,7 +1103,9 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_SPNEGO: - ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token); + ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, + &auth_token, + &auth->client_hdr_signing); if (!NT_STATUS_IS_OK(ret) && !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) { @@ -1126,6 +1147,7 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, abstract, transfer, &auth_info, + auth->client_hdr_signing, rpc_out); return ret; } @@ -1507,6 +1529,7 @@ static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx, abstract, transfer, &auth_info, + false, /* client_hdr_signing */ rpc_out); data_blob_free(&auth_info); return status; @@ -1676,6 +1699,15 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case DCERPC_AUTH_TYPE_SPNEGO: gensec_security = talloc_get_type_abort(pauth->auth_ctx, struct gensec_security); + + if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) { + if (pauth->client_hdr_signing) { + pauth->hdr_signing = true; + gensec_want_feature(gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER); + } + } + status = gensec_update(gensec_security, state, NULL, auth.credentials, &auth_token); if (NT_STATUS_EQUAL(status, -- 1.9.3 From 472b11d1b0fdbb1ca61e64979e4b5fd7dc1756a5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 22:56:03 +0100 Subject: [PATCH 156/249] s3:rpc_server: add support for DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN If the backend supports it there's no reason to avoid it. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 523d616268af5f94e11c863f9acdebabace80608) --- source3/rpc_server/srv_pipe.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 5f834fb..f572819 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -42,6 +42,7 @@ #include "rpc_server/rpc_contexts.h" #include "lib/param/param.h" #include "librpc/ndr/ndr_table.h" +#include "auth/gensec/gensec.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -418,10 +419,11 @@ bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) *******************************************************************/ static bool pipe_auth_generic_bind(struct pipes_struct *p, - TALLOC_CTX *mem_ctx, + struct ncacn_packet *pkt, struct dcerpc_auth *auth_info, DATA_BLOB *response) { + TALLOC_CTX *mem_ctx = pkt; struct gensec_security *gensec_security = NULL; NTSTATUS status; @@ -444,6 +446,17 @@ static bool pipe_auth_generic_bind(struct pipes_struct *p, p->auth.auth_ctx = gensec_security; p->auth.auth_type = auth_info->auth_type; + if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) { + p->auth.client_hdr_signing = true; + p->auth.hdr_signing = gensec_have_feature(gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER); + } + + if (p->auth.hdr_signing) { + gensec_want_feature(gensec_security, + GENSEC_FEATURE_SIGN_PKT_HEADER); + } + return true; } @@ -548,6 +561,7 @@ static bool api_pipe_bind_req(struct pipes_struct *p, unsigned int auth_type = DCERPC_AUTH_TYPE_NONE; NTSTATUS status; struct ndr_syntax_id id; + uint8_t pfc_flags = 0; union dcerpc_payload u; struct dcerpc_ack_ctx bind_ack_ctx; DATA_BLOB auth_resp = data_blob_null; @@ -792,10 +806,15 @@ static bool api_pipe_bind_req(struct pipes_struct *p, * header and are never sending more than one PDU here. */ + pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; + + if (p->auth.hdr_signing) { + pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN; + } + status = dcerpc_push_ncacn_packet(p->mem_ctx, DCERPC_PKT_BIND_ACK, - DCERPC_PFC_FLAG_FIRST | - DCERPC_PFC_FLAG_LAST, + pfc_flags, auth_resp.length, pkt->call_id, &u, -- 1.9.3 From 4e6bea89ffcca074e0320b98e65485f348a469a5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 09:25:23 +0100 Subject: [PATCH 157/249] librpc/ndr: add LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES This lets ndr_pull_subcontext_end() make sure that all subcontext bytes are consumed otherwise it returns NDR_ERR_UNREAD_BYTES. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit b62308ed994e9734dfd934d230531010d9e7cefa) --- librpc/idl/idl_types.h | 2 ++ librpc/ndr/libndr.h | 6 ++++++ librpc/ndr/ndr.c | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/librpc/idl/idl_types.h b/librpc/idl/idl_types.h index c50efac..838c219 100644 --- a/librpc/idl/idl_types.h +++ b/librpc/idl/idl_types.h @@ -53,3 +53,5 @@ #define NDR_RELATIVE_REVERSE LIBNDR_FLAG_RELATIVE_REVERSE #define NDR_NO_RELATIVE_REVERSE LIBNDR_FLAG_NO_RELATIVE_REVERSE + +#define NDR_SUBCONTEXT_NO_UNREAD_BYTES LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h index a950519..8070c3c 100644 --- a/librpc/ndr/libndr.h +++ b/librpc/ndr/libndr.h @@ -123,6 +123,12 @@ struct ndr_print { #define LIBNDR_FLAG_STR_RAW8 (1<<13) #define LIBNDR_STRING_FLAGS (0x7FFC) +/* + * This lets ndr_pull_subcontext_end() return + * NDR_ERR_UNREAD_BYTES. + */ +#define LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES (1<<17) + /* set if relative pointers should *not* be marshalled in reverse order */ #define LIBNDR_FLAG_NO_RELATIVE_REVERSE (1<<18) diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index e86cf2f..15a7f12 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -638,6 +638,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr, ssize_t size_is) { uint32_t advance; + uint32_t highest_ofs; + if (size_is >= 0) { advance = size_is; } else if (header_size > 0) { @@ -645,6 +647,24 @@ _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr, } else { advance = subndr->offset; } + + if (subndr->offset > ndr->relative_highest_offset) { + highest_ofs = subndr->offset; + } else { + highest_ofs = subndr->relative_highest_offset; + } + if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) { + /* + * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified + */ + highest_ofs = advance; + } + if (highest_ofs < advance) { + return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES, + "not all bytes consumed ofs[%u] advance[%u]", + highest_ofs, advance); + } + NDR_CHECK(ndr_pull_advance(ndr, advance)); return NDR_ERR_SUCCESS; } -- 1.9.3 From 5960d93d9cddca327ad8d24a41c64421ac6bb561 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 3 Jan 2014 15:06:23 +0100 Subject: [PATCH 158/249] dcerpc.idl: add documentation references To [C706 - DCE 1.1: Remote Procedure Call] and [MS-RPCE]. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 66c39420e29e7c257d9cdc5d04c061472bbefd19) --- librpc/idl/dcerpc.idl | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl index 86f22a4..23cac89 100644 --- a/librpc/idl/dcerpc.idl +++ b/librpc/idl/dcerpc.idl @@ -5,8 +5,17 @@ but given that pidl can handle it nicely it simplifies things a lot to do it this way - see http://www.opengroup.org/onlinepubs/9629399/chap12.htm for packet - layouts + See [C706 - DCE 1.1: Remote Procedure Call] for the OpenGroup + DCERPC specification: + http://pubs.opengroup.org/onlinepubs/9629399/toc.htm + + See C706 - Chapter 12: RPC PDU Encodings for packet layouts: + http://www.opengroup.org/onlinepubs/9629399/chap12.htm + + See also [MS-RPCE] for the Microsoft + "Remote Procedure Call Protocol Extensions". + http://msdn.microsoft.com/en-us/library/cc243560.aspx + */ import "misc.idl"; -- 1.9.3 From 812cb7e6010b39fb752cf85026fd8d8a5dccbb39 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 2 Jan 2014 11:18:38 +0100 Subject: [PATCH 159/249] dcerpc.idl: add dcerpc_sec_verification_trailer See [MS-RPCE] 2.2.2.13 Verification Trailer for details. Pair-Programmed-With: Gregor Beck Signed-off-by: Gregor Beck Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit c0dc2fb7e1dadcef35a132040448cb27ff1d5bfa) --- librpc/idl/dcerpc.idl | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ librpc/ndr/ndr_dcerpc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ librpc/wscript_build | 2 +- 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 librpc/ndr/ndr_dcerpc.c diff --git a/librpc/idl/dcerpc.idl b/librpc/idl/dcerpc.idl index 23cac89..8e9be0e 100644 --- a/librpc/idl/dcerpc.idl +++ b/librpc/idl/dcerpc.idl @@ -19,6 +19,8 @@ */ import "misc.idl"; +cpp_quote("extern const uint8_t DCERPC_SEC_VT_MAGIC[8];") + interface dcerpc { typedef struct { @@ -514,4 +516,69 @@ interface dcerpc uint8 serial_low; [switch_is(ptype)] dcerpc_payload u; } ncadg_packet; + + typedef [bitmap16bit] bitmap { + DCERPC_SEC_VT_COMMAND_ENUM = 0x3FFF, + DCERPC_SEC_VT_COMMAND_END = 0x4000, + DCERPC_SEC_VT_MUST_PROCESS = 0x8000 + } dcerpc_sec_vt_command; + + typedef [enum16bit] enum { + DCERPC_SEC_VT_COMMAND_BITMASK1 = 0x0001, + DCERPC_SEC_VT_COMMAND_PCONTEXT = 0x0002, + DCERPC_SEC_VT_COMMAND_HEADER2 = 0x0003 + } dcerpc_sec_vt_command_enum; + + typedef [bitmap32bit] bitmap { + DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING = 0x00000001 + } dcerpc_sec_vt_bitmask1; + + typedef struct { + ndr_syntax_id abstract_syntax; + ndr_syntax_id transfer_syntax; + } dcerpc_sec_vt_pcontext; + + typedef struct { + dcerpc_pkt_type ptype; /* Packet type */ + [value(0)] uint8 reserved1; + [value(0)] uint16 reserved2; + uint8 drep[4]; /* NDR data representation */ + uint32 call_id; /* Call identifier */ + uint16 context_id; + uint16 opnum; + } dcerpc_sec_vt_header2; + + typedef [switch_type(dcerpc_sec_vt_command_enum),nodiscriminant] union { + [case(DCERPC_SEC_VT_COMMAND_BITMASK1)] dcerpc_sec_vt_bitmask1 bitmask1; + [case(DCERPC_SEC_VT_COMMAND_PCONTEXT)] dcerpc_sec_vt_pcontext pcontext; + [case(DCERPC_SEC_VT_COMMAND_HEADER2)] dcerpc_sec_vt_header2 header2; + [default,flag(NDR_REMAINING)] DATA_BLOB _unknown; + } dcerpc_sec_vt_union; + + typedef struct { + dcerpc_sec_vt_command command; + [switch_is(command & DCERPC_SEC_VT_COMMAND_ENUM)] + [subcontext(2),flag(NDR_SUBCONTEXT_NO_UNREAD_BYTES)] + dcerpc_sec_vt_union u; + } dcerpc_sec_vt; + + typedef [public,nopush,nopull] struct { + uint16 count; + } dcerpc_sec_vt_count; + + /* + * We assume that the whole verification trailer fits into + * the last 1024 bytes after the stub data. + * + * There're currently only 3 commands defined and each should + * only be used once. + */ + const uint16 DCERPC_SEC_VT_MAX_SIZE = 1024; + + typedef [public,flag(NDR_PAHEX)] struct { + [flag(NDR_ALIGN4)] DATA_BLOB _pad; + [value(DCERPC_SEC_VT_MAGIC)] uint8 magic[8]; + dcerpc_sec_vt_count count; + dcerpc_sec_vt commands[count.count]; + } dcerpc_sec_verification_trailer; } diff --git a/librpc/ndr/ndr_dcerpc.c b/librpc/ndr/ndr_dcerpc.c new file mode 100644 index 0000000..88a7f38 --- /dev/null +++ b/librpc/ndr/ndr_dcerpc.c @@ -0,0 +1,66 @@ +/* + Unix SMB/CIFS implementation. + + Manually parsed structures found in the DCERPC protocol + + Copyright (C) Stefan Metzmacher 2014 + Copyright (C) Gregor Beck 2014 + + 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 "includes.h" +#include "bin/default/librpc/gen_ndr/ndr_dcerpc.h" + +#include "librpc/gen_ndr/ndr_misc.h" + +const uint8_t DCERPC_SEC_VT_MAGIC[] = {0x8a,0xe3,0x13,0x71,0x02,0xf4,0x36,0x71}; + +_PUBLIC_ enum ndr_err_code ndr_push_dcerpc_sec_vt_count(struct ndr_push *ndr, int ndr_flags, const struct dcerpc_sec_vt_count *r) +{ + NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags); + /* nothing */ + return NDR_ERR_SUCCESS; +} + +_PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_sec_vt_count(struct ndr_pull *ndr, int ndr_flags, struct dcerpc_sec_vt_count *r) +{ + uint32_t _saved_ofs = ndr->offset; + + NDR_PULL_CHECK_FLAGS(ndr, ndr_flags); + + if (!(ndr_flags & NDR_SCALARS)) { + return NDR_ERR_SUCCESS; + } + + r->count = 0; + + while (true) { + uint16_t command; + uint16_t length; + + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &command)); + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &length)); + NDR_CHECK(ndr_pull_advance(ndr, length)); + + r->count += 1; + + if (command & DCERPC_SEC_VT_COMMAND_END) { + break; + } + } + + ndr->offset = _saved_ofs; + return NDR_ERR_SUCCESS; +} diff --git a/librpc/wscript_build b/librpc/wscript_build index 2017a29..a5cf687 100644 --- a/librpc/wscript_build +++ b/librpc/wscript_build @@ -301,7 +301,7 @@ bld.SAMBA_SUBSYSTEM('NDR_FSRVP', ) bld.SAMBA_SUBSYSTEM('NDR_DCERPC', - source='gen_ndr/ndr_dcerpc.c', + source='gen_ndr/ndr_dcerpc.c ndr/ndr_dcerpc.c', public_deps='ndr', public_headers='gen_ndr/ndr_dcerpc.h gen_ndr/dcerpc.h', header_path= [ ('*gen_ndr*', 'gen_ndr') ], -- 1.9.3 From 3480b809bd9426ce6b976b9965a54de32d246a66 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 5 Jan 2014 07:57:51 +0100 Subject: [PATCH 160/249] s3:rpc_client: fill alloc_hint with the remaining data not the total data. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit f0532fe0cd69aeb161088ca990d376f119102e61) --- source3/rpc_client/cli_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 1cab580..5edd897 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1277,7 +1277,7 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, ZERO_STRUCT(u.request); - u.request.alloc_hint = state->req_data->length; + u.request.alloc_hint = data_left; u.request.context_id = 0; u.request.opnum = state->op_num; -- 1.9.3 From bd675cd6e4848bee8798dacf1768556de48f3112 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 5 Jan 2014 08:12:45 +0100 Subject: [PATCH 161/249] s3:rpc_client: send a dcerpc_sec_verification_trailer if needed Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Tue Jan 7 02:24:42 CET 2014 on sn-devel-104 (cherry picked from commit 6ab9164c74e0ad57bdde8abb568953026b644e27) --- source3/librpc/rpc/dcerpc.h | 1 + source3/rpc_client/cli_pipe.c | 202 ++++++++++++++++++++++++++++++++++++++-- source3/rpc_client/rpc_client.h | 1 + 3 files changed, 194 insertions(+), 10 deletions(-) diff --git a/source3/librpc/rpc/dcerpc.h b/source3/librpc/rpc/dcerpc.h index aaf8d68..9d0f861 100644 --- a/source3/librpc/rpc/dcerpc.h +++ b/source3/librpc/rpc/dcerpc.h @@ -41,6 +41,7 @@ struct pipe_auth_data { enum dcerpc_AuthLevel auth_level; bool client_hdr_signing; bool hdr_signing; + bool verified_bitmask1; void *auth_ctx; diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 5edd897..a45023f 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1166,12 +1166,17 @@ struct rpc_api_pipe_req_state { uint32_t call_id; const DATA_BLOB *req_data; uint32_t req_data_sent; + DATA_BLOB req_trailer; + uint32_t req_trailer_sent; + bool verify_bitmask1; + bool verify_pcontext; DATA_BLOB rpc_out; DATA_BLOB reply_pdu; }; static void rpc_api_pipe_req_write_done(struct tevent_req *subreq); static void rpc_api_pipe_req_done(struct tevent_req *subreq); +static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state); static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, bool *is_last_frag); @@ -1207,6 +1212,11 @@ static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, goto post_status; } + status = prepare_verification_trailer(state); + if (!NT_STATUS_IS_OK(status)) { + goto post_status; + } + status = prepare_next_frag(state, &is_last_frag); if (!NT_STATUS_IS_OK(status)) { goto post_status; @@ -1241,25 +1251,164 @@ static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx, return NULL; } +static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state) +{ + struct pipe_auth_data *a = state->cli->auth; + struct dcerpc_sec_verification_trailer *t; + struct dcerpc_sec_vt *c = NULL; + struct ndr_push *ndr = NULL; + enum ndr_err_code ndr_err; + size_t align = 0; + size_t pad = 0; + + if (a == NULL) { + return NT_STATUS_OK; + } + + if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) { + return NT_STATUS_OK; + } + + t = talloc_zero(state, struct dcerpc_sec_verification_trailer); + if (t == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (!a->verified_bitmask1) { + t->commands = talloc_realloc(t, t->commands, + struct dcerpc_sec_vt, + t->count.count + 1); + if (t->commands == NULL) { + return NT_STATUS_NO_MEMORY; + } + c = &t->commands[t->count.count++]; + ZERO_STRUCTP(c); + + c->command = DCERPC_SEC_VT_COMMAND_BITMASK1; + if (a->client_hdr_signing) { + c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING; + } + state->verify_bitmask1 = true; + } + + if (!state->cli->verified_pcontext) { + t->commands = talloc_realloc(t, t->commands, + struct dcerpc_sec_vt, + t->count.count + 1); + if (t->commands == NULL) { + return NT_STATUS_NO_MEMORY; + } + c = &t->commands[t->count.count++]; + ZERO_STRUCTP(c); + + c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT; + c->u.pcontext.abstract_syntax = state->cli->abstract_syntax; + c->u.pcontext.transfer_syntax = state->cli->transfer_syntax; + + state->verify_pcontext = true; + } + + if (!a->hdr_signing) { + t->commands = talloc_realloc(t, t->commands, + struct dcerpc_sec_vt, + t->count.count + 1); + if (t->commands == NULL) { + return NT_STATUS_NO_MEMORY; + } + c = &t->commands[t->count.count++]; + ZERO_STRUCTP(c); + + c->command = DCERPC_SEC_VT_COMMAND_HEADER2; + c->u.header2.ptype = DCERPC_PKT_REQUEST; + c->u.header2.drep[0] = DCERPC_DREP_LE; + c->u.header2.drep[1] = 0; + c->u.header2.drep[2] = 0; + c->u.header2.drep[3] = 0; + c->u.header2.call_id = state->call_id; + c->u.header2.context_id = 0; + c->u.header2.opnum = state->op_num; + } + + if (t->count.count == 0) { + TALLOC_FREE(t); + return NT_STATUS_OK; + } + + c = &t->commands[t->count.count - 1]; + c->command |= DCERPC_SEC_VT_COMMAND_END; + + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t); + } + + ndr = ndr_push_init_ctx(state); + if (ndr == NULL) { + return NT_STATUS_NO_MEMORY; + } + + ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr, + NDR_SCALARS | NDR_BUFFERS, + t); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return ndr_map_error2ntstatus(ndr_err); + } + state->req_trailer = ndr_push_blob(ndr); + + align = state->req_data->length & 0x3; + if (align > 0) { + pad = 4 - align; + } + if (pad > 0) { + bool ok; + uint8_t *p; + const uint8_t zeros[4] = { 0, }; + + ok = data_blob_append(ndr, &state->req_trailer, zeros, pad); + if (!ok) { + return NT_STATUS_NO_MEMORY; + } + + /* move the padding to the start */ + p = state->req_trailer.data; + memmove(p + pad, p, state->req_trailer.length - pad); + memset(p, 0, pad); + } + + return NT_STATUS_OK; +} + static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, bool *is_last_frag) { - size_t data_sent_thistime; size_t auth_len; size_t frag_len; uint8_t flags = 0; size_t pad_len; size_t data_left; + size_t data_thistime; + size_t trailer_left; + size_t trailer_thistime = 0; + size_t total_left; + size_t total_thistime; NTSTATUS status; + bool ok; union dcerpc_payload u; data_left = state->req_data->length - state->req_data_sent; + trailer_left = state->req_trailer.length - state->req_trailer_sent; + total_left = data_left + trailer_left; + if ((total_left < data_left) || (total_left < trailer_left)) { + /* + * overflow + */ + return NT_STATUS_INVALID_PARAMETER_MIX; + } status = dcerpc_guess_sizes(state->cli->auth, - DCERPC_REQUEST_LENGTH, data_left, + DCERPC_REQUEST_LENGTH, total_left, state->cli->max_xmit_frag, CLIENT_NDR_PADDING_SIZE, - &data_sent_thistime, + &total_thistime, &frag_len, &auth_len, &pad_len); if (!NT_STATUS_IS_OK(status)) { return status; @@ -1269,15 +1418,20 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, flags = DCERPC_PFC_FLAG_FIRST; } - if (data_sent_thistime == data_left) { + if (total_thistime == total_left) { flags |= DCERPC_PFC_FLAG_LAST; } + data_thistime = MIN(total_thistime, data_left); + if (data_thistime < total_thistime) { + trailer_thistime = total_thistime - data_thistime; + } + data_blob_free(&state->rpc_out); ZERO_STRUCT(u.request); - u.request.alloc_hint = data_left; + u.request.alloc_hint = total_left; u.request.context_id = 0; u.request.opnum = state->op_num; @@ -1297,11 +1451,26 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, * at this stage */ dcerpc_set_frag_length(&state->rpc_out, frag_len); - /* Copy in the data. */ - if (!data_blob_append(NULL, &state->rpc_out, + if (data_thistime > 0) { + /* Copy in the data. */ + ok = data_blob_append(NULL, &state->rpc_out, state->req_data->data + state->req_data_sent, - data_sent_thistime)) { - return NT_STATUS_NO_MEMORY; + data_thistime); + if (!ok) { + return NT_STATUS_NO_MEMORY; + } + state->req_data_sent += data_thistime; + } + + if (trailer_thistime > 0) { + /* Copy in the verification trailer. */ + ok = data_blob_append(NULL, &state->rpc_out, + state->req_trailer.data + state->req_trailer_sent, + trailer_thistime); + if (!ok) { + return NT_STATUS_NO_MEMORY; + } + state->req_trailer_sent += trailer_thistime; } switch (state->cli->auth->auth_level) { @@ -1321,7 +1490,6 @@ static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state, return NT_STATUS_INVALID_PARAMETER; } - state->req_data_sent += data_sent_thistime; *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0); return status; @@ -1385,6 +1553,20 @@ static void rpc_api_pipe_req_done(struct tevent_req *subreq) tevent_req_nterror(req, status); return; } + + if (state->cli->auth == NULL) { + tevent_req_done(req); + return; + } + + if (state->verify_bitmask1) { + state->cli->auth->verified_bitmask1 = true; + } + + if (state->verify_pcontext) { + state->cli->verified_pcontext = true; + } + tevent_req_done(req); } diff --git a/source3/rpc_client/rpc_client.h b/source3/rpc_client/rpc_client.h index 6561b28..8024f01 100644 --- a/source3/rpc_client/rpc_client.h +++ b/source3/rpc_client/rpc_client.h @@ -39,6 +39,7 @@ struct rpc_pipe_client { struct ndr_syntax_id abstract_syntax; struct ndr_syntax_id transfer_syntax; + bool verified_pcontext; char *desthost; char *srv_name_slash; -- 1.9.3 From 3df8f8c1dda254a85e4fa02b74d23a4802bc595c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 18 Apr 2013 19:16:42 +0200 Subject: [PATCH 162/249] libcli/auth: add netlogon_creds_cli* infrastructure This provides an abstraction to hide netlogon_creds_CredentialState, which is stored in a node local tdb. Where the global state (netlogon_creds_CredentialState) between client and server was only kept in memory (on the client side), we now use the abstracted netlogon_creds_cli_context. We now use a node specific computer name in order to establish individual netlogon sessions per node. If the caller wants to use some netlogon calls with credential chain (struct netr_Authenticator), netlogon_creds_cli_lock*() is used to get the current netlogon_creds_CredentialState in a g_lock'ed fashion, a talloc_free() will release the lock. The locking is needed as there might be more than one process (multiple winbindd child, cmdline tools) which want to talk to a specific domain controller. The usage of netlogon_creds_CredentialState needs to be serialized as it uses sequence numbers. LogonSamLogonEx doesn't use the credential chain, but for some operations it needs the global session in order to de/encrypt individual fields. It uses the lockless netlogon_creds_cli_get() and netlogon_creds_cli_validate() functions, which just make sure the session hasn't changed between get and validate. This is prepares the proper fix for a large number of bugs: https://bugzilla.samba.org/show_bug.cgi?id=6563 https://bugzilla.samba.org/show_bug.cgi?id=7944 https://bugzilla.samba.org/show_bug.cgi?id=7945 https://bugzilla.samba.org/show_bug.cgi?id=7568 https://bugzilla.samba.org/show_bug.cgi?id=8599 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 6e6d9f9f12284ed06a21cc02080e436b7326065f) --- libcli/auth/netlogon_creds_cli.c | 2596 ++++++++++++++++++++++++++++++++++++++ libcli/auth/netlogon_creds_cli.h | 138 ++ libcli/auth/wscript_build | 4 + 3 files changed, 2738 insertions(+) create mode 100644 libcli/auth/netlogon_creds_cli.c create mode 100644 libcli/auth/netlogon_creds_cli.h diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c new file mode 100644 index 0000000..75d6b2c --- /dev/null +++ b/libcli/auth/netlogon_creds_cli.c @@ -0,0 +1,2596 @@ +/* + Unix SMB/CIFS implementation. + + module to store/fetch session keys for the schannel client + + Copyright (C) Stefan Metzmacher 2013 + + 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 "includes.h" +#include "system/filesys.h" +#include +#include "lib/util/tevent_ntstatus.h" +#include "lib/dbwrap/dbwrap.h" +#include "lib/dbwrap/dbwrap_rbt.h" +#include "lib/util/util_tdb.h" +#include "libcli/security/security.h" +#include "../lib/param/param.h" +#include "../libcli/auth/schannel.h" +#include "../librpc/gen_ndr/ndr_schannel.h" +#include "../librpc/gen_ndr/ndr_netlogon_c.h" +#include "../librpc/gen_ndr/server_id.h" +#include "netlogon_creds_cli.h" +#include "source3/include/messages.h" +#include "source3/include/g_lock.h" + +struct netlogon_creds_cli_locked_state; + +struct netlogon_creds_cli_context { + struct { + const char *computer; + const char *account; + uint32_t proposed_flags; + uint32_t required_flags; + enum netr_SchannelType type; + enum dcerpc_AuthLevel auth_level; + } client; + + struct { + const char *computer; + const char *netbios_domain; + uint32_t cached_flags; + bool try_validation6; + bool try_logon_ex; + bool try_logon_with; + } server; + + struct { + const char *key_name; + TDB_DATA key_data; + struct db_context *ctx; + struct g_lock_ctx *g_ctx; + struct netlogon_creds_cli_locked_state *locked_state; + } db; +}; + +struct netlogon_creds_cli_locked_state { + struct netlogon_creds_cli_context *context; + bool is_glocked; + struct netlogon_creds_CredentialState *creds; +}; + +static int netlogon_creds_cli_locked_state_destructor( + struct netlogon_creds_cli_locked_state *state) +{ + struct netlogon_creds_cli_context *context = state->context; + + if (context == NULL) { + return 0; + } + + if (context->db.locked_state == state) { + context->db.locked_state = NULL; + } + + if (state->is_glocked) { + g_lock_unlock(context->db.g_ctx, + context->db.key_name); + } + + return 0; +} + +static NTSTATUS netlogon_creds_cli_context_common( + const char *client_computer, + const char *client_account, + enum netr_SchannelType type, + enum dcerpc_AuthLevel auth_level, + uint32_t proposed_flags, + uint32_t required_flags, + const char *server_computer, + const char *server_netbios_domain, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_context) +{ + struct netlogon_creds_cli_context *context = NULL; + + *_context = NULL; + + context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); + if (context == NULL) { + return NT_STATUS_NO_MEMORY; + } + + context->client.computer = talloc_strdup(context, client_computer); + if (context->client.computer == NULL) { + talloc_free(context); + return NT_STATUS_NO_MEMORY; + } + + context->client.account = talloc_strdup(context, client_account); + if (context->client.account == NULL) { + talloc_free(context); + return NT_STATUS_NO_MEMORY; + } + + context->client.proposed_flags = proposed_flags; + context->client.required_flags = required_flags; + context->client.type = type; + context->client.auth_level = auth_level; + + context->server.computer = talloc_strdup(context, server_computer); + if (context->server.computer == NULL) { + talloc_free(context); + return NT_STATUS_NO_MEMORY; + } + + context->server.netbios_domain = talloc_strdup(context, server_netbios_domain); + if (context->server.netbios_domain == NULL) { + talloc_free(context); + return NT_STATUS_NO_MEMORY; + } + + context->db.key_name = talloc_asprintf(context, "CLI[%s/%s]/SRV[%s/%s]", + client_computer, + client_account, + server_computer, + server_netbios_domain); + if (context->db.key_name == NULL) { + talloc_free(context); + return NT_STATUS_NO_MEMORY; + } + + context->db.key_data = string_term_tdb_data(context->db.key_name); + + *_context = context; + return NT_STATUS_OK; +} + +static struct db_context *netlogon_creds_cli_global_db; + +NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx) +{ + char *fname; + struct db_context *global_db; + + if (netlogon_creds_cli_global_db != NULL) { + return NT_STATUS_OK; + } + + fname = lpcfg_private_db_path(talloc_autofree_context(), lp_ctx, "netlogon_creds_cli"); + if (fname == NULL) { + return NT_STATUS_NO_MEMORY; + } + + global_db = dbwrap_local_open(talloc_autofree_context(), lp_ctx, + fname, 0, + TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, + O_RDWR|O_CREAT, + 0600, DBWRAP_LOCK_ORDER_2); + if (global_db == NULL) { + DEBUG(0,("netlogon_creds_cli_open_global_db: Failed to open %s - %s\n", + fname, strerror(errno))); + talloc_free(fname); + return NT_STATUS_NO_MEMORY; + } + TALLOC_FREE(fname); + + netlogon_creds_cli_global_db = global_db; + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + struct messaging_context *msg_ctx, + const char *client_account, + enum netr_SchannelType type, + const char *server_computer, + const char *server_netbios_domain, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_context) +{ + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + struct netlogon_creds_cli_context *context = NULL; + const char *client_computer; + uint32_t proposed_flags; + uint32_t required_flags = 0; + bool reject_md5_servers = false; + bool require_strong_key = false; + int require_sign_or_seal = true; + bool seal_secure_channel = true; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + bool neutralize_nt4_emulation = false; + struct server_id self = { + .vnn = NONCLUSTER_VNN, + .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY, + }; + + if (msg_ctx != NULL) { + self = messaging_server_id(msg_ctx); + } + + *_context = NULL; + + if (self.vnn != NONCLUSTER_VNN) { + client_computer = talloc_asprintf(frame, + "%s_cluster_vnn_%u", + lpcfg_netbios_name(lp_ctx), + (unsigned)self.vnn); + if (client_computer == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + } else { + client_computer = lpcfg_netbios_name(lp_ctx); + } + + /* + * allow overwrite per domain + * reject md5 servers: + */ + //TODO: add lpcfp_reject_md5_servers() + reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, + "__default__", + "reject md5 servers", + reject_md5_servers); + reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, + "reject md5 servers", + server_netbios_domain, + reject_md5_servers); + + /* + * allow overwrite per domain + * require strong key: + */ + //TODO: add lpcfp_require_strong_key() + require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, + "__default__", + "require strong key", + require_strong_key); + require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, + "require strong key", + server_netbios_domain, + require_strong_key); + + /* + * allow overwrite per domain + * client schannel: + */ + require_sign_or_seal = lpcfg_client_schannel(lp_ctx); + require_sign_or_seal = lpcfg_parm_int(lp_ctx, NULL, + "client schannel", + server_netbios_domain, + require_sign_or_seal); + + /* + * allow overwrite per domain + * winbind sealed pipes: + */ + seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx); + seal_secure_channel = lpcfg_parm_bool(lp_ctx, NULL, + "winbind sealed pipes", + server_netbios_domain, + seal_secure_channel); + + /* + * allow overwrite per domain + * neutralize nt4 emulation: + */ + //TODO: add lpcfp_neutralize_nt4_emulation() + neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, + "__default__", + "neutralize nt4 emulation", + neutralize_nt4_emulation); + neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, + "neutralize nt4 emulation", + server_netbios_domain, + neutralize_nt4_emulation); + + proposed_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + proposed_flags |= NETLOGON_NEG_SUPPORTS_AES; + + switch (type) { + case SEC_CHAN_WKSTA: + if (lpcfg_security(lp_ctx) == SEC_ADS) { + /* + * AD domains should be secure + */ + required_flags |= NETLOGON_NEG_PASSWORD_SET2; + require_sign_or_seal = true; + require_strong_key = true; + } + break; + + case SEC_CHAN_DOMAIN: + break; + + case SEC_CHAN_DNS_DOMAIN: + /* + * AD domains should be secure + */ + required_flags |= NETLOGON_NEG_PASSWORD_SET2; + require_sign_or_seal = true; + require_strong_key = true; + neutralize_nt4_emulation = true; + break; + + case SEC_CHAN_BDC: + required_flags |= NETLOGON_NEG_PASSWORD_SET2; + require_sign_or_seal = true; + require_strong_key = true; + break; + + case SEC_CHAN_RODC: + required_flags |= NETLOGON_NEG_RODC_PASSTHROUGH; + required_flags |= NETLOGON_NEG_PASSWORD_SET2; + require_sign_or_seal = true; + require_strong_key = true; + neutralize_nt4_emulation = true; + break; + + default: + TALLOC_FREE(frame); + return NT_STATUS_INVALID_PARAMETER; + } + + if (neutralize_nt4_emulation) { + proposed_flags |= NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION; + } + + if (require_sign_or_seal == false) { + proposed_flags &= ~NETLOGON_NEG_AUTHENTICATED_RPC; + } else { + required_flags |= NETLOGON_NEG_ARCFOUR; + required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC; + } + + if (reject_md5_servers) { + required_flags |= NETLOGON_NEG_ARCFOUR; + required_flags |= NETLOGON_NEG_PASSWORD_SET2; + required_flags |= NETLOGON_NEG_SUPPORTS_AES; + required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC; + } + + if (require_strong_key) { + required_flags |= NETLOGON_NEG_ARCFOUR; + required_flags |= NETLOGON_NEG_STRONG_KEYS; + required_flags |= NETLOGON_NEG_AUTHENTICATED_RPC; + } + + proposed_flags |= required_flags; + + if (seal_secure_channel) { + auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + } else { + auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; + } + + status = netlogon_creds_cli_context_common(client_computer, + client_account, + type, + auth_level, + proposed_flags, + required_flags, + server_computer, + server_netbios_domain, + mem_ctx, + &context); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + if (msg_ctx != NULL) { + context->db.g_ctx = g_lock_ctx_init(context, msg_ctx); + if (context->db.g_ctx == NULL) { + TALLOC_FREE(context); + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + } + + if (netlogon_creds_cli_global_db != NULL) { + context->db.ctx = netlogon_creds_cli_global_db; + *_context = context; + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + status = netlogon_creds_cli_open_global_db(lp_ctx); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(context); + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + context->db.ctx = netlogon_creds_cli_global_db; + *_context = context; + TALLOC_FREE(frame); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, + const char *client_account, + enum netr_SchannelType type, + uint32_t proposed_flags, + uint32_t required_flags, + enum dcerpc_AuthLevel auth_level, + const char *server_computer, + const char *server_netbios_domain, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_context) +{ + NTSTATUS status; + struct netlogon_creds_cli_context *context = NULL; + + *_context = NULL; + + status = netlogon_creds_cli_context_common(client_computer, + client_account, + type, + auth_level, + proposed_flags, + required_flags, + server_computer, + server_netbios_domain, + mem_ctx, + &context); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + context->db.ctx = db_open_rbt(context); + if (context->db.ctx == NULL) { + talloc_free(context); + return NT_STATUS_NO_MEMORY; + } + + *_context = context; + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_context_copy( + const struct netlogon_creds_cli_context *src, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_dst) +{ + struct netlogon_creds_cli_context *dst; + + dst = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); + if (dst == NULL) { + return NT_STATUS_NO_MEMORY; + } + + *dst = *src; + + dst->client.computer = talloc_strdup(dst, src->client.computer); + if (dst->client.computer == NULL) { + TALLOC_FREE(dst); + return NT_STATUS_NO_MEMORY; + } + dst->client.account = talloc_strdup(dst, src->client.account); + if (dst->client.account == NULL) { + TALLOC_FREE(dst); + return NT_STATUS_NO_MEMORY; + } + dst->server.computer = talloc_strdup(dst, src->server.computer); + if (dst->server.computer == NULL) { + TALLOC_FREE(dst); + return NT_STATUS_NO_MEMORY; + } + dst->server.netbios_domain = talloc_strdup(dst, src->server.netbios_domain); + if (dst->server.netbios_domain == NULL) { + TALLOC_FREE(dst); + return NT_STATUS_NO_MEMORY; + } + + dst->db.key_name = talloc_strdup(dst, src->db.key_name); + if (dst->db.key_name == NULL) { + TALLOC_FREE(dst); + return NT_STATUS_NO_MEMORY; + } + + dst->db.key_data = string_term_tdb_data(dst->db.key_name); + + *_dst = dst; + return NT_STATUS_OK; +} + +enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( + struct netlogon_creds_cli_context *context) +{ + return context->client.auth_level; +} + +struct netlogon_creds_cli_fetch_state { + TALLOC_CTX *mem_ctx; + struct netlogon_creds_CredentialState *creds; + uint32_t required_flags; + NTSTATUS status; +}; + +static void netlogon_creds_cli_fetch_parser(TDB_DATA key, TDB_DATA data, + void *private_data) +{ + struct netlogon_creds_cli_fetch_state *state = + (struct netlogon_creds_cli_fetch_state *)private_data; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + uint32_t tmp_flags; + + state->creds = talloc_zero(state->mem_ctx, + struct netlogon_creds_CredentialState); + if (state->creds == NULL) { + state->status = NT_STATUS_NO_MEMORY; + return; + } + + blob.data = data.dptr; + blob.length = data.dsize; + + ndr_err = ndr_pull_struct_blob(&blob, state->creds, state->creds, + (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + TALLOC_FREE(state->creds); + state->status = ndr_map_error2ntstatus(ndr_err); + return; + } + + tmp_flags = state->creds->negotiate_flags; + tmp_flags &= state->required_flags; + if (tmp_flags != state->required_flags) { + TALLOC_FREE(state->creds); + state->status = NT_STATUS_DOWNGRADE_DETECTED; + return; + } + + state->status = NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **_creds) +{ + NTSTATUS status; + struct netlogon_creds_cli_fetch_state fstate = { + .mem_ctx = mem_ctx, + .status = NT_STATUS_INTERNAL_ERROR, + .required_flags = context->client.required_flags, + }; + static const struct netr_Credential zero_creds; + + *_creds = NULL; + + status = dbwrap_parse_record(context->db.ctx, + context->db.key_data, + netlogon_creds_cli_fetch_parser, + &fstate); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = fstate.status; + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* + * mark it as invalid for step operations. + */ + fstate.creds->sequence = 0; + fstate.creds->seed = zero_creds; + fstate.creds->client = zero_creds; + fstate.creds->server = zero_creds; + + if (context->server.cached_flags == fstate.creds->negotiate_flags) { + *_creds = fstate.creds; + return NT_STATUS_OK; + } + + /* + * It is really important to try SamLogonEx here, + * because multiple processes can talk to the same + * domain controller, without using the credential + * chain. + * + * With a normal SamLogon call, we must keep the + * credentials chain updated and intact between all + * users of the machine account (which would imply + * cross-node communication for every NTLM logon). + * + * The credentials chain is not per NETLOGON pipe + * connection, but globally on the server/client pair + * by computer name, while the client is free to use + * any computer name. We include the cluster node number + * in our computer name in order to avoid cross node + * coordination of the credential chain. + * + * It's also important to use NetlogonValidationSamInfo4 (6), + * because it relies on the rpc transport encryption + * and avoids using the global netlogon schannel + * session key to en/decrypt secret information + * like the user_session_key for network logons. + * + * [MS-APDS] 3.1.5.2 NTLM Network Logon + * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and + * NETLOGON_NEG_AUTHENTICATED_RPC set together + * are the indication that the server supports + * NetlogonValidationSamInfo4 (6). And it must only + * be used if "SealSecureChannel" is used. + * + * The "SealSecureChannel" AUTH_TYPE_SCHANNEL/AUTH_LEVEL_PRIVACY + * check is done in netlogon_creds_cli_LogonSamLogon*(). + */ + context->server.cached_flags = fstate.creds->negotiate_flags; + context->server.try_validation6 = true; + context->server.try_logon_ex = true; + context->server.try_logon_with = true; + + if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { + context->server.try_validation6 = false; + context->server.try_logon_ex = false; + } + if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { + context->server.try_validation6 = false; + } + + *_creds = fstate.creds; + return NT_STATUS_OK; +} + +bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context, + const struct netlogon_creds_CredentialState *creds1) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct netlogon_creds_CredentialState *creds2; + DATA_BLOB blob1; + DATA_BLOB blob2; + NTSTATUS status; + enum ndr_err_code ndr_err; + int cmp; + + status = netlogon_creds_cli_get(context, frame, &creds2); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return false; + } + + ndr_err = ndr_push_struct_blob(&blob1, frame, creds1, + (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + TALLOC_FREE(frame); + return false; + } + + ndr_err = ndr_push_struct_blob(&blob2, frame, creds2, + (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + TALLOC_FREE(frame); + return false; + } + + if (blob1.length != blob2.length) { + TALLOC_FREE(frame); + return false; + } + + cmp = memcmp(blob1.data, blob2.data, blob1.length); + if (cmp != 0) { + TALLOC_FREE(frame); + return false; + } + + TALLOC_FREE(frame); + return true; +} + +NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context, + struct netlogon_creds_CredentialState **_creds) +{ + struct netlogon_creds_CredentialState *creds = *_creds; + NTSTATUS status; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + TDB_DATA data; + + *_creds = NULL; + + if (context->db.locked_state == NULL) { + /* + * this was not the result of netlogon_creds_cli_lock*() + */ + TALLOC_FREE(creds); + return NT_STATUS_INVALID_PAGE_PROTECTION; + } + + if (context->db.locked_state->creds != creds) { + /* + * this was not the result of netlogon_creds_cli_lock*() + */ + TALLOC_FREE(creds); + return NT_STATUS_INVALID_PAGE_PROTECTION; + } + + ndr_err = ndr_push_struct_blob(&blob, creds, creds, + (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + TALLOC_FREE(creds); + status = ndr_map_error2ntstatus(ndr_err); + return status; + } + + data.dptr = blob.data; + data.dsize = blob.length; + + status = dbwrap_store(context->db.ctx, + context->db.key_data, + data, TDB_REPLACE); + TALLOC_FREE(creds); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context, + struct netlogon_creds_CredentialState **_creds) +{ + struct netlogon_creds_CredentialState *creds = *_creds; + NTSTATUS status; + + *_creds = NULL; + + if (context->db.locked_state == NULL) { + /* + * this was not the result of netlogon_creds_cli_lock*() + */ + TALLOC_FREE(creds); + return NT_STATUS_INVALID_PAGE_PROTECTION; + } + + if (context->db.locked_state->creds != creds) { + /* + * this was not the result of netlogon_creds_cli_lock*() + */ + TALLOC_FREE(creds); + return NT_STATUS_INVALID_PAGE_PROTECTION; + } + + status = dbwrap_delete(context->db.ctx, + context->db.key_data); + TALLOC_FREE(creds); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + +struct netlogon_creds_cli_lock_state { + struct netlogon_creds_cli_locked_state *locked_state; + struct netlogon_creds_CredentialState *creds; +}; + +static void netlogon_creds_cli_lock_done(struct tevent_req *subreq); +static void netlogon_creds_cli_lock_fetch(struct tevent_req *req); + +struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context) +{ + struct tevent_req *req; + struct netlogon_creds_cli_lock_state *state; + struct netlogon_creds_cli_locked_state *locked_state; + struct tevent_req *subreq; + + req = tevent_req_create(mem_ctx, &state, + struct netlogon_creds_cli_lock_state); + if (req == NULL) { + return NULL; + } + + if (context->db.locked_state != NULL) { + tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED); + return tevent_req_post(req, ev); + } + + locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state); + if (tevent_req_nomem(locked_state, req)) { + return tevent_req_post(req, ev); + } + talloc_set_destructor(locked_state, + netlogon_creds_cli_locked_state_destructor); + locked_state->context = context; + + context->db.locked_state = locked_state; + state->locked_state = locked_state; + + if (context->db.g_ctx == NULL) { + netlogon_creds_cli_lock_fetch(req); + if (!tevent_req_is_in_progress(req)) { + return tevent_req_post(req, ev); + } + + return req; + } + + subreq = g_lock_lock_send(state, ev, + context->db.g_ctx, + context->db.key_name, + G_LOCK_WRITE); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, netlogon_creds_cli_lock_done, req); + + return req; +} + +static void netlogon_creds_cli_lock_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_lock_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_lock_state); + NTSTATUS status; + + status = g_lock_lock_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + state->locked_state->is_glocked = true; + + netlogon_creds_cli_lock_fetch(req); +} + +static void netlogon_creds_cli_lock_fetch(struct tevent_req *req) +{ + struct netlogon_creds_cli_lock_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_lock_state); + struct netlogon_creds_cli_context *context = state->locked_state->context; + struct netlogon_creds_cli_fetch_state fstate = { + .status = NT_STATUS_INTERNAL_ERROR, + .required_flags = context->client.required_flags, + }; + NTSTATUS status; + + fstate.mem_ctx = state; + status = dbwrap_parse_record(context->db.ctx, + context->db.key_data, + netlogon_creds_cli_fetch_parser, + &fstate); + if (tevent_req_nterror(req, status)) { + return; + } + status = fstate.status; + if (tevent_req_nterror(req, status)) { + return; + } + + if (context->server.cached_flags == fstate.creds->negotiate_flags) { + state->creds = fstate.creds; + tevent_req_done(req); + return; + } + + context->server.cached_flags = fstate.creds->negotiate_flags; + context->server.try_validation6 = true; + context->server.try_logon_ex = true; + context->server.try_logon_with = true; + + if (!(context->server.cached_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { + context->server.try_validation6 = false; + context->server.try_logon_ex = false; + } + if (!(context->server.cached_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { + context->server.try_validation6 = false; + } + + state->creds = fstate.creds; + tevent_req_done(req); + return; +} + +NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **creds) +{ + struct netlogon_creds_cli_lock_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_lock_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + + talloc_steal(state->creds, state->locked_state); + state->locked_state->creds = state->creds; + *creds = talloc_move(mem_ctx, &state->creds); + tevent_req_received(req); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **creds) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = netlogon_creds_cli_lock_send(frame, ev, context); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = netlogon_creds_cli_lock_recv(req, mem_ctx, creds); + fail: + TALLOC_FREE(frame); + return status; +} + +struct netlogon_creds_cli_auth_state { + struct tevent_context *ev; + struct netlogon_creds_cli_context *context; + struct dcerpc_binding_handle *binding_handle; + struct samr_Password current_nt_hash; + struct samr_Password previous_nt_hash; + struct samr_Password used_nt_hash; + char *srv_name_slash; + uint32_t current_flags; + struct netr_Credential client_challenge; + struct netr_Credential server_challenge; + struct netlogon_creds_CredentialState *creds; + struct netr_Credential client_credential; + struct netr_Credential server_credential; + uint32_t rid; + bool try_auth3; + bool try_auth2; + bool require_auth2; + bool try_previous_nt_hash; + struct netlogon_creds_cli_locked_state *locked_state; +}; + +static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq); +static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req); + +struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + struct samr_Password current_nt_hash, + const struct samr_Password *previous_nt_hash) +{ + struct tevent_req *req; + struct netlogon_creds_cli_auth_state *state; + struct netlogon_creds_cli_locked_state *locked_state; + NTSTATUS status; + + req = tevent_req_create(mem_ctx, &state, + struct netlogon_creds_cli_auth_state); + if (req == NULL) { + return NULL; + } + + state->ev = ev; + state->context = context; + state->binding_handle = b; + state->current_nt_hash = current_nt_hash; + if (previous_nt_hash != NULL) { + state->previous_nt_hash = *previous_nt_hash; + state->try_previous_nt_hash = true; + } + + if (context->db.locked_state != NULL) { + tevent_req_nterror(req, NT_STATUS_LOCK_NOT_GRANTED); + return tevent_req_post(req, ev); + } + + locked_state = talloc_zero(state, struct netlogon_creds_cli_locked_state); + if (tevent_req_nomem(locked_state, req)) { + return tevent_req_post(req, ev); + } + talloc_set_destructor(locked_state, + netlogon_creds_cli_locked_state_destructor); + locked_state->context = context; + + context->db.locked_state = locked_state; + state->locked_state = locked_state; + + state->srv_name_slash = talloc_asprintf(state, "\\\\%s", + context->server.computer); + if (tevent_req_nomem(state->srv_name_slash, req)) { + return tevent_req_post(req, ev); + } + + state->try_auth3 = true; + state->try_auth2 = true; + + if (context->client.required_flags != 0) { + state->require_auth2 = true; + } + + state->used_nt_hash = state->current_nt_hash; + state->current_flags = context->client.proposed_flags; + + if (context->db.g_ctx != NULL) { + struct tevent_req *subreq; + + subreq = g_lock_lock_send(state, ev, + context->db.g_ctx, + context->db.key_name, + G_LOCK_WRITE); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, + netlogon_creds_cli_auth_locked, + req); + + return req; + } + + status = dbwrap_delete(state->context->db.ctx, + state->context->db.key_data); + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { + status = NT_STATUS_OK; + } + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + netlogon_creds_cli_auth_challenge_start(req); + if (!tevent_req_is_in_progress(req)) { + return tevent_req_post(req, ev); + } + + return req; +} + +static void netlogon_creds_cli_auth_locked(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_auth_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_auth_state); + NTSTATUS status; + + status = g_lock_lock_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + state->locked_state->is_glocked = true; + + status = dbwrap_delete(state->context->db.ctx, + state->context->db.key_data); + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { + status = NT_STATUS_OK; + } + if (tevent_req_nterror(req, status)) { + return; + } + + netlogon_creds_cli_auth_challenge_start(req); +} + +static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq); + +static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req) +{ + struct netlogon_creds_cli_auth_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_auth_state); + struct tevent_req *subreq; + + TALLOC_FREE(state->creds); + + generate_random_buffer(state->client_challenge.data, + sizeof(state->client_challenge.data)); + + subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.computer, + &state->client_challenge, + &state->server_challenge); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, + netlogon_creds_cli_auth_challenge_done, + req); +} + +static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq); + +static void netlogon_creds_cli_auth_challenge_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_auth_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_auth_state); + NTSTATUS status; + NTSTATUS result; + + status = dcerpc_netr_ServerReqChallenge_recv(subreq, state, &result); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + if (tevent_req_nterror(req, result)) { + return; + } + + if (!state->try_auth3 && !state->try_auth2) { + state->current_flags = 0; + } + + /* Calculate the session key and client credentials */ + + state->creds = netlogon_creds_client_init(state, + state->context->client.account, + state->context->client.computer, + state->context->client.type, + &state->client_challenge, + &state->server_challenge, + &state->used_nt_hash, + &state->client_credential, + state->current_flags); + if (tevent_req_nomem(state->creds, req)) { + return; + } + + if (state->try_auth3) { + subreq = dcerpc_netr_ServerAuthenticate3_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.account, + state->context->client.type, + state->context->client.computer, + &state->client_credential, + &state->server_credential, + &state->creds->negotiate_flags, + &state->rid); + if (tevent_req_nomem(subreq, req)) { + return; + } + } else if (state->try_auth2) { + state->rid = 0; + + subreq = dcerpc_netr_ServerAuthenticate2_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.account, + state->context->client.type, + state->context->client.computer, + &state->client_credential, + &state->server_credential, + &state->creds->negotiate_flags); + if (tevent_req_nomem(subreq, req)) { + return; + } + } else { + state->rid = 0; + + subreq = dcerpc_netr_ServerAuthenticate_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.account, + state->context->client.type, + state->context->client.computer, + &state->client_credential, + &state->server_credential); + if (tevent_req_nomem(subreq, req)) { + return; + } + } + tevent_req_set_callback(subreq, + netlogon_creds_cli_auth_srvauth_done, + req); +} + +static void netlogon_creds_cli_auth_srvauth_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_auth_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_auth_state); + NTSTATUS status; + NTSTATUS result; + bool ok; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + TDB_DATA data; + uint32_t tmp_flags; + + if (state->try_auth3) { + status = dcerpc_netr_ServerAuthenticate3_recv(subreq, state, + &result); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + state->try_auth3 = false; + netlogon_creds_cli_auth_challenge_start(req); + return; + } + if (tevent_req_nterror(req, status)) { + return; + } + } else if (state->try_auth2) { + status = dcerpc_netr_ServerAuthenticate2_recv(subreq, state, + &result); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + state->try_auth2 = false; + if (state->require_auth2) { + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + return; + } + netlogon_creds_cli_auth_challenge_start(req); + return; + } + if (tevent_req_nterror(req, status)) { + return; + } + } else { + status = dcerpc_netr_ServerAuthenticate_recv(subreq, state, + &result); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + } + + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) + { + tevent_req_nterror(req, result); + return; + } + + tmp_flags = state->creds->negotiate_flags; + tmp_flags &= state->context->client.required_flags; + if (tmp_flags != state->context->client.required_flags) { + if (NT_STATUS_IS_OK(result)) { + tevent_req_nterror(req, NT_STATUS_DOWNGRADE_DETECTED); + return; + } + tevent_req_nterror(req, result); + return; + } + + if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) { + + tmp_flags = state->context->client.proposed_flags; + if ((state->current_flags == tmp_flags) && + (state->creds->negotiate_flags != tmp_flags)) + { + /* + * lets retry with the negotiated flags + */ + state->current_flags = state->creds->negotiate_flags; + netlogon_creds_cli_auth_challenge_start(req); + return; + } + + if (!state->try_previous_nt_hash) { + /* + * we already retried, giving up... + */ + tevent_req_nterror(req, result); + return; + } + + /* + * lets retry with the old nt hash. + */ + state->try_previous_nt_hash = false; + state->used_nt_hash = state->previous_nt_hash; + state->current_flags = state->context->client.proposed_flags; + netlogon_creds_cli_auth_challenge_start(req); + return; + } + + ok = netlogon_creds_client_check(state->creds, + &state->server_credential); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); + return; + } + + ndr_err = ndr_push_struct_blob(&blob, state, state->creds, + (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + tevent_req_nterror(req, status); + return; + } + + data.dptr = blob.data; + data.dsize = blob.length; + + status = dbwrap_store(state->context->db.ctx, + state->context->db.key_data, + data, TDB_REPLACE); + TALLOC_FREE(state->locked_state); + if (tevent_req_nterror(req, status)) { + return; + } + + tevent_req_done(req); +} + +NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + tevent_req_received(req); + return status; + } + + tevent_req_received(req); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + struct samr_Password current_nt_hash, + const struct samr_Password *previous_nt_hash) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = netlogon_creds_cli_auth_send(frame, ev, context, b, + current_nt_hash, + previous_nt_hash); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = netlogon_creds_cli_auth_recv(req); + fail: + TALLOC_FREE(frame); + return status; +} + +struct netlogon_creds_cli_check_state { + struct tevent_context *ev; + struct netlogon_creds_cli_context *context; + struct dcerpc_binding_handle *binding_handle; + + char *srv_name_slash; + + union netr_Capabilities caps; + + struct netlogon_creds_CredentialState *creds; + struct netlogon_creds_CredentialState tmp_creds; + struct netr_Authenticator req_auth; + struct netr_Authenticator rep_auth; +}; + +static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, + NTSTATUS status); +static void netlogon_creds_cli_check_locked(struct tevent_req *subreq); + +struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b) +{ + struct tevent_req *req; + struct netlogon_creds_cli_check_state *state; + struct tevent_req *subreq; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + + req = tevent_req_create(mem_ctx, &state, + struct netlogon_creds_cli_check_state); + if (req == NULL) { + return NULL; + } + + state->ev = ev; + state->context = context; + state->binding_handle = b; + + state->srv_name_slash = talloc_asprintf(state, "\\\\%s", + context->server.computer); + if (tevent_req_nomem(state->srv_name_slash, req)) { + return tevent_req_post(req, ev); + } + + dcerpc_binding_handle_auth_info(state->binding_handle, + &auth_type, &auth_level); + + if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return tevent_req_post(req, ev); + } + + switch (auth_level) { + case DCERPC_AUTH_LEVEL_INTEGRITY: + case DCERPC_AUTH_LEVEL_PRIVACY: + break; + default: + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return tevent_req_post(req, ev); + } + + subreq = netlogon_creds_cli_lock_send(state, state->ev, + state->context); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + + tevent_req_set_callback(subreq, + netlogon_creds_cli_check_locked, + req); + + return req; +} + +static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, + NTSTATUS status) +{ + struct netlogon_creds_cli_check_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_check_state); + + if (state->creds == NULL) { + return; + } + + if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) && + !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) && + !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) && + !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && + !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { + TALLOC_FREE(state->creds); + return; + } + + netlogon_creds_cli_delete(state->context, &state->creds); +} + +static void netlogon_creds_cli_check_caps(struct tevent_req *subreq); + +static void netlogon_creds_cli_check_locked(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_check_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_check_state); + NTSTATUS status; + + status = netlogon_creds_cli_lock_recv(subreq, state, + &state->creds); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + /* + * we defer all callbacks in order to cleanup + * the database record. + */ + tevent_req_defer_callback(req, state->ev); + + state->tmp_creds = *state->creds; + netlogon_creds_client_authenticator(&state->tmp_creds, + &state->req_auth); + ZERO_STRUCT(state->rep_auth); + + subreq = dcerpc_netr_LogonGetCapabilities_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.computer, + &state->req_auth, + &state->rep_auth, + 1, + &state->caps); + if (tevent_req_nomem(subreq, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_check_cleanup(req, status); + return; + } + tevent_req_set_callback(subreq, + netlogon_creds_cli_check_caps, + req); +} + +static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_check_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_check_state); + NTSTATUS status; + NTSTATUS result; + bool ok; + + status = dcerpc_netr_LogonGetCapabilities_recv(subreq, state, + &result); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + /* + * Note that the negotiated flags are already checked + * for our required flags after the ServerAuthenticate3/2 call. + */ + uint32_t negotiated = state->tmp_creds.negotiate_flags; + + if (negotiated & NETLOGON_NEG_SUPPORTS_AES) { + /* + * If we have negotiated NETLOGON_NEG_SUPPORTS_AES + * already, we expect this to work! + */ + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + if (negotiated & NETLOGON_NEG_STRONG_KEYS) { + /* + * If we have negotiated NETLOGON_NEG_STRONG_KEYS + * we expect this to work at least as far as the + * NOT_SUPPORTED error handled below! + * + * NT 4.0 and Old Samba servers are not + * allowed without "require strong key = no" + */ + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + /* + * If we not require NETLOGON_NEG_SUPPORTS_AES or + * NETLOGON_NEG_STRONG_KEYS, it's ok to ignore + * NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. + * + * This is needed against NT 4.0 and old Samba servers. + * + * As we're using DCERPC_AUTH_TYPE_SCHANNEL with + * DCERPC_AUTH_LEVEL_INTEGRITY or DCERPC_AUTH_LEVEL_PRIVACY + * we should detect a faked NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE + * with the next request as the sequence number processing + * gets out of sync. + */ + netlogon_creds_cli_check_cleanup(req, result); + tevent_req_done(req); + return; + } + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { + /* + * Note that the negotiated flags are already checked + * for our required flags after the ServerAuthenticate3/2 call. + */ + uint32_t negotiated = state->tmp_creds.negotiate_flags; + + if (negotiated & NETLOGON_NEG_SUPPORTS_AES) { + /* + * If we have negotiated NETLOGON_NEG_SUPPORTS_AES + * already, we expect this to work! + */ + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + /* + * This is ok, the server does not support + * NETLOGON_NEG_SUPPORTS_AES. + * + * netr_LogonGetCapabilities() was + * netr_LogonDummyRoutine1() before + * NETLOGON_NEG_SUPPORTS_AES was invented. + */ + netlogon_creds_cli_check_cleanup(req, result); + tevent_req_done(req); + return; + } + + ok = netlogon_creds_client_check(&state->tmp_creds, + &state->rep_auth.cred); + if (!ok) { + status = NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + if (tevent_req_nterror(req, result)) { + netlogon_creds_cli_check_cleanup(req, result); + return; + } + + if (state->caps.server_capabilities != state->tmp_creds.negotiate_flags) { + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + /* + * This is the key check that makes this check secure. If we + * get OK here (rather than NOT_SUPPORTED), then the server + * did support AES. If the server only proposed STRONG_KEYS + * and not AES, then it should have failed with + * NOT_IMPLEMENTED. We always send AES as a client, so the + * server should always have returned it. + */ + if (!(state->caps.server_capabilities & NETLOGON_NEG_SUPPORTS_AES)) { + status = NT_STATUS_DOWNGRADE_DETECTED; + tevent_req_nterror(req, status); + netlogon_creds_cli_check_cleanup(req, status); + return; + } + + *state->creds = state->tmp_creds; + status = netlogon_creds_cli_store(state->context, + &state->creds); + netlogon_creds_cli_check_cleanup(req, status); + if (tevent_req_nterror(req, status)) { + return; + } + + tevent_req_done(req); +} + +NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + netlogon_creds_cli_check_cleanup(req, status); + tevent_req_received(req); + return status; + } + + tevent_req_received(req); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = netlogon_creds_cli_check_send(frame, ev, context, b); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = netlogon_creds_cli_check_recv(req); + fail: + TALLOC_FREE(frame); + return status; +} + +struct netlogon_creds_cli_ServerPasswordSet_state { + struct tevent_context *ev; + struct netlogon_creds_cli_context *context; + struct dcerpc_binding_handle *binding_handle; + uint32_t old_timeout; + + char *srv_name_slash; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + + struct samr_CryptPassword samr_crypt_password; + struct netr_CryptPassword netr_crypt_password; + struct samr_Password samr_password; + + struct netlogon_creds_CredentialState *creds; + struct netlogon_creds_CredentialState tmp_creds; + struct netr_Authenticator req_auth; + struct netr_Authenticator rep_auth; +}; + +static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req, + NTSTATUS status); +static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq); + +struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + const char *new_password, + const uint32_t *new_version) +{ + struct tevent_req *req; + struct netlogon_creds_cli_ServerPasswordSet_state *state; + struct tevent_req *subreq; + bool ok; + + req = tevent_req_create(mem_ctx, &state, + struct netlogon_creds_cli_ServerPasswordSet_state); + if (req == NULL) { + return NULL; + } + + state->ev = ev; + state->context = context; + state->binding_handle = b; + + /* + * netr_ServerPasswordSet + */ + E_md4hash(new_password, state->samr_password.hash); + + /* + * netr_ServerPasswordSet2 + */ + ok = encode_pw_buffer(state->samr_crypt_password.data, + new_password, STR_UNICODE); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return tevent_req_post(req, ev); + } + + if (new_version != NULL) { + struct NL_PASSWORD_VERSION version; + uint32_t len = IVAL(state->samr_crypt_password.data, 512); + uint32_t ofs = 512 - len; + uint8_t *p; + + if (ofs < 12) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return tevent_req_post(req, ev); + } + ofs -= 12; + + version.ReservedField = 0; + version.PasswordVersionNumber = *new_version; + version.PasswordVersionPresent = + NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT; + + p = state->samr_crypt_password.data + ofs; + SIVAL(p, 0, version.ReservedField); + SIVAL(p, 4, version.PasswordVersionNumber); + SIVAL(p, 8, version.PasswordVersionPresent); + } + + state->srv_name_slash = talloc_asprintf(state, "\\\\%s", + context->server.computer); + if (tevent_req_nomem(state->srv_name_slash, req)) { + return tevent_req_post(req, ev); + } + + dcerpc_binding_handle_auth_info(state->binding_handle, + &state->auth_type, + &state->auth_level); + + subreq = netlogon_creds_cli_lock_send(state, state->ev, + state->context); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + + tevent_req_set_callback(subreq, + netlogon_creds_cli_ServerPasswordSet_locked, + req); + + return req; +} + +static void netlogon_creds_cli_ServerPasswordSet_cleanup(struct tevent_req *req, + NTSTATUS status) +{ + struct netlogon_creds_cli_ServerPasswordSet_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_ServerPasswordSet_state); + + if (state->creds == NULL) { + return; + } + + dcerpc_binding_handle_set_timeout(state->binding_handle, + state->old_timeout); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) && + !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) && + !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) && + !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && + !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { + TALLOC_FREE(state->creds); + return; + } + + netlogon_creds_cli_delete(state->context, &state->creds); +} + +static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq); + +static void netlogon_creds_cli_ServerPasswordSet_locked(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_ServerPasswordSet_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_ServerPasswordSet_state); + NTSTATUS status; + + status = netlogon_creds_cli_lock_recv(subreq, state, + &state->creds); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + switch (state->auth_level) { + case DCERPC_AUTH_LEVEL_INTEGRITY: + case DCERPC_AUTH_LEVEL_PRIVACY: + break; + default: + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return; + } + } else { + uint32_t tmp = state->creds->negotiate_flags; + + if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) { + /* + * if DCERPC_AUTH_TYPE_SCHANNEL is supported + * it should be used, which means + * we had a chance to verify no downgrade + * happened. + * + * This relies on netlogon_creds_cli_check* + * being called before, as first request after + * the DCERPC bind. + */ + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); + return; + } + } + + state->old_timeout = dcerpc_binding_handle_set_timeout( + state->binding_handle, 600000); + + /* + * we defer all callbacks in order to cleanup + * the database record. + */ + tevent_req_defer_callback(req, state->ev); + + state->tmp_creds = *state->creds; + netlogon_creds_client_authenticator(&state->tmp_creds, + &state->req_auth); + ZERO_STRUCT(state->rep_auth); + + if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { + + if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + netlogon_creds_aes_encrypt(&state->tmp_creds, + state->samr_crypt_password.data, + 516); + } else { + netlogon_creds_arcfour_crypt(&state->tmp_creds, + state->samr_crypt_password.data, + 516); + } + + memcpy(state->netr_crypt_password.data, + state->samr_crypt_password.data, 512); + state->netr_crypt_password.length = + IVAL(state->samr_crypt_password.data, 512); + + subreq = dcerpc_netr_ServerPasswordSet2_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->tmp_creds.account_name, + state->tmp_creds.secure_channel_type, + state->tmp_creds.computer_name, + &state->req_auth, + &state->rep_auth, + &state->netr_crypt_password); + if (tevent_req_nomem(subreq, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + return; + } + } else { + netlogon_creds_des_encrypt(&state->tmp_creds, + &state->samr_password); + + subreq = dcerpc_netr_ServerPasswordSet_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->tmp_creds.account_name, + state->tmp_creds.secure_channel_type, + state->tmp_creds.computer_name, + &state->req_auth, + &state->rep_auth, + &state->samr_password); + if (tevent_req_nomem(subreq, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + return; + } + } + + tevent_req_set_callback(subreq, + netlogon_creds_cli_ServerPasswordSet_done, + req); +} + +static void netlogon_creds_cli_ServerPasswordSet_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_ServerPasswordSet_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_ServerPasswordSet_state); + NTSTATUS status; + NTSTATUS result; + bool ok; + + if (state->tmp_creds.negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { + status = dcerpc_netr_ServerPasswordSet2_recv(subreq, state, + &result); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + return; + } + } else { + status = dcerpc_netr_ServerPasswordSet_recv(subreq, state, + &result); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + return; + } + } + + ok = netlogon_creds_client_check(&state->tmp_creds, + &state->rep_auth.cred); + if (!ok) { + status = NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, status); + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + return; + } + + if (tevent_req_nterror(req, result)) { + netlogon_creds_cli_ServerPasswordSet_cleanup(req, result); + return; + } + + dcerpc_binding_handle_set_timeout(state->binding_handle, + state->old_timeout); + + *state->creds = state->tmp_creds; + status = netlogon_creds_cli_store(state->context, + &state->creds); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + return; + } + + tevent_req_done(req); +} + +NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + netlogon_creds_cli_ServerPasswordSet_cleanup(req, status); + tevent_req_received(req); + return status; + } + + tevent_req_received(req); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_ServerPasswordSet( + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + const char *new_password, + const uint32_t *new_version) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = netlogon_creds_cli_ServerPasswordSet_send(frame, ev, context, b, + new_password, + new_version); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = netlogon_creds_cli_ServerPasswordSet_recv(req); + fail: + TALLOC_FREE(frame); + return status; +} + +struct netlogon_creds_cli_LogonSamLogon_state { + struct tevent_context *ev; + struct netlogon_creds_cli_context *context; + struct dcerpc_binding_handle *binding_handle; + + char *srv_name_slash; + + enum netr_LogonInfoClass logon_level; + const union netr_LogonLevel *const_logon; + union netr_LogonLevel *logon; + uint32_t flags; + + uint16_t validation_level; + union netr_Validation *validation; + uint8_t authoritative; + + /* + * do we need encryption at the application layer? + */ + bool user_encrypt; + bool try_logon_ex; + bool try_validation6; + + /* + * the read only credentials before we started the operation + */ + struct netlogon_creds_CredentialState *ro_creds; + + struct netlogon_creds_CredentialState *lk_creds; + + struct netlogon_creds_CredentialState tmp_creds; + struct netr_Authenticator req_auth; + struct netr_Authenticator rep_auth; +}; + +static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req); +static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req, + NTSTATUS status); + +struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + enum netr_LogonInfoClass logon_level, + const union netr_LogonLevel *logon, + uint32_t flags) +{ + struct tevent_req *req; + struct netlogon_creds_cli_LogonSamLogon_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct netlogon_creds_cli_LogonSamLogon_state); + if (req == NULL) { + return NULL; + } + + state->ev = ev; + state->context = context; + state->binding_handle = b; + + state->logon_level = logon_level; + state->const_logon = logon; + state->flags = flags; + + state->srv_name_slash = talloc_asprintf(state, "\\\\%s", + context->server.computer); + if (tevent_req_nomem(state->srv_name_slash, req)) { + return tevent_req_post(req, ev); + } + + switch (logon_level) { + case NetlogonInteractiveInformation: + case NetlogonInteractiveTransitiveInformation: + case NetlogonServiceInformation: + case NetlogonServiceTransitiveInformation: + case NetlogonGenericInformation: + state->user_encrypt = true; + break; + + case NetlogonNetworkInformation: + case NetlogonNetworkTransitiveInformation: + break; + } + + state->validation = talloc_zero(state, union netr_Validation); + if (tevent_req_nomem(state->validation, req)) { + return tevent_req_post(req, ev); + } + + netlogon_creds_cli_LogonSamLogon_start(req); + if (!tevent_req_is_in_progress(req)) { + return tevent_req_post(req, ev); + } + + /* + * we defer all callbacks in order to cleanup + * the database record. + */ + tevent_req_defer_callback(req, state->ev); + return req; +} + +static void netlogon_creds_cli_LogonSamLogon_cleanup(struct tevent_req *req, + NTSTATUS status) +{ + struct netlogon_creds_cli_LogonSamLogon_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_LogonSamLogon_state); + + if (state->lk_creds == NULL) { + return; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + /* + * This is a hack to recover from a bug in old + * Samba servers, when LogonSamLogonEx() fails: + * + * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX. + * + * All following request will get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. + * + * A second bug generates NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE, + * instead of NT_STATUS_ACCESS_DENIED or NT_STATUS_RPC_SEC_PKG_ERROR + * If the sign/seal check fails. + * + * In that case we need to cleanup the netlogon session. + * + * It's the job of the caller to disconnect the current + * connection, if netlogon_creds_cli_LogonSamLogon() + * returns NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. + */ + if (!state->context->server.try_logon_with) { + status = NT_STATUS_NETWORK_ACCESS_DENIED; + } + } + + if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) && + !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) && + !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) && + !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && + !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) { + TALLOC_FREE(state->lk_creds); + return; + } + + netlogon_creds_cli_delete(state->context, &state->lk_creds); +} + +static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq); + +static void netlogon_creds_cli_LogonSamLogon_start(struct tevent_req *req) +{ + struct netlogon_creds_cli_LogonSamLogon_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_LogonSamLogon_state); + struct tevent_req *subreq; + NTSTATUS status; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + + TALLOC_FREE(state->ro_creds); + TALLOC_FREE(state->logon); + ZERO_STRUCTP(state->validation); + + dcerpc_binding_handle_auth_info(state->binding_handle, + &auth_type, &auth_level); + + state->try_logon_ex = state->context->server.try_logon_ex; + state->try_validation6 = state->context->server.try_validation6; + + if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { + state->try_logon_ex = false; + } + + if (auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { + state->try_validation6 = false; + } + + if (state->try_logon_ex) { + if (state->try_validation6) { + state->validation_level = 6; + } else { + state->validation_level = 3; + state->user_encrypt = true; + } + + state->logon = netlogon_creds_shallow_copy_logon(state, + state->logon_level, + state->const_logon); + if (tevent_req_nomem(state->logon, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + + if (state->user_encrypt) { + status = netlogon_creds_cli_get(state->context, + state, + &state->ro_creds); + if (!NT_STATUS_IS_OK(status)) { + status = NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, status); + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + + netlogon_creds_encrypt_samlogon_logon(state->ro_creds, + state->logon_level, + state->logon); + } + + subreq = dcerpc_netr_LogonSamLogonEx_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.computer, + state->logon_level, + state->logon, + state->validation_level, + state->validation, + &state->authoritative, + &state->flags); + if (tevent_req_nomem(subreq, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + tevent_req_set_callback(subreq, + netlogon_creds_cli_LogonSamLogon_done, + req); + return; + } + + if (state->lk_creds == NULL) { + subreq = netlogon_creds_cli_lock_send(state, state->ev, + state->context); + if (tevent_req_nomem(subreq, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + tevent_req_set_callback(subreq, + netlogon_creds_cli_LogonSamLogon_done, + req); + return; + } + + state->tmp_creds = *state->lk_creds; + netlogon_creds_client_authenticator(&state->tmp_creds, + &state->req_auth); + ZERO_STRUCT(state->rep_auth); + + state->logon = netlogon_creds_shallow_copy_logon(state, + state->logon_level, + state->const_logon); + if (tevent_req_nomem(state->logon, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + + netlogon_creds_encrypt_samlogon_logon(state->ro_creds, + state->logon_level, + state->logon); + + state->validation_level = 3; + + if (state->context->server.try_logon_with) { + subreq = dcerpc_netr_LogonSamLogonWithFlags_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.computer, + &state->req_auth, + &state->rep_auth, + state->logon_level, + state->logon, + state->validation_level, + state->validation, + &state->authoritative, + &state->flags); + if (tevent_req_nomem(subreq, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + } else { + state->flags = 0; + + subreq = dcerpc_netr_LogonSamLogon_send(state, state->ev, + state->binding_handle, + state->srv_name_slash, + state->context->client.computer, + &state->req_auth, + &state->rep_auth, + state->logon_level, + state->logon, + state->validation_level, + state->validation, + &state->authoritative); + if (tevent_req_nomem(subreq, req)) { + status = NT_STATUS_NO_MEMORY; + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + } + + tevent_req_set_callback(subreq, + netlogon_creds_cli_LogonSamLogon_done, + req); +} + +static void netlogon_creds_cli_LogonSamLogon_done(struct tevent_req *subreq) +{ + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_creds_cli_LogonSamLogon_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_LogonSamLogon_state); + NTSTATUS status; + NTSTATUS result; + bool ok; + + if (state->try_logon_ex) { + status = dcerpc_netr_LogonSamLogonEx_recv(subreq, + state->validation, + &result); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + state->context->server.try_validation6 = false; + state->context->server.try_logon_ex = false; + netlogon_creds_cli_LogonSamLogon_start(req); + return; + } + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + + if ((state->validation_level == 6) && + (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) || + NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) || + NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) + { + state->context->server.try_validation6 = false; + netlogon_creds_cli_LogonSamLogon_start(req); + return; + } + + if (tevent_req_nterror(req, result)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, result); + return; + } + + if (state->ro_creds == NULL) { + tevent_req_done(req); + return; + } + + ok = netlogon_creds_cli_validate(state->context, state->ro_creds); + if (!ok) { + /* + * We got a race, lets retry with on authenticator + * protection. + */ + TALLOC_FREE(state->ro_creds); + state->try_logon_ex = false; + netlogon_creds_cli_LogonSamLogon_start(req); + return; + } + + netlogon_creds_decrypt_samlogon_validation(state->ro_creds, + state->validation_level, + state->validation); + + tevent_req_done(req); + return; + } + + if (state->lk_creds == NULL) { + status = netlogon_creds_cli_lock_recv(subreq, state, + &state->lk_creds); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + + netlogon_creds_cli_LogonSamLogon_start(req); + return; + } + + if (state->context->server.try_logon_with) { + status = dcerpc_netr_LogonSamLogonWithFlags_recv(subreq, + state->validation, + &result); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + state->context->server.try_logon_with = false; + netlogon_creds_cli_LogonSamLogon_start(req); + return; + } + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + } else { + status = dcerpc_netr_LogonSamLogon_recv(subreq, + state->validation, + &result); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + } + + ok = netlogon_creds_client_check(&state->tmp_creds, + &state->rep_auth.cred); + if (!ok) { + status = NT_STATUS_ACCESS_DENIED; + tevent_req_nterror(req, status); + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + + *state->lk_creds = state->tmp_creds; + status = netlogon_creds_cli_store(state->context, + &state->lk_creds); + if (tevent_req_nterror(req, status)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + return; + } + + if (tevent_req_nterror(req, result)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, result); + return; + } + + netlogon_creds_decrypt_samlogon_validation(&state->tmp_creds, + state->validation_level, + state->validation); + + tevent_req_done(req); +} + +NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + uint16_t *validation_level, + union netr_Validation **validation, + uint8_t *authoritative, + uint32_t *flags) +{ + struct netlogon_creds_cli_LogonSamLogon_state *state = + tevent_req_data(req, + struct netlogon_creds_cli_LogonSamLogon_state); + NTSTATUS status; + + /* authoritative is also returned on error */ + *authoritative = state->authoritative; + + if (tevent_req_is_nterror(req, &status)) { + netlogon_creds_cli_LogonSamLogon_cleanup(req, status); + tevent_req_received(req); + return status; + } + + *validation_level = state->validation_level; + *validation = talloc_move(mem_ctx, &state->validation); + *flags = state->flags; + + tevent_req_received(req); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_creds_cli_LogonSamLogon( + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + enum netr_LogonInfoClass logon_level, + const union netr_LogonLevel *logon, + TALLOC_CTX *mem_ctx, + uint16_t *validation_level, + union netr_Validation **validation, + uint8_t *authoritative, + uint32_t *flags) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = netlogon_creds_cli_LogonSamLogon_send(frame, ev, context, b, + logon_level, logon, + *flags); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = netlogon_creds_cli_LogonSamLogon_recv(req, mem_ctx, + validation_level, + validation, + authoritative, + flags); + fail: + TALLOC_FREE(frame); + return status; +} diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h new file mode 100644 index 0000000..f8f2bef --- /dev/null +++ b/libcli/auth/netlogon_creds_cli.h @@ -0,0 +1,138 @@ +/* + Unix SMB/CIFS implementation. + + module to store/fetch session keys for the schannel client + + Copyright (C) Stefan Metzmacher 2013 + + 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 . +*/ + +#ifndef NETLOGON_CREDS_CLI_H +#define NETLOGON_CREDS_CLI_H + +#include "librpc/gen_ndr/dcerpc.h" +#include "librpc/gen_ndr/schannel.h" + +struct netlogon_creds_cli_context; +struct messaging_context; +struct dcerpc_binding_handle; + +NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); + +NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, + struct messaging_context *msg_ctx, + const char *client_account, + enum netr_SchannelType type, + const char *server_computer, + const char *server_netbios_domain, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_context); +NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, + const char *client_account, + enum netr_SchannelType type, + enum dcerpc_AuthLevel auth_level, + uint32_t proposed_flags, + uint32_t required_flags, + const char *server_computer, + const char *server_netbios_domain, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_context); +NTSTATUS netlogon_creds_cli_context_copy( + const struct netlogon_creds_cli_context *src, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **_dst); + +enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( + struct netlogon_creds_cli_context *context); + +NTSTATUS netlogon_creds_cli_get(struct netlogon_creds_cli_context *context, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **_creds); +bool netlogon_creds_cli_validate(struct netlogon_creds_cli_context *context, + const struct netlogon_creds_CredentialState *creds1); + +NTSTATUS netlogon_creds_cli_store(struct netlogon_creds_cli_context *context, + struct netlogon_creds_CredentialState **_creds); +NTSTATUS netlogon_creds_cli_delete(struct netlogon_creds_cli_context *context, + struct netlogon_creds_CredentialState **_creds); + +struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context); +NTSTATUS netlogon_creds_cli_lock_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **creds); +NTSTATUS netlogon_creds_cli_lock(struct netlogon_creds_cli_context *context, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState **creds); + +struct tevent_req *netlogon_creds_cli_auth_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + struct samr_Password current_nt_hash, + const struct samr_Password *previous_nt_hash); +NTSTATUS netlogon_creds_cli_auth_recv(struct tevent_req *req); +NTSTATUS netlogon_creds_cli_auth(struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + struct samr_Password current_nt_hash, + const struct samr_Password *previous_nt_hash); + +struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b); +NTSTATUS netlogon_creds_cli_check_recv(struct tevent_req *req); +NTSTATUS netlogon_creds_cli_check(struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b); + +struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + const char *new_password, + const uint32_t *new_version); +NTSTATUS netlogon_creds_cli_ServerPasswordSet_recv(struct tevent_req *req); +NTSTATUS netlogon_creds_cli_ServerPasswordSet( + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + const char *new_password, + const uint32_t *new_version); + +struct tevent_req *netlogon_creds_cli_LogonSamLogon_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + enum netr_LogonInfoClass logon_level, + const union netr_LogonLevel *logon, + uint32_t flags); +NTSTATUS netlogon_creds_cli_LogonSamLogon_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + uint16_t *validation_level, + union netr_Validation **validation, + uint8_t *authoritative, + uint32_t *flags); +NTSTATUS netlogon_creds_cli_LogonSamLogon( + struct netlogon_creds_cli_context *context, + struct dcerpc_binding_handle *b, + enum netr_LogonInfoClass logon_level, + const union netr_LogonLevel *logon, + TALLOC_CTX *mem_ctx, + uint16_t *validation_level, + union netr_Validation **validation, + uint8_t *authoritative, + uint32_t *flags); + +#endif /* NETLOGON_CREDS_CLI_H */ diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build index ca2be2d..51eb293 100755 --- a/libcli/auth/wscript_build +++ b/libcli/auth/wscript_build @@ -28,6 +28,10 @@ bld.SAMBA_SUBSYSTEM('COMMON_SCHANNEL', deps='dbwrap util_tdb samba-hostconfig NDR_NETLOGON' ) +bld.SAMBA_SUBSYSTEM('NETLOGON_CREDS_CLI', + source='netlogon_creds_cli.c', + deps='dbwrap util_tdb tevent-util samba-hostconfig RPC_NDR_NETLOGON NDR_NETLOGON' + ) bld.SAMBA_SUBSYSTEM('PAM_ERRORS', source='pam_errors.c', -- 1.9.3 From e4a4e18ea7f9a9742de16e477917da6ae11ac42e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Dec 2013 17:31:45 +0100 Subject: [PATCH 163/249] libcli/auth: use unique key_name values in netlogon_creds_cli_context_common() Until all callers are fixed to pass the same 'server_computer' value, we try to calculate a server_netbios_name and use this as unique identifier for a specific domain controller. Otherwise winbind would use 'hostname.example.com' while 'net rpc testjoin' would use 'HOSTNAME', which leads to 2 records in netlogon_creds_cli.tdb for the same domain controller. Once all callers are fixed we can think about reverting this commit. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit dc96b1ddccfe8eb1a631355f9471ee0b620d682c) --- libcli/auth/netlogon_creds_cli.c | 58 +++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 75d6b2c..a872b31 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -106,23 +106,30 @@ static NTSTATUS netlogon_creds_cli_context_common( struct netlogon_creds_cli_context **_context) { struct netlogon_creds_cli_context *context = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + char *_key_name = NULL; + char *server_netbios_name = NULL; + char *p = NULL; *_context = NULL; context = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); if (context == NULL) { + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } context->client.computer = talloc_strdup(context, client_computer); if (context->client.computer == NULL) { - talloc_free(context); + TALLOC_FREE(context); + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } context->client.account = talloc_strdup(context, client_account); if (context->client.account == NULL) { - talloc_free(context); + TALLOC_FREE(context); + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } @@ -133,29 +140,60 @@ static NTSTATUS netlogon_creds_cli_context_common( context->server.computer = talloc_strdup(context, server_computer); if (context->server.computer == NULL) { - talloc_free(context); + TALLOC_FREE(context); + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } context->server.netbios_domain = talloc_strdup(context, server_netbios_domain); if (context->server.netbios_domain == NULL) { - talloc_free(context); + TALLOC_FREE(context); + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } - context->db.key_name = talloc_asprintf(context, "CLI[%s/%s]/SRV[%s/%s]", - client_computer, - client_account, - server_computer, - server_netbios_domain); + /* + * TODO: + * Force the callers to provide a unique + * value for server_computer and use this directly. + * + * For now we have to deal with + * "HOSTNAME" vs. "hostname.example.com". + */ + server_netbios_name = talloc_strdup(frame, server_computer); + if (server_netbios_name == NULL) { + TALLOC_FREE(context); + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + p = strchr(server_netbios_name, '.'); + if (p != NULL) { + p[0] = '\0'; + } + + _key_name = talloc_asprintf(frame, "CLI[%s/%s]/SRV[%s/%s]", + client_computer, + client_account, + server_netbios_name, + server_netbios_domain); + if (_key_name == NULL) { + TALLOC_FREE(context); + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + context->db.key_name = talloc_strdup_upper(context, _key_name); if (context->db.key_name == NULL) { - talloc_free(context); + TALLOC_FREE(context); + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } context->db.key_data = string_term_tdb_data(context->db.key_name); *_context = context; + TALLOC_FREE(frame); return NT_STATUS_OK; } -- 1.9.3 From 29bc7cb7a1c0ef62c923ce859cdd07de2846c5f5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 19:01:28 +0200 Subject: [PATCH 164/249] s3:param: set Globals.bWinbindSealedPipes = true Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 99d8653d83aa2e2e3a0ea097ab7cb65d62d76daf) --- source3/param/loadparm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 40f3242..7d95256 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -834,6 +834,7 @@ static void init_globals(bool reinit_globals) Globals.security = SEC_USER; Globals.bEncryptPasswords = true; Globals.clientSchannel = Auto; + Globals.bWinbindSealedPipes = true; Globals.serverSchannel = Auto; Globals.bReadRaw = true; Globals.bWriteRaw = true; -- 1.9.3 From 21b9d9847ba236d78156de07dd24032e64f2124d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 18:39:56 +0200 Subject: [PATCH 165/249] lib/param: add "neutralize nt4 emulation" option, defaulting to false Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit b39ca3a2aefdd43a55b9cdd8fa5136254b283927) --- .../smbdotconf/winbind/netutralizent4emulation.xml | 19 +++++++++++++++++++ lib/param/param_functions.c | 1 + lib/param/param_table.c | 9 +++++++++ 3 files changed, 29 insertions(+) create mode 100644 docs-xml/smbdotconf/winbind/netutralizent4emulation.xml diff --git a/docs-xml/smbdotconf/winbind/netutralizent4emulation.xml b/docs-xml/smbdotconf/winbind/netutralizent4emulation.xml new file mode 100644 index 0000000..8294a90 --- /dev/null +++ b/docs-xml/smbdotconf/winbind/netutralizent4emulation.xml @@ -0,0 +1,19 @@ + + + This option controls whether winbindd sends + the NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION flag in order to bypass + the NT4 emulation of a domain controller. + + Typically you should not need set this. + It can be useful for upgrades from NT4 to AD domains. + + The behavior can be controlled per netbios domain + by using 'neutralize nt4 emulation:NETBIOSDOMAIN = yes' as option. + + +no + diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c index 60f9c07..aef091b 100644 --- a/lib/param/param_functions.c +++ b/lib/param/param_functions.c @@ -192,6 +192,7 @@ FN_GLOBAL_BOOL(log_writeable_files_on_exit, bLogWriteableFilesOnExit) FN_GLOBAL_BOOL(map_untrusted_to_domain, bMapUntrustedToDomain) FN_GLOBAL_BOOL(ms_add_printer_wizard, bMsAddPrinterWizard) FN_GLOBAL_BOOL(multicast_dns_register, bMulticastDnsRegister) +FN_GLOBAL_BOOL(neutralize_nt4_emulation, bNeutralizeNT4Emulation) FN_GLOBAL_BOOL(nis_home_map, bNISHomeMap) FN_GLOBAL_BOOL(nmbd_bind_explicit_broadcast, bNmbdBindExplicitBroadcast) FN_GLOBAL_BOOL(ntlm_auth, bNTLMAuth) diff --git a/lib/param/param_table.c b/lib/param/param_table.c index 8e3f952..edf6829 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -4188,6 +4188,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "neutralize nt4 emulation", + .type = P_BOOL, + .p_class = P_GLOBAL, + .offset = GLOBAL_VAR(bNeutralizeNT4Emulation), + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, {N_("DNS options"), P_SEP, P_SEPARATOR}, { -- 1.9.3 From d1cfe2d0f3f72e8b7700eee01e47b0bb9d3b9ca3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 18:39:56 +0200 Subject: [PATCH 166/249] lib/param: add "reject md5 servers" option, defaulting to false Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit de4f8f0825790452455a9d51e9d84d4d4a5c0d3b) --- docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 23 +++++++++++++++++++++++ lib/param/param_functions.c | 1 + lib/param/param_table.c | 9 +++++++++ 3 files changed, 33 insertions(+) create mode 100644 docs-xml/smbdotconf/winbind/rejectmd5servers.xml diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml new file mode 100644 index 0000000..18f8bcb --- /dev/null +++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml @@ -0,0 +1,23 @@ + + + This option controls whether winbindd requires support + for aes support for the netlogon secure channel. + + The following flags will be required NETLOGON_NEG_ARCFOUR, + NETLOGON_NEG_SUPPORTS_AES, NETLOGON_NEG_PASSWORD_SET2 and NETLOGON_NEG_AUTHENTICATED_RPC. + + You can set this to yes if all domain controllers support aes. + This will prevent downgrade attacks. + + The behavior can be controlled per netbios domain + by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option. + + This option takes precedence to the option. + + +no + diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c index aef091b..ecd7f8e 100644 --- a/lib/param/param_functions.c +++ b/lib/param/param_functions.c @@ -204,6 +204,7 @@ FN_GLOBAL_BOOL(pam_password_change, bPamPasswordChange) FN_GLOBAL_BOOL(passdb_expand_explicit, bPassdbExpandExplicit) FN_GLOBAL_BOOL(passwd_chat_debug, bPasswdChatDebug) FN_GLOBAL_BOOL(registry_shares, bRegistryShares) +FN_GLOBAL_BOOL(reject_md5_servers, bRejectMD5Servers) FN_GLOBAL_BOOL(reset_on_zero_vc, bResetOnZeroVC) FN_GLOBAL_BOOL(rpc_big_endian, bRpcBigEndian) FN_GLOBAL_BOOL(stat_cache, bStatCache) diff --git a/lib/param/param_table.c b/lib/param/param_table.c index edf6829..b53f850 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -4197,6 +4197,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "reject md5 servers", + .type = P_BOOL, + .p_class = P_GLOBAL, + .offset = GLOBAL_VAR(bRejectMD5Servers), + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, {N_("DNS options"), P_SEP, P_SEPARATOR}, { -- 1.9.3 From 2545090f09da279655510f87d02c631c74409eb1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 18:39:56 +0200 Subject: [PATCH 167/249] lib/param: add "require strong key" option, defaulting to true Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 6630c68cce8fbbd700e7d4cd92ec3ebb2a268f06) --- docs-xml/smbdotconf/winbind/requirestrongkey.xml | 27 ++++++++++++++++++++++++ lib/param/loadparm.c | 1 + lib/param/param_functions.c | 1 + lib/param/param_table.c | 9 ++++++++ 4 files changed, 38 insertions(+) create mode 100644 docs-xml/smbdotconf/winbind/requirestrongkey.xml diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml new file mode 100644 index 0000000..de749bb --- /dev/null +++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml @@ -0,0 +1,27 @@ + + + This option controls whether winbindd requires support + for md5 strong key support for the netlogon secure channel. + + The following flags will be required NETLOGON_NEG_STRONG_KEYS, + NETLOGON_NEG_ARCFOUR and NETLOGON_NEG_AUTHENTICATED_RPC. + + You can set this to no if some domain controllers only support des. + This might allows weak crypto to be negotiated, may via downgrade attacks. + + The behavior can be controlled per netbios domain + by using 'require strong key:NETBIOSDOMAIN = no' as option. + + Note for active directory domain this option is hardcoded to 'yes' + + This option yields precedence to the option. + + This option takes precedence to the option. + + +yes + diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 23b45e2..a84a166 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -2183,6 +2183,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\"); lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True"); + lpcfg_do_global_parameter(lp_ctx, "require strong key", "True"); lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR); lpcfg_do_global_parameter(lp_ctx, "winbindd privileged socket directory", dyn_WINBINDD_PRIVILEGED_SOCKET_DIR); lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR); diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c index ecd7f8e..41b137f 100644 --- a/lib/param/param_functions.c +++ b/lib/param/param_functions.c @@ -205,6 +205,7 @@ FN_GLOBAL_BOOL(passdb_expand_explicit, bPassdbExpandExplicit) FN_GLOBAL_BOOL(passwd_chat_debug, bPasswdChatDebug) FN_GLOBAL_BOOL(registry_shares, bRegistryShares) FN_GLOBAL_BOOL(reject_md5_servers, bRejectMD5Servers) +FN_GLOBAL_BOOL(require_strong_key, bRequireStrongKey) FN_GLOBAL_BOOL(reset_on_zero_vc, bResetOnZeroVC) FN_GLOBAL_BOOL(rpc_big_endian, bRpcBigEndian) FN_GLOBAL_BOOL(stat_cache, bStatCache) diff --git a/lib/param/param_table.c b/lib/param/param_table.c index b53f850..36e8554 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -4206,6 +4206,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "require strong key", + .type = P_BOOL, + .p_class = P_GLOBAL, + .offset = GLOBAL_VAR(bRequireStrongKey), + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, {N_("DNS options"), P_SEP, P_SEPARATOR}, { -- 1.9.3 From 4e604cc566b2854045c5b794a846c1ab1ef4a35f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 19:01:47 +0200 Subject: [PATCH 168/249] s3:param: set Globals.bRequireStrongKey = true Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit e7954bcc04ec6761b2ed6dad08b90c65efafa948) --- source3/param/loadparm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 7d95256..ed46e53 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -835,6 +835,7 @@ static void init_globals(bool reinit_globals) Globals.bEncryptPasswords = true; Globals.clientSchannel = Auto; Globals.bWinbindSealedPipes = true; + Globals.bRequireStrongKey = true; Globals.serverSchannel = Auto; Globals.bReadRaw = true; Globals.bWriteRaw = true; -- 1.9.3 From 382f69a0f3762947a3e8cc02e8e9817533073195 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 18:48:15 +0200 Subject: [PATCH 169/249] libcli/auth: make use of real options in netlogon_creds_cli_context_global() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit fa3af7c2e8f1bf292e190ba3d933b6e1d552595d) --- libcli/auth/netlogon_creds_cli.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index a872b31..6590b21 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -279,11 +279,7 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, * allow overwrite per domain * reject md5 servers: */ - //TODO: add lpcfp_reject_md5_servers() - reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, - "__default__", - "reject md5 servers", - reject_md5_servers); + reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx); reject_md5_servers = lpcfg_parm_bool(lp_ctx, NULL, "reject md5 servers", server_netbios_domain, @@ -293,11 +289,7 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, * allow overwrite per domain * require strong key: */ - //TODO: add lpcfp_require_strong_key() - require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, - "__default__", - "require strong key", - require_strong_key); + require_strong_key = lpcfg_require_strong_key(lp_ctx); require_strong_key = lpcfg_parm_bool(lp_ctx, NULL, "require strong key", server_netbios_domain, @@ -327,11 +319,7 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, * allow overwrite per domain * neutralize nt4 emulation: */ - //TODO: add lpcfp_neutralize_nt4_emulation() - neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, - "__default__", - "neutralize nt4 emulation", - neutralize_nt4_emulation); + neutralize_nt4_emulation = lpcfg_neutralize_nt4_emulation(lp_ctx); neutralize_nt4_emulation = lpcfg_parm_bool(lp_ctx, NULL, "neutralize nt4 emulation", server_netbios_domain, -- 1.9.3 From 79e8c0c97591ed8bc129561e44b0d94757fcc4e1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Dec 2013 10:45:27 +0100 Subject: [PATCH 170/249] docs-xml: explain the interaction between security = ads and other options. It implies 'require strong key = yes' and 'client schannel = yes'. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit f703a37a56e215827dbb2a7ec8da6738bf17f600) --- docs-xml/smbdotconf/security/security.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs-xml/smbdotconf/security/security.xml b/docs-xml/smbdotconf/security/security.xml index 406089f..2f5c3f7 100644 --- a/docs-xml/smbdotconf/security/security.xml +++ b/docs-xml/smbdotconf/security/security.xml @@ -99,7 +99,10 @@ Note that this mode does NOT make Samba operate as a Active Directory Domain Controller. - + + Note that this forces yes + and yes for the primary domain. + Read the chapter about Domain Membership in the HOWTO for details. -- 1.9.3 From 27ea332df51e3cd8ed9601633282b688e6f288a7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Dec 2013 10:46:57 +0100 Subject: [PATCH 171/249] docs-xml: explain the interaction of 'client schannel' with 'require strong key = yes' Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 1d69fdddd5287757c2e67b0982d00241a6d75d26) --- docs-xml/smbdotconf/security/clientschannel.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs-xml/smbdotconf/security/clientschannel.xml b/docs-xml/smbdotconf/security/clientschannel.xml index e229182..ac4cc59 100644 --- a/docs-xml/smbdotconf/security/clientschannel.xml +++ b/docs-xml/smbdotconf/security/clientschannel.xml @@ -12,6 +12,11 @@ enforce it, and yes denies access if the server is not able to speak netlogon schannel. + + Note that for active directory domains this is hardcoded to + yes. + + This option yields precedence to the option. auto yes -- 1.9.3 From 4853daeffb1916db3b92dc6ba9e5776652ec5f4e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 19:31:58 +0200 Subject: [PATCH 172/249] s3:winbindd: make use of the "winbind sealed pipes" option for all connections Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 225982e1cb6276ed5c6a47c0e4827d75e8ab2fb1) --- source3/winbindd/winbindd.h | 3 +++ source3/winbindd/winbindd_cm.c | 20 +++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 72eb3ec..afde685 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -25,6 +25,7 @@ #include "nsswitch/winbind_struct_protocol.h" #include "nsswitch/libwbclient/wbclient.h" +#include "librpc/gen_ndr/dcerpc.h" #include "librpc/gen_ndr/wbint.h" #include "talloc_dict.h" @@ -105,6 +106,8 @@ struct getpwent_user { struct winbindd_cm_conn { struct cli_state *cli; + enum dcerpc_AuthLevel auth_level; + struct rpc_pipe_client *samr_pipe; struct policy_handle sam_connect_handle, sam_domain_handle; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index c4f59d3..6c1244e 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -1722,6 +1722,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, } if (NT_STATUS_IS_OK(result)) { + bool seal_pipes = true; winbindd_set_locator_kdc_envs(domain); @@ -1741,6 +1742,17 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, */ store_current_dc_in_gencache(domain->name, domain->dcname, new_conn->cli); + + seal_pipes = lp_winbind_sealed_pipes(); + seal_pipes = lp_parm_bool(-1, "winbind sealed pipes", + domain->name, + seal_pipes); + + if (seal_pipes) { + new_conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + } else { + new_conn->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; + } } else { /* Ensure we setup the retry handler. */ set_domain_offline(domain); @@ -1813,6 +1825,8 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn) } } + conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + if (conn->cli) { cli_shutdown(conn->cli); } @@ -2363,7 +2377,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, &ndr_table_samr, NCACN_NP, GENSEC_OID_NTLMSSP, - DCERPC_AUTH_LEVEL_PRIVACY, + conn->auth_level, smbXcli_conn_remote_name(conn->cli->conn), domain_name, machine_account, @@ -2534,7 +2548,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, if (conn->lsa_pipe_tcp && conn->lsa_pipe_tcp->transport->transport == NCACN_IP_TCP && - conn->lsa_pipe_tcp->auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY && + conn->lsa_pipe_tcp->auth->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY && rpccli_is_connected(conn->lsa_pipe_tcp)) { goto done; } @@ -2602,7 +2616,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, result = cli_rpc_pipe_open_spnego (conn->cli, &ndr_table_lsarpc, NCACN_NP, GENSEC_OID_NTLMSSP, - DCERPC_AUTH_LEVEL_PRIVACY, + conn->auth_level, smbXcli_conn_remote_name(conn->cli->conn), conn->cli->domain, conn->cli->user_name, conn->cli->password, &conn->lsa_pipe); -- 1.9.3 From c2116e6a1ee32ff36942091287e90b08d1ecf6d1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 14 Nov 2013 18:53:06 +0100 Subject: [PATCH 173/249] docs-xml: update 'winbind sealed pipes' description Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 11aed7cd3dbd967593b34a206f0802fd0002bf27) --- docs-xml/smbdotconf/winbind/winbindsealedpipes.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml b/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml index 26f446e..63f5588 100644 --- a/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml +++ b/docs-xml/smbdotconf/winbind/winbindsealedpipes.xml @@ -4,12 +4,12 @@ advanced="1" developer="1" xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> - This option controls whether any requests made over the Samba 4 winbind + This option controls whether any requests from winbindd to domain controllers pipe will be sealed. Disabling sealing can be useful for debugging purposes. - Note that this option only applies to the Samba 4 winbind and not - to the standard winbind. + The behavior can be controlled per netbios domain + by using 'winbind sealed pipes:NETBIOSDOMAIN = no' as option. yes -- 1.9.3 From ea14b4a713a85a2d87cba6ad88127020e1d5e813 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 27 Jul 2013 11:30:13 +0200 Subject: [PATCH 174/249] s3:rpc_client: make use of the new netlogon_creds_cli_context This exchanges rpc_pipe_client->dc with rpc_pipe_client->netlogon_creds and lets the secure channel session state be stored in node local database. This is the proper fix for a large number of bugs: https://bugzilla.samba.org/show_bug.cgi?id=6563 https://bugzilla.samba.org/show_bug.cgi?id=7944 https://bugzilla.samba.org/show_bug.cgi?id=7945 https://bugzilla.samba.org/show_bug.cgi?id=7568 https://bugzilla.samba.org/show_bug.cgi?id=8599 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 38d4dba37406515181e4d6f1a1faffc18e652e27) --- source3/libnet/libnet_join.c | 3 +- source3/libnet/libnet_samsync.c | 19 +- source3/rpc_client/cli_netlogon.c | 436 ++++++++------------------------- source3/rpc_client/cli_pipe.c | 139 +++-------- source3/rpc_client/cli_pipe.h | 2 +- source3/rpc_client/cli_pipe_schannel.c | 3 +- source3/rpc_client/rpc_client.h | 2 +- source3/rpcclient/cmd_netlogon.c | 57 ++++- source3/winbindd/winbindd.h | 9 - source3/winbindd/winbindd_cm.c | 36 +-- source3/winbindd/winbindd_pam.c | 136 ++-------- source3/wscript_build | 6 +- 12 files changed, 250 insertions(+), 598 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index c1eccda..5dc620f 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1279,7 +1279,8 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, status = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, - netbios_domain_name, &netlogon_pipe->dc, &pipe_hnd); + netbios_domain_name, + netlogon_pipe->netlogon_creds, &pipe_hnd); cli_shutdown(cli); diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c index a103785..02d3fc6 100644 --- a/source3/libnet/libnet_samsync.c +++ b/source3/libnet/libnet_samsync.c @@ -30,6 +30,7 @@ #include "../librpc/gen_ndr/ndr_netlogon_c.h" #include "../libcli/security/security.h" #include "messages.h" +#include "../libcli/auth/netlogon_creds_cli.h" /** * Fix up the delta, dealing with encryption issues so that the final @@ -213,8 +214,15 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, do { struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; + struct netlogon_creds_CredentialState *creds = NULL; - netlogon_creds_client_authenticator(ctx->cli->dc, &credential); + status = netlogon_creds_cli_lock(ctx->cli->netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + netlogon_creds_client_authenticator(creds, &credential); if (ctx->single_object_replication && !ctx->force_full_replication) { @@ -254,28 +262,33 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, } if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); return status; } /* Check returned credentials. */ - if (!netlogon_creds_client_check(ctx->cli->dc, + if (!netlogon_creds_client_check(creds, &return_authenticator.cred)) { + TALLOC_FREE(creds); DEBUG(0,("credentials chain check failed\n")); return NT_STATUS_ACCESS_DENIED; } if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) { + TALLOC_FREE(creds); return result; } if (NT_STATUS_IS_ERR(result)) { + TALLOC_FREE(creds); break; } samsync_fix_delta_array(mem_ctx, - ctx->cli->dc, + creds, database_id, delta_enum_array); + TALLOC_FREE(creds); /* Process results */ callback_status = ctx->ops->process_objects(mem_ctx, database_id, diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 5e8a2fc..fcd24d6 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -23,11 +23,13 @@ #include "includes.h" #include "rpc_client/rpc_client.h" #include "../libcli/auth/libcli_auth.h" +#include "../libcli/auth/netlogon_creds_cli.h" #include "../librpc/gen_ndr/ndr_netlogon_c.h" #include "rpc_client/cli_netlogon.h" #include "rpc_client/init_netlogon.h" #include "rpc_client/util_netlogon.h" #include "../libcli/security/security.h" +#include "lib/param/param.h" /**************************************************************************** Wrapper function that uses the auth and auth2 calls to set up a NETLOGON @@ -44,113 +46,81 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, enum netr_SchannelType sec_chan_type, uint32_t *neg_flags_inout) { + TALLOC_CTX *frame = talloc_stackframe(); + struct loadparm_context *lp_ctx; NTSTATUS status; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - struct netr_Credential clnt_chal_send; - struct netr_Credential srv_chal_recv; struct samr_Password password; - bool retried = false; fstring mach_acct; - uint32_t neg_flags = *neg_flags_inout; struct dcerpc_binding_handle *b = cli->binding_handle; + struct netlogon_creds_CredentialState *creds = NULL; if (!ndr_syntax_id_equal(&cli->abstract_syntax, &ndr_table_netlogon.syntax_id)) { + TALLOC_FREE(frame); return NT_STATUS_INVALID_PARAMETER; } - TALLOC_FREE(cli->dc); - - /* Store the machine account password we're going to use. */ - memcpy(password.hash, machine_pwd, 16); - - fstr_sprintf( mach_acct, "%s$", machine_account); - - again: - /* Create the client challenge. */ - generate_random_buffer(clnt_chal_send.data, 8); - - /* Get the server challenge. */ - status = dcerpc_netr_ServerReqChallenge(b, talloc_tos(), - cli->srv_name_slash, - clnt_name, - &clnt_chal_send, - &srv_chal_recv, - &result); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (!NT_STATUS_IS_OK(result)) { - return result; + if (!strequal(lp_netbios_name(), clnt_name)) { + TALLOC_FREE(frame); + return NT_STATUS_INVALID_PARAMETER; } - /* Calculate the session key and client credentials */ + TALLOC_FREE(cli->netlogon_creds); - cli->dc = netlogon_creds_client_init(cli, - mach_acct, - clnt_name, - sec_chan_type, - &clnt_chal_send, - &srv_chal_recv, - &password, - &clnt_chal_send, - neg_flags); + fstr_sprintf( mach_acct, "%s$", machine_account); - if (!cli->dc) { + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } - - /* - * Send client auth-2 challenge and receive server repy. - */ - - status = dcerpc_netr_ServerAuthenticate2(b, talloc_tos(), - cli->srv_name_slash, - cli->dc->account_name, - sec_chan_type, - cli->dc->computer_name, - &clnt_chal_send, /* input. */ - &srv_chal_recv, /* output. */ - &neg_flags, - &result); + status = netlogon_creds_cli_context_global(lp_ctx, + NULL, /* msg_ctx */ + mach_acct, + sec_chan_type, + server_name, + domain, + cli, &cli->netlogon_creds); + talloc_unlink(frame, lp_ctx); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); return status; } - /* we might be talking to NT4, so let's downgrade in that case and retry - * with the returned neg_flags - gd */ - if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) { - retried = true; - TALLOC_FREE(cli->dc); - goto again; + status = netlogon_creds_cli_get(cli->netlogon_creds, + frame, &creds); + if (NT_STATUS_IS_OK(status)) { + DEBUG(5,("rpccli_netlogon_setup_creds: server %s using " + "cached credential\n", + cli->desthost)); + *neg_flags_inout = creds->negotiate_flags; + TALLOC_FREE(frame); + return NT_STATUS_OK; } - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - /* - * Check the returned value using the initial - * server received challenge. - */ - - if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("rpccli_netlogon_setup_creds: server %s " - "replied with bad credential\n", - cli->desthost )); - return NT_STATUS_ACCESS_DENIED; - } + /* Store the machine account password we're going to use. */ + memcpy(password.hash, machine_pwd, 16); DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential " "chain established.\n", cli->desthost )); - cli->dc->negotiate_flags = neg_flags; - *neg_flags_inout = neg_flags; + status = netlogon_creds_cli_auth(cli->netlogon_creds, b, + password, NULL); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + status = netlogon_creds_cli_get(cli->netlogon_creds, + frame, &creds); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return NT_STATUS_INTERNAL_ERROR; + } + *neg_flags_inout = creds->negotiate_flags; + TALLOC_FREE(frame); return NT_STATUS_OK; } @@ -163,20 +133,16 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, const char *username, const char *password, const char *workstation, - uint16_t validation_level, + uint16_t _ignored_validation_level, int logon_type) { - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; NTSTATUS status; - struct netr_Authenticator clnt_creds; - struct netr_Authenticator ret_creds; union netr_LogonLevel *logon; - union netr_Validation validation; - uint8_t authoritative; + uint16_t validation_level = 0; + union netr_Validation *validation = NULL; + uint8_t authoritative = 0; + uint32_t flags = 0; fstring clnt_name_slash; - struct dcerpc_binding_handle *b = cli->binding_handle; - - ZERO_STRUCT(ret_creds); logon = talloc_zero(mem_ctx, union netr_LogonLevel); if (!logon) { @@ -191,8 +157,6 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, /* Initialise input parameters */ - netlogon_creds_client_authenticator(cli->dc, &clnt_creds); - switch (logon_type) { case NetlogonInteractiveInformation: { @@ -208,17 +172,6 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); - if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16); - netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16); - } else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) { - netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16); - netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16); - } else { - netlogon_creds_des_encrypt(cli->dc, &lmpassword); - netlogon_creds_des_encrypt(cli->dc, &ntpassword); - } - password_info->identity_info.domain_name.string = domain; password_info->identity_info.parameter_control = logon_parameters; password_info->identity_info.logon_id_low = 0xdead; @@ -281,28 +234,20 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, return NT_STATUS_INVALID_INFO_CLASS; } - status = dcerpc_netr_LogonSamLogon(b, mem_ctx, - cli->srv_name_slash, - lp_netbios_name(), - &clnt_creds, - &ret_creds, - logon_type, - logon, - validation_level, - &validation, - &authoritative, - &result); + status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, + cli->binding_handle, + logon_type, + logon, + mem_ctx, + &validation_level, + &validation, + &authoritative, + &flags); if (!NT_STATUS_IS_OK(status)) { return status; } - /* Always check returned credentials */ - if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { - DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - - return result; + return NT_STATUS_OK; } static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, @@ -366,29 +311,24 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, const char *domain, const char *workstation, const uint8 chal[8], - uint16_t validation_level, + uint16_t _ignored_validation_level, DATA_BLOB lm_response, DATA_BLOB nt_response, struct netr_SamInfo3 **info3) { - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; NTSTATUS status; const char *workstation_name_slash; - const char *server_name_slash; - struct netr_Authenticator clnt_creds; - struct netr_Authenticator ret_creds; union netr_LogonLevel *logon = NULL; struct netr_NetworkInfo *network_info; - uint8_t authoritative; - union netr_Validation validation; + uint16_t validation_level = 0; + union netr_Validation *validation = NULL; + uint8_t authoritative = 0; + uint32_t flags = 0; struct netr_ChallengeResponse lm; struct netr_ChallengeResponse nt; - struct dcerpc_binding_handle *b = cli->binding_handle; *info3 = NULL; - ZERO_STRUCT(ret_creds); - ZERO_STRUCT(lm); ZERO_STRUCT(nt); @@ -402,21 +342,13 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, return NT_STATUS_NO_MEMORY; } - netlogon_creds_client_authenticator(cli->dc, &clnt_creds); - - if (server[0] != '\\' && server[1] != '\\') { - server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server); - } else { - server_name_slash = server; - } - if (workstation[0] != '\\' && workstation[1] != '\\') { workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); } else { workstation_name_slash = workstation; } - if (!workstation_name_slash || !server_name_slash) { + if (!workstation_name_slash) { DEBUG(0, ("talloc_asprintf failed!\n")); return NT_STATUS_NO_MEMORY; } @@ -443,40 +375,27 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, /* Marshall data and send request */ - status = dcerpc_netr_LogonSamLogon(b, mem_ctx, - server_name_slash, - lp_netbios_name(), - &clnt_creds, - &ret_creds, - NetlogonNetworkInformation, - logon, - validation_level, - &validation, - &authoritative, - &result); + status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, + cli->binding_handle, + NetlogonNetworkInformation, + logon, + mem_ctx, + &validation_level, + &validation, + &authoritative, + &flags); if (!NT_STATUS_IS_OK(status)) { return status; } - /* Always check returned credentials. */ - if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) { - DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level, - &validation); - - result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); - if (!NT_STATUS_IS_OK(result)) { - return result; + status = map_validation_to_info3(mem_ctx, + validation_level, validation, + info3); + if (!NT_STATUS_IS_OK(status)) { + return status; } - return result; + return NT_STATUS_OK; } NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, @@ -492,100 +411,18 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, DATA_BLOB nt_response, struct netr_SamInfo3 **info3) { - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - NTSTATUS status; - const char *workstation_name_slash; - const char *server_name_slash; - union netr_LogonLevel *logon = NULL; - struct netr_NetworkInfo *network_info; - uint8_t authoritative; - union netr_Validation validation; - struct netr_ChallengeResponse lm; - struct netr_ChallengeResponse nt; - uint32_t flags = 0; - struct dcerpc_binding_handle *b = cli->binding_handle; - - *info3 = NULL; - - ZERO_STRUCT(lm); - ZERO_STRUCT(nt); - - logon = talloc_zero(mem_ctx, union netr_LogonLevel); - if (!logon) { - return NT_STATUS_NO_MEMORY; - } - - network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); - if (!network_info) { - return NT_STATUS_NO_MEMORY; - } - - if (server[0] != '\\' && server[1] != '\\') { - server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server); - } else { - server_name_slash = server; - } - - if (workstation[0] != '\\' && workstation[1] != '\\') { - workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); - } else { - workstation_name_slash = workstation; - } - - if (!workstation_name_slash || !server_name_slash) { - DEBUG(0, ("talloc_asprintf failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - /* Initialise input parameters */ - - lm.data = lm_response.data; - lm.length = lm_response.length; - nt.data = nt_response.data; - nt.length = nt_response.length; - - network_info->identity_info.domain_name.string = domain; - network_info->identity_info.parameter_control = logon_parameters; - network_info->identity_info.logon_id_low = 0xdead; - network_info->identity_info.logon_id_high = 0xbeef; - network_info->identity_info.account_name.string = username; - network_info->identity_info.workstation.string = workstation_name_slash; - - memcpy(network_info->challenge, chal, 8); - network_info->nt = nt; - network_info->lm = lm; - - logon->network = network_info; - - /* Marshall data and send request */ - - status = dcerpc_netr_LogonSamLogonEx(b, mem_ctx, - server_name_slash, - lp_netbios_name(), - NetlogonNetworkInformation, - logon, - validation_level, - &validation, - &authoritative, - &flags, - &result); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level, - &validation); - - result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - return result; + return rpccli_netlogon_sam_network_logon(cli, + mem_ctx, + logon_parameters, + server, + username, + domain, + workstation, + chal, + validation_level, + lm_response, + nt_response, + info3); } /********************************************************* @@ -605,11 +442,9 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, const unsigned char new_trust_passwd_hash[16], enum netr_SchannelType sec_channel_type) { - NTSTATUS result, status; - struct netr_Authenticator clnt_creds, srv_cred; - struct dcerpc_binding_handle *b = cli->binding_handle; + NTSTATUS result; - if (!cli->dc) { + if (cli->netlogon_creds == NULL) { uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; result = rpccli_netlogon_setup_creds(cli, @@ -627,77 +462,16 @@ NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, } } - netlogon_creds_client_authenticator(cli->dc, &clnt_creds); - - if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { - - struct netr_CryptPassword new_password; - uint32_t old_timeout; - - init_netr_CryptPassword(new_trust_pwd_cleartext, - cli->dc, - &new_password); - - old_timeout = dcerpc_binding_handle_set_timeout(b, 600000); - - status = dcerpc_netr_ServerPasswordSet2(b, mem_ctx, - cli->srv_name_slash, - cli->dc->account_name, - sec_channel_type, - cli->dc->computer_name, - &clnt_creds, - &srv_cred, - &new_password, - &result); - - dcerpc_binding_handle_set_timeout(b, old_timeout); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("dcerpc_netr_ServerPasswordSet2 failed: %s\n", - nt_errstr(status))); - return status; - } - } else { - - struct samr_Password new_password; - uint32_t old_timeout; - - memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash)); - netlogon_creds_des_encrypt(cli->dc, &new_password); - - old_timeout = dcerpc_binding_handle_set_timeout(b, 600000); - - status = dcerpc_netr_ServerPasswordSet(b, mem_ctx, - cli->srv_name_slash, - cli->dc->account_name, - sec_channel_type, - cli->dc->computer_name, - &clnt_creds, - &srv_cred, - &new_password, - &result); - - dcerpc_binding_handle_set_timeout(b, old_timeout); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("dcerpc_netr_ServerPasswordSet failed: %s\n", - nt_errstr(status))); - return status; - } - } - - /* Always check returned credentials. */ - if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { - DEBUG(0,("credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - + result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds, + cli->binding_handle, + new_trust_pwd_cleartext, + NULL); /* new_version */ if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("dcerpc_netr_ServerPasswordSet{2} failed: %s\n", + DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n", nt_errstr(result))); return result; } - return result; + return NT_STATUS_OK; } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index a45023f..fe1613d 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -24,6 +24,7 @@ #include "librpc/gen_ndr/ndr_epmapper_c.h" #include "../librpc/gen_ndr/ndr_dssetup.h" #include "../libcli/auth/schannel.h" +#include "../libcli/auth/netlogon_creds_cli.h" #include "auth_generic.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/gen_ndr/ndr_netlogon_c.h" @@ -3024,34 +3025,39 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, - struct netlogon_creds_CredentialState **pdc, + struct netlogon_creds_cli_context *netlogon_creds, struct rpc_pipe_client **_rpccli) { struct rpc_pipe_client *rpccli; struct pipe_auth_data *rpcauth; + struct netlogon_creds_CredentialState *creds = NULL; NTSTATUS status; - NTSTATUS result; - struct netlogon_creds_CredentialState save_creds; - struct netr_Authenticator auth; - struct netr_Authenticator return_auth; - union netr_Capabilities capabilities; const char *target_service = table->authservices->names[0]; + int rpc_pipe_bind_dbglvl = 0; status = cli_rpc_pipe_open(cli, transport, table, &rpccli); if (!NT_STATUS_IS_OK(status)) { return status; } + status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &creds); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("netlogon_creds_cli_get returned %s\n", + nt_errstr(status))); + TALLOC_FREE(rpccli); + return status; + } + status = rpccli_generic_bind_data(rpccli, DCERPC_AUTH_TYPE_SCHANNEL, auth_level, NULL, target_service, domain, - (*pdc)->computer_name, + creds->computer_name, NULL, CRED_AUTO_USE_KERBEROS, - *pdc, + creds, &rpcauth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpccli_generic_bind_data returned %s\n", @@ -3060,120 +3066,43 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return status; } - /* - * The credentials on a new netlogon pipe are the ones we are passed - * in - copy them over - * - * This may get overwritten... in rpc_pipe_bind()... - */ - rpccli->dc = netlogon_creds_copy(rpccli, *pdc); - if (rpccli->dc == NULL) { - TALLOC_FREE(rpccli); - return NT_STATUS_NO_MEMORY; - } - status = rpc_pipe_bind(rpccli, rpcauth); + if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { + rpc_pipe_bind_dbglvl = 1; + netlogon_creds_cli_delete(netlogon_creds, &creds); + } if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: " - "cli_rpc_pipe_bind failed with error %s\n", - nt_errstr(status) )); + DEBUG(rpc_pipe_bind_dbglvl, + ("cli_rpc_pipe_open_schannel_with_key: " + "rpc_pipe_bind failed with error %s\n", + nt_errstr(status))); TALLOC_FREE(rpccli); return status; } - if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) { - goto done; - } - - save_creds = *rpccli->dc; - ZERO_STRUCT(return_auth); - ZERO_STRUCT(capabilities); + TALLOC_FREE(creds); - netlogon_creds_client_authenticator(&save_creds, &auth); - - status = dcerpc_netr_LogonGetCapabilities(rpccli->binding_handle, - talloc_tos(), - rpccli->srv_name_slash, - save_creds.computer_name, - &auth, &return_auth, - 1, &capabilities, - &result); - if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { - if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - DEBUG(5, ("AES was negotiated and the error was %s - " - "downgrade detected\n", - nt_errstr(status))); - TALLOC_FREE(rpccli); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - /* This is probably an old Samba Version */ - DEBUG(5, ("We are checking against an NT or old Samba - %s\n", - nt_errstr(status))); + if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) { goto done; } + status = netlogon_creds_cli_check(netlogon_creds, + rpccli->binding_handle); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", + DEBUG(0, ("netlogon_creds_cli_check failed with %s\n", nt_errstr(status))); TALLOC_FREE(rpccli); return status; } - if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) { - if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - /* This means AES isn't supported. */ - DEBUG(5, ("AES was negotiated and the result was %s - " - "downgrade detected\n", - nt_errstr(result))); - TALLOC_FREE(rpccli); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - /* This is probably an old Windows version */ - DEBUG(5, ("We are checking against an win2k3 or Samba - %s\n", - nt_errstr(result))); - goto done; - } - - /* - * We need to check the credential state here, cause win2k3 and earlier - * returns NT_STATUS_NOT_IMPLEMENTED - */ - if (!netlogon_creds_client_check(&save_creds, &return_auth.cred)) { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("cli_rpc_pipe_open_schannel_with_key: server %s " - "replied with bad credential\n", - rpccli->desthost)); - TALLOC_FREE(rpccli); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - *rpccli->dc = save_creds; - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n", - nt_errstr(result))); - TALLOC_FREE(rpccli); - return result; - } - - if (!(save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) { - /* This means AES isn't supported. */ - DEBUG(5, ("AES is not negotiated, but netr_LogonGetCapabilities " - "was OK - downgrade detected\n")); - TALLOC_FREE(rpccli); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - if (save_creds.negotiate_flags != capabilities.server_capabilities) { - DEBUG(0, ("The client capabilities don't match the server " - "capabilities: local[0x%08X] remote[0x%08X]\n", - save_creds.negotiate_flags, - capabilities.server_capabilities)); + status = netlogon_creds_cli_context_copy(netlogon_creds, + rpccli, + &rpccli->netlogon_creds); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("netlogon_creds_cli_context_copy failed with %s\n", + nt_errstr(status))); TALLOC_FREE(rpccli); - return NT_STATUS_INVALID_NETWORK_RESPONSE; + return status; } done: diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 826f9bf..cf0c5c6 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -96,7 +96,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, - struct netlogon_creds_CredentialState **pdc, + struct netlogon_creds_cli_context *netlogon_creds, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index aaae44b..e3d65c8 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -112,7 +112,8 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, table, transport, auth_level, domain, &netlogon_pipe->dc, + cli, table, transport, auth_level, domain, + netlogon_pipe->netlogon_creds, &result); /* Now we've bound using the session key we can close the netlog pipe. */ diff --git a/source3/rpc_client/rpc_client.h b/source3/rpc_client/rpc_client.h index 8024f01..7c4cceb 100644 --- a/source3/rpc_client/rpc_client.h +++ b/source3/rpc_client/rpc_client.h @@ -50,7 +50,7 @@ struct rpc_pipe_client { struct pipe_auth_data *auth; /* The following is only non-null on a netlogon client pipe. */ - struct netlogon_creds_CredentialState *dc; + struct netlogon_creds_cli_context *netlogon_creds; }; #endif /* _RPC_CLIENT_H */ diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index d92434b..2e0b5e5 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -26,6 +26,7 @@ #include "../librpc/gen_ndr/ndr_netlogon_c.h" #include "rpc_client/cli_netlogon.h" #include "secrets.h" +#include "../libcli/auth/netlogon_creds_cli.h" static WERROR cmd_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, @@ -630,8 +631,15 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, do { struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; + struct netlogon_creds_CredentialState *creds = NULL; - netlogon_creds_client_authenticator(cli->dc, &credential); + status = netlogon_creds_cli_lock(cli->netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_DatabaseSync2(b, mem_ctx, logon_server, @@ -645,15 +653,18 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, 0xffff, &result); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); return status; } /* Check returned credentials. */ - if (!netlogon_creds_client_check(cli->dc, + if (!netlogon_creds_client_check(creds, &return_authenticator.cred)) { DEBUG(0,("credentials chain check failed\n")); + TALLOC_FREE(creds); return NT_STATUS_ACCESS_DENIED; } + TALLOC_FREE(creds); if (NT_STATUS_IS_ERR(result)) { break; @@ -699,8 +710,15 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, do { struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + + status = netlogon_creds_cli_lock(cli->netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - netlogon_creds_client_authenticator(cli->dc, &credential); + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_DatabaseDeltas(b, mem_ctx, logon_server, @@ -713,15 +731,18 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, 0xffff, &result); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); return status; } /* Check returned credentials. */ - if (!netlogon_creds_client_check(cli->dc, + if (!netlogon_creds_client_check(creds, &return_authenticator.cred)) { DEBUG(0,("credentials chain check failed\n")); + TALLOC_FREE(creds); return NT_STATUS_ACCESS_DENIED; } + TALLOC_FREE(creds); if (NT_STATUS_IS_ERR(result)) { break; @@ -1129,6 +1150,7 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, struct netr_ChangeLogEntry e; uint32_t rid = 500; struct dcerpc_binding_handle *b = cli->binding_handle; + struct netlogon_creds_CredentialState *creds = NULL; if (argc > 2) { fprintf(stderr, "Usage: %s \n", argv[0]); @@ -1158,7 +1180,13 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, return status; } - netlogon_creds_client_authenticator(cli->dc, &clnt_creds); + status = netlogon_creds_cli_lock(cli->netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + netlogon_creds_client_authenticator(creds, &clnt_creds); ZERO_STRUCT(e); @@ -1176,13 +1204,16 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, &delta_enum_array, &result); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); return status; } - if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { + if (!netlogon_creds_client_check(creds, &srv_cred.cred)) { DEBUG(0,("credentials chain check failed\n")); + TALLOC_FREE(creds); return NT_STATUS_ACCESS_DENIED; } + TALLOC_FREE(creds); return result; } @@ -1198,6 +1229,7 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, union netr_Capabilities capabilities; uint32_t level = 1; struct dcerpc_binding_handle *b = cli->binding_handle; + struct netlogon_creds_CredentialState *creds = NULL; if (argc > 2) { fprintf(stderr, "Usage: %s \n", argv[0]); @@ -1210,7 +1242,13 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, ZERO_STRUCT(return_authenticator); - netlogon_creds_client_authenticator(cli->dc, &credential); + status = netlogon_creds_cli_lock(cli->netlogon_creds, + mem_ctx, &creds); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + netlogon_creds_client_authenticator(creds, &credential); status = dcerpc_netr_LogonGetCapabilities(b, mem_ctx, cli->desthost, @@ -1221,14 +1259,17 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, &capabilities, &result); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); return status; } - if (!netlogon_creds_client_check(cli->dc, + if (!netlogon_creds_client_check(creds, &return_authenticator.cred)) { DEBUG(0,("credentials chain check failed\n")); + TALLOC_FREE(creds); return NT_STATUS_ACCESS_DENIED; } + TALLOC_FREE(creds); printf("capabilities: 0x%08x\n", capabilities.server_capabilities); diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index afde685..b5fc010 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -165,16 +165,7 @@ struct winbindd_domain { time_t startup_time; /* When we set "startup" true. monotonic clock */ bool startup; /* are we in the first 30 seconds after startup_time ? */ - bool can_do_samlogon_ex; /* Due to the lack of finer control what type - * of DC we have, let us try to do a - * credential-chain less samlogon_ex call - * with AD and schannel. If this fails with - * DCERPC_FAULT_OP_RNG_ERROR, then set this - * to False. This variable is around so that - * we don't have to try _ex every time. */ - bool can_do_ncacn_ip_tcp; - bool can_do_validation6; /* Lookup methods for this domain (LDAP or RPC) */ struct winbindd_methods *methods; diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 6c1244e..e0d1d0c 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2047,7 +2047,6 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain ) domain->active_directory ? "" : "NOT ")); domain->can_do_ncacn_ip_tcp = domain->active_directory; - domain->can_do_validation6 = domain->active_directory; domain->initialized = True; @@ -2248,7 +2247,6 @@ done: domain->name, domain->active_directory ? "" : "NOT ")); domain->can_do_ncacn_ip_tcp = domain->active_directory; - domain->can_do_validation6 = domain->active_directory; TALLOC_FREE(cli); @@ -2289,7 +2287,7 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain ) ***********************************************************************/ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, - struct netlogon_creds_CredentialState **ppdc) + struct netlogon_creds_cli_context **ppdc) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct rpc_pipe_client *netlogon_pipe; @@ -2306,11 +2304,11 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, /* Return a pointer to the struct netlogon_creds_CredentialState from the netlogon pipe. */ - if (!domain->conn.netlogon_pipe->dc) { + if (!domain->conn.netlogon_pipe->netlogon_creds) { return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */ } - *ppdc = domain->conn.netlogon_pipe->dc; + *ppdc = domain->conn.netlogon_pipe->netlogon_creds; return NT_STATUS_OK; } @@ -2319,7 +2317,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, { struct winbindd_cm_conn *conn; NTSTATUS status, result; - struct netlogon_creds_CredentialState *p_creds; + struct netlogon_creds_cli_context *p_creds; char *machine_password = NULL; char *machine_account = NULL; const char *domain_name = NULL; @@ -2431,7 +2429,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, status = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_samr, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, - domain->name, &p_creds, &conn->samr_pipe); + domain->name, p_creds, &conn->samr_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("cm_connect_sam: failed to connect to SAMR pipe for " @@ -2534,7 +2532,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, struct rpc_pipe_client **cli) { struct winbindd_cm_conn *conn; - struct netlogon_creds_CredentialState *creds; + struct netlogon_creds_cli_context *creds; NTSTATUS status; DEBUG(10,("cm_connect_lsa_tcp\n")); @@ -2565,7 +2563,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, NCACN_IP_TCP, DCERPC_AUTH_LEVEL_PRIVACY, domain->name, - &creds, + creds, &conn->lsa_pipe_tcp); if (!NT_STATUS_IS_OK(status)) { DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n", @@ -2589,7 +2587,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, { struct winbindd_cm_conn *conn; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - struct netlogon_creds_CredentialState *p_creds; + struct netlogon_creds_cli_context *p_creds; result = init_dc_connection_rpc(domain); if (!NT_STATUS_IS_OK(result)) @@ -2662,7 +2660,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, result = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_lsarpc, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, - domain->name, &p_creds, &conn->lsa_pipe); + domain->name, p_creds, &conn->lsa_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(10,("cm_connect_lsa: failed to connect to LSA pipe for " @@ -2826,10 +2824,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, no_schannel: if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - /* - * NetSamLogonEx only works for schannel - */ - domain->can_do_samlogon_ex = False; /* We're done - just keep the existing connection to NETLOGON * open */ @@ -2845,7 +2839,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, result = cli_rpc_pipe_open_schannel_with_key( conn->cli, &ndr_table_netlogon, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, domain->name, &netlogon_pipe->dc, + DCERPC_AUTH_LEVEL_PRIVACY, domain->name, + netlogon_pipe->netlogon_creds, &conn->netlogon_pipe); /* We can now close the initial netlogon pipe. */ @@ -2859,15 +2854,6 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, return result; } - /* - * Always try netr_LogonSamLogonEx. We will fall back for NT4 - * which gives DCERPC_FAULT_OP_RNG_ERROR (function not - * supported). We used to only try SamLogonEx for AD, but - * Samba DCs can also do it. And because we don't distinguish - * between Samba and NT4, always try it once. - */ - domain->can_do_samlogon_ex = true; - *cli = conn->netlogon_pipe; return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c356686..39483a5 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1228,8 +1228,6 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, do { struct rpc_pipe_client *netlogon_pipe; - const struct pipe_auth_data *auth; - uint32_t neg_flags = 0; ZERO_STRUCTP(info3); retry = false; @@ -1278,75 +1276,7 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, } netr_attempts = 0; - auth = netlogon_pipe->auth; - if (netlogon_pipe->dc) { - neg_flags = netlogon_pipe->dc->negotiate_flags; - } - - /* It is really important to try SamLogonEx here, - * because in a clustered environment, we want to use - * one machine account from multiple physical - * computers. - * - * With a normal SamLogon call, we must keep the - * credentials chain updated and intact between all - * users of the machine account (which would imply - * cross-node communication for every NTLM logon). - * - * (The credentials chain is not per NETLOGON pipe - * connection, but globally on the server/client pair - * by machine name). - * - * When using SamLogonEx, the credentials are not - * supplied, but the session key is implied by the - * wrapping SamLogon context. - * - * -- abartlet 21 April 2008 - * - * It's also important to use NetlogonValidationSamInfo4 (6), - * because it relies on the rpc transport encryption - * and avoids using the global netlogon schannel - * session key to en/decrypt secret information - * like the user_session_key for network logons. - * - * [MS-APDS] 3.1.5.2 NTLM Network Logon - * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and - * NETLOGON_NEG_AUTHENTICATED_RPC set together - * are the indication that the server supports - * NetlogonValidationSamInfo4 (6). And it must only - * be used if "SealSecureChannel" is used. - * - * -- metze 4 February 2011 - */ - - if (auth == NULL) { - domain->can_do_validation6 = false; - } else if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { - domain->can_do_validation6 = false; - } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { - domain->can_do_validation6 = false; - } else if (!(neg_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) { - domain->can_do_validation6 = false; - } else if (!(neg_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { - domain->can_do_validation6 = false; - } - - if (domain->can_do_samlogon_ex && domain->can_do_validation6) { - result = rpccli_netlogon_sam_network_logon_ex( - netlogon_pipe, - mem_ctx, - logon_parameters, - server, /* server name */ - username, /* user name */ - domainname, /* target domain */ - workstation, /* workstation */ - chal, - 6, - lm_response, - nt_response, - info3); - } else { - result = rpccli_netlogon_sam_network_logon( + result = rpccli_netlogon_sam_network_logon( netlogon_pipe, mem_ctx, logon_parameters, @@ -1355,48 +1285,10 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, domainname, /* target domain */ workstation, /* workstation */ chal, - domain->can_do_validation6 ? 6 : 3, + -1, /* ignored */ lm_response, nt_response, info3); - } - - if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { - - /* - * It's likely that the server also does not support - * validation level 6 - */ - domain->can_do_validation6 = false; - - if (domain->can_do_samlogon_ex) { - DEBUG(3, ("Got a DC that can not do NetSamLogonEx, " - "retrying with NetSamLogon\n")); - domain->can_do_samlogon_ex = false; - retry = true; - continue; - } - - - /* Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon - * (no Ex). This happens against old Samba - * DCs. Drop the connection. - */ - invalidate_cm_connection(&domain->conn); - result = NT_STATUS_LOGON_FAILURE; - break; - } - - if (domain->can_do_validation6 && - (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) || - NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) || - NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) { - DEBUG(3,("Got a DC that can not do validation level 6, " - "retrying with level 3\n")); - domain->can_do_validation6 = false; - retry = true; - continue; - } /* * we increment this after the "feature negotiation" @@ -1428,6 +1320,30 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, retry = true; } + if (NT_STATUS_EQUAL(result, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) { + /* + * Got DCERPC_FAULT_OP_RNG_ERROR for SamLogon + * (no Ex). This happens against old Samba + * DCs, if LogonSamLogonEx() fails with an error + * e.g. NT_STATUS_NO_SUCH_USER or NT_STATUS_WRONG_PASSWORD. + * + * The server will log something like this: + * api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX. + * + * This sets the whole connection into a fault_state mode + * and all following request get NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE. + * + * This also happens to our retry with LogonSamLogonWithFlags() + * and LogonSamLogon(). + * + * In order to recover from this situation, we need to + * drop the connection. + */ + invalidate_cm_connection(&domain->conn); + result = NT_STATUS_LOGON_FAILURE; + break; + } + } while ( (attempts < 2) && retry ); if (NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT)) { diff --git a/source3/wscript_build b/source3/wscript_build index 13d15c3..0d3ba8e 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -671,8 +671,8 @@ bld.SAMBA3_LIBRARY('msrpc3', deps='''ndr ndr-standard RPC_NDR_EPMAPPER NTLMSSP_COMMON COMMON_SCHANNEL LIBCLI_AUTH LIBTSOCKET gse dcerpc-binding - libsmb - ndr-table''', + libsmb ndr-table NETLOGON_CREDS_CLI + ''', vars=locals(), private_library=True) @@ -1114,7 +1114,7 @@ bld.SAMBA3_LIBRARY('libcli_lsa3', bld.SAMBA3_LIBRARY('libcli_netlogon3', source=LIBCLI_NETLOGON_SRC, - deps='RPC_NDR_NETLOGON INIT_NETLOGON cliauth param', + deps='msrpc3 RPC_NDR_NETLOGON INIT_NETLOGON cliauth param NETLOGON_CREDS_CLI', private_library=True) bld.SAMBA3_LIBRARY('cli_spoolss', -- 1.9.3 From 0b489bffb452e05d595abc2894532100162a4e8c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 17:03:00 +0200 Subject: [PATCH 175/249] s3:rpc_client: use netlogon_creds_cli_auth_level() in cli_rpc_pipe_open_schannel_with_key() This means the auth level is now based on the "winbindd sealed pipes" option, defaulting to "yes" and DCERPC_AUTH_LEVEL_PRIVACY. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 5adfc5f9f737c003b84b0187fa17b9fc3784442e) --- source3/libnet/libnet_join.c | 1 - source3/rpc_client/cli_pipe.c | 4 +++- source3/rpc_client/cli_pipe.h | 1 - source3/rpc_client/cli_pipe_schannel.c | 2 +- source3/winbindd/winbindd_cm.c | 5 +---- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 5dc620f..b2805ee 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -1278,7 +1278,6 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, status = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, netbios_domain_name, netlogon_pipe->netlogon_creds, &pipe_hnd); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index fe1613d..31cd7f5 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3023,7 +3023,6 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, const struct ndr_interface_table *table, enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, const char *domain, struct netlogon_creds_cli_context *netlogon_creds, struct rpc_pipe_client **_rpccli) @@ -3031,6 +3030,7 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct rpc_pipe_client *rpccli; struct pipe_auth_data *rpcauth; struct netlogon_creds_CredentialState *creds = NULL; + enum dcerpc_AuthLevel auth_level; NTSTATUS status; const char *target_service = table->authservices->names[0]; int rpc_pipe_bind_dbglvl = 0; @@ -3048,6 +3048,8 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return status; } + auth_level = netlogon_creds_cli_auth_level(netlogon_creds); + status = rpccli_generic_bind_data(rpccli, DCERPC_AUTH_TYPE_SCHANNEL, auth_level, diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index cf0c5c6..c21c55d 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -94,7 +94,6 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, const struct ndr_interface_table *table, enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, const char *domain, struct netlogon_creds_cli_context *netlogon_creds, struct rpc_pipe_client **presult); diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index e3d65c8..8f9161f 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -112,7 +112,7 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, } status = cli_rpc_pipe_open_schannel_with_key( - cli, table, transport, auth_level, domain, + cli, table, transport, domain, netlogon_pipe->netlogon_creds, &result); diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index e0d1d0c..1546002 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2428,7 +2428,6 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, } status = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_samr, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, domain->name, p_creds, &conn->samr_pipe); if (!NT_STATUS_IS_OK(status)) { @@ -2561,7 +2560,6 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain, status = cli_rpc_pipe_open_schannel_with_key(conn->cli, &ndr_table_lsarpc, NCACN_IP_TCP, - DCERPC_AUTH_LEVEL_PRIVACY, domain->name, creds, &conn->lsa_pipe_tcp); @@ -2659,7 +2657,6 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, } result = cli_rpc_pipe_open_schannel_with_key (conn->cli, &ndr_table_lsarpc, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, domain->name, p_creds, &conn->lsa_pipe); if (!NT_STATUS_IS_OK(result)) { @@ -2839,7 +2836,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, result = cli_rpc_pipe_open_schannel_with_key( conn->cli, &ndr_table_netlogon, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, domain->name, + domain->name, netlogon_pipe->netlogon_creds, &conn->netlogon_pipe); -- 1.9.3 From 0f19f3b64e4f0b969eec4f2048df7c40be661e82 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 7 Aug 2013 11:27:25 +0200 Subject: [PATCH 176/249] s3:rpc_client: add rpccli_{create,setup}_netlogon_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 14ceb7b501fce6623be284cbcceb573fd2e10d3a) --- source3/rpc_client/cli_netlogon.c | 105 ++++++++++++++++++++++++++++++++++++++ source3/rpc_client/cli_netlogon.h | 16 ++++++ 2 files changed, 121 insertions(+) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index fcd24d6..89aec37 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -21,15 +21,19 @@ */ #include "includes.h" +#include "libsmb/libsmb.h" #include "rpc_client/rpc_client.h" +#include "rpc_client/cli_pipe.h" #include "../libcli/auth/libcli_auth.h" #include "../libcli/auth/netlogon_creds_cli.h" #include "../librpc/gen_ndr/ndr_netlogon_c.h" +#include "../librpc/gen_ndr/schannel.h" #include "rpc_client/cli_netlogon.h" #include "rpc_client/init_netlogon.h" #include "rpc_client/util_netlogon.h" #include "../libcli/security/security.h" #include "lib/param/param.h" +#include "libcli/smb/smbXcli_base.h" /**************************************************************************** Wrapper function that uses the auth and auth2 calls to set up a NETLOGON @@ -124,6 +128,107 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, return NT_STATUS_OK; } +NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, + const char *server_netbios_domain, + const char *client_account, + enum netr_SchannelType sec_chan_type, + struct messaging_context *msg_ctx, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **netlogon_creds) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct loadparm_context *lp_ctx; + NTSTATUS status; + + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + status = netlogon_creds_cli_context_global(lp_ctx, + msg_ctx, + client_account, + sec_chan_type, + server_computer, + server_netbios_domain, + mem_ctx, netlogon_creds); + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + +NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, + struct netlogon_creds_cli_context *netlogon_creds, + bool force_reauth, + struct samr_Password current_nt_hash, + const struct samr_Password *previous_nt_hash) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct rpc_pipe_client *netlogon_pipe = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + NTSTATUS status; + + status = netlogon_creds_cli_get(netlogon_creds, + frame, &creds); + if (NT_STATUS_IS_OK(status)) { + const char *action = "using"; + + if (force_reauth) { + action = "overwrite"; + } + + DEBUG(5,("%s: %s cached netlogon_creds cli[%s/%s] to %s\n", + __FUNCTION__, action, + creds->account_name, creds->computer_name, + smbXcli_conn_remote_name(cli->conn))); + if (!force_reauth) { + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + TALLOC_FREE(creds); + } + + status = cli_rpc_pipe_open_noauth(cli, + &ndr_table_netlogon, + &netlogon_pipe); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("%s: failed to open noauth netlogon connection to %s - %s\n", + __FUNCTION__, + smbXcli_conn_remote_name(cli->conn), + nt_errstr(status))); + TALLOC_FREE(frame); + return status; + } + talloc_steal(frame, netlogon_pipe); + + status = netlogon_creds_cli_auth(netlogon_creds, + netlogon_pipe->binding_handle, + current_nt_hash, + previous_nt_hash); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + status = netlogon_creds_cli_get(netlogon_creds, + frame, &creds); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return NT_STATUS_INTERNAL_ERROR; + } + + DEBUG(5,("%s: using new netlogon_creds cli[%s/%s] to %s\n", + __FUNCTION__, + creds->account_name, creds->computer_name, + smbXcli_conn_remote_name(cli->conn))); + + TALLOC_FREE(frame); + return NT_STATUS_OK; +} + /* Logon domain user */ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index ad59d5b..82e0923 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -23,6 +23,10 @@ #ifndef _RPC_CLIENT_CLI_NETLOGON_H_ #define _RPC_CLIENT_CLI_NETLOGON_H_ +struct cli_state; +struct messaging_context; +struct netlogon_creds_cli_context; + /* The following definitions come from rpc_client/cli_netlogon.c */ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, @@ -33,6 +37,18 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, const unsigned char machine_pwd[16], enum netr_SchannelType sec_chan_type, uint32_t *neg_flags_inout); +NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, + const char *server_netbios_domain, + const char *client_account, + enum netr_SchannelType sec_chan_type, + struct messaging_context *msg_ctx, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **netlogon_creds); +NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, + struct netlogon_creds_cli_context *netlogon_creds, + bool force_reauth, + struct samr_Password current_nt_hash, + const struct samr_Password *previous_nt_hash); NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 logon_parameters, -- 1.9.3 From de0ed0882a458e52ef232e7d44234bf393311fc0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Dec 2013 20:05:56 +0100 Subject: [PATCH 177/249] s3:rpc_client: add rpccli_pre_open_netlogon_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3c025af657899c9a2ff14f868c03ff72ab74cf8e) --- source3/rpc_client/cli_netlogon.c | 21 +++++++++++++++++++++ source3/rpc_client/cli_netlogon.h | 1 + 2 files changed, 22 insertions(+) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 89aec37..9342fc3 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -128,6 +128,27 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, return NT_STATUS_OK; } +NTSTATUS rpccli_pre_open_netlogon_creds(void) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct loadparm_context *lp_ctx; + NTSTATUS status; + + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + status = netlogon_creds_cli_open_global_db(lp_ctx); + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, const char *server_netbios_domain, const char *client_account, diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index 82e0923..3096c48 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -37,6 +37,7 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, const unsigned char machine_pwd[16], enum netr_SchannelType sec_chan_type, uint32_t *neg_flags_inout); +NTSTATUS rpccli_pre_open_netlogon_creds(void); NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, const char *server_netbios_domain, const char *client_account, -- 1.9.3 From f4f7df785d1641f1e21ad8374140715fd41be07a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Aug 2013 14:07:43 +0200 Subject: [PATCH 178/249] s3:rpc_client: remove unused rpccli_netlogon_sam_network_logon_ex() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a07cc9a1c6ab8fee516e069a6f90bb48a7abf875) --- source3/rpc_client/cli_netlogon.c | 27 --------------------------- source3/rpc_client/cli_netlogon.h | 12 ------------ 2 files changed, 39 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 9342fc3..253d060 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -524,33 +524,6 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, return NT_STATUS_OK; } -NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - uint16_t validation_level, - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **info3) -{ - return rpccli_netlogon_sam_network_logon(cli, - mem_ctx, - logon_parameters, - server, - username, - domain, - workstation, - chal, - validation_level, - lm_response, - nt_response, - info3); -} - /********************************************************* Change the domain password on the PDC. diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index 3096c48..f10e5c7 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -71,18 +71,6 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, DATA_BLOB lm_response, DATA_BLOB nt_response, struct netr_SamInfo3 **info3); -NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - uint16_t validation_level, - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **info3); NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *account_name, -- 1.9.3 From b250859baf6c720e636c2435b0593af83acf6acc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Aug 2013 14:36:24 +0200 Subject: [PATCH 179/249] s3:rpc_client: add rpccli_netlogon_network_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 5196493c9e599b741417b119b48188ba0d646a37) --- source3/rpc_client/cli_netlogon.c | 103 ++++++++++++++++++++++++++++++++++++++ source3/rpc_client/cli_netlogon.h | 14 ++++++ 2 files changed, 117 insertions(+) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 253d060..e335423 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -524,6 +524,109 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, return NT_STATUS_OK; } +NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + TALLOC_CTX *mem_ctx, + uint32_t logon_parameters, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + uint8_t *authoritative, + uint32_t *flags, + struct netr_SamInfo3 **info3) +{ + NTSTATUS status; + const char *workstation_name_slash; + union netr_LogonLevel *logon = NULL; + struct netr_NetworkInfo *network_info; + uint16_t validation_level = 0; + union netr_Validation *validation = NULL; + uint8_t _authoritative = 0; + uint32_t _flags = 0; + struct netr_ChallengeResponse lm; + struct netr_ChallengeResponse nt; + + *info3 = NULL; + + if (authoritative == NULL) { + authoritative = &_authoritative; + } + if (flags == NULL) { + flags = &_flags; + } + + ZERO_STRUCT(lm); + ZERO_STRUCT(nt); + + logon = talloc_zero(mem_ctx, union netr_LogonLevel); + if (!logon) { + return NT_STATUS_NO_MEMORY; + } + + network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); + if (!network_info) { + return NT_STATUS_NO_MEMORY; + } + + if (workstation[0] != '\\' && workstation[1] != '\\') { + workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); + } else { + workstation_name_slash = workstation; + } + + if (!workstation_name_slash) { + DEBUG(0, ("talloc_asprintf failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + /* Initialise input parameters */ + + lm.data = lm_response.data; + lm.length = lm_response.length; + nt.data = nt_response.data; + nt.length = nt_response.length; + + network_info->identity_info.domain_name.string = domain; + network_info->identity_info.parameter_control = logon_parameters; + network_info->identity_info.logon_id_low = 0xdead; + network_info->identity_info.logon_id_high = 0xbeef; + network_info->identity_info.account_name.string = username; + network_info->identity_info.workstation.string = workstation_name_slash; + + memcpy(network_info->challenge, chal, 8); + network_info->nt = nt; + network_info->lm = lm; + + logon->network = network_info; + + /* Marshall data and send request */ + + status = netlogon_creds_cli_LogonSamLogon(creds, + binding_handle, + NetlogonNetworkInformation, + logon, + mem_ctx, + &validation_level, + &validation, + authoritative, + flags); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = map_validation_to_info3(mem_ctx, + validation_level, validation, + info3); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + /********************************************************* Change the domain password on the PDC. diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index f10e5c7..54ed7ae 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -26,6 +26,7 @@ struct cli_state; struct messaging_context; struct netlogon_creds_cli_context; +struct dcerpc_binding_handle; /* The following definitions come from rpc_client/cli_netlogon.c */ @@ -71,6 +72,19 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, DATA_BLOB lm_response, DATA_BLOB nt_response, struct netr_SamInfo3 **info3); +NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + TALLOC_CTX *mem_ctx, + uint32_t logon_parameters, + const char *username, + const char *domain, + const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + uint8_t *authoritative, + uint32_t *flags, + struct netr_SamInfo3 **info3); NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *account_name, -- 1.9.3 From 2488e78fdf3058bf3a48c2086afd0f3248a43417 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Aug 2013 14:56:06 +0200 Subject: [PATCH 180/249] s3:rpc_client: add rpccli_netlogon_password_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit b7dc3fb20468aa67ea7ddc1cea21fbe458e74565) --- source3/rpc_client/cli_netlogon.c | 133 ++++++++++++++++++++++++++++++++++++++ source3/rpc_client/cli_netlogon.h | 8 +++ 2 files changed, 141 insertions(+) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index e335423..a9f8604 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -376,6 +376,139 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, return NT_STATUS_OK; } +NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + uint32_t logon_parameters, + const char *domain, + const char *username, + const char *password, + const char *workstation, + enum netr_LogonInfoClass logon_type) +{ + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + union netr_LogonLevel *logon; + uint16_t validation_level = 0; + union netr_Validation *validation = NULL; + uint8_t authoritative = 0; + uint32_t flags = 0; + char *workstation_slash = NULL; + + logon = talloc_zero(frame, union netr_LogonLevel); + if (logon == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + if (workstation == NULL) { + workstation = lp_netbios_name(); + } + + workstation_slash = talloc_asprintf(frame, "\\\\%s", workstation); + if (workstation_slash == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + /* Initialise input parameters */ + + switch (logon_type) { + case NetlogonInteractiveInformation: { + + struct netr_PasswordInfo *password_info; + + struct samr_Password lmpassword; + struct samr_Password ntpassword; + + password_info = talloc_zero(frame, struct netr_PasswordInfo); + if (password_info == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); + + password_info->identity_info.domain_name.string = domain; + password_info->identity_info.parameter_control = logon_parameters; + password_info->identity_info.logon_id_low = 0xdead; + password_info->identity_info.logon_id_high = 0xbeef; + password_info->identity_info.account_name.string = username; + password_info->identity_info.workstation.string = workstation_slash; + + password_info->lmpassword = lmpassword; + password_info->ntpassword = ntpassword; + + logon->password = password_info; + + break; + } + case NetlogonNetworkInformation: { + struct netr_NetworkInfo *network_info; + uint8 chal[8]; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + struct netr_ChallengeResponse lm; + struct netr_ChallengeResponse nt; + + ZERO_STRUCT(lm); + ZERO_STRUCT(nt); + + network_info = talloc_zero(frame, struct netr_NetworkInfo); + if (network_info == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + generate_random_buffer(chal, 8); + + SMBencrypt(password, chal, local_lm_response); + SMBNTencrypt(password, chal, local_nt_response); + + lm.length = 24; + lm.data = local_lm_response; + + nt.length = 24; + nt.data = local_nt_response; + + network_info->identity_info.domain_name.string = domain; + network_info->identity_info.parameter_control = logon_parameters; + network_info->identity_info.logon_id_low = 0xdead; + network_info->identity_info.logon_id_high = 0xbeef; + network_info->identity_info.account_name.string = username; + network_info->identity_info.workstation.string = workstation_slash; + + memcpy(network_info->challenge, chal, 8); + network_info->nt = nt; + network_info->lm = lm; + + logon->network = network_info; + + break; + } + default: + DEBUG(0, ("switch value %d not supported\n", + logon_type)); + TALLOC_FREE(frame); + return NT_STATUS_INVALID_INFO_CLASS; + } + + status = netlogon_creds_cli_LogonSamLogon(creds, + binding_handle, + logon_type, + logon, + frame, + &validation_level, + &validation, + &authoritative, + &flags); + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, uint16_t validation_level, union netr_Validation *validation, diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index 54ed7ae..d4c6670 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -60,6 +60,14 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, const char *workstation, uint16_t validation_level, int logon_type); +NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, + struct dcerpc_binding_handle *binding_handle, + uint32_t logon_parameters, + const char *domain, + const char *username, + const char *password, + const char *workstation, + enum netr_LogonInfoClass logon_type); NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 logon_parameters, -- 1.9.3 From 10c272f991643913358efd5fefb28fc1ce307c70 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Dec 2013 20:06:14 +0100 Subject: [PATCH 181/249] s3:winbindd: call rpccli_pre_open_netlogon_creds() in the parent This opens the CLEAR_IF_FIRST tdb in the long living parent. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 07126b6fb22cebce660d1d1a4f0f9fb905064aa0) --- source3/winbindd/winbindd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 69a17bf..a90c8fe 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -31,6 +31,7 @@ #include "../librpc/gen_ndr/srv_lsa.h" #include "../librpc/gen_ndr/srv_samr.h" #include "secrets.h" +#include "rpc_client/cli_netlogon.h" #include "idmap.h" #include "lib/addrchange.h" #include "serverid.h" @@ -1538,6 +1539,13 @@ int main(int argc, char **argv, char **envp) return False; } + status = rpccli_pre_open_netlogon_creds(); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n", + nt_errstr(status))); + exit(1); + } + /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ -- 1.9.3 From 4cb4ec2065f1f8b3598eb37ca24ce0f8fdf567aa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 7 Aug 2013 11:32:44 +0200 Subject: [PATCH 182/249] s3:winbindd: make use of rpccli_{create,setup}_netlogon_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 22e4e2c1d1252e434cb928d4530c378a62a64138) --- source3/winbindd/winbindd.h | 3 + source3/winbindd/winbindd_cm.c | 125 ++++++++++++++++++++--------------- source3/winbindd/winbindd_dual_srv.c | 1 + 3 files changed, 77 insertions(+), 52 deletions(-) diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index b5fc010..8f89e27 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -116,6 +116,9 @@ struct winbindd_cm_conn { struct policy_handle lsa_policy; struct rpc_pipe_client *netlogon_pipe; + struct netlogon_creds_cli_context *netlogon_creds; + uint32_t netlogon_flags; + bool netlogon_force_reauth; }; /* Async child */ diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 1546002..7b6cc96 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -79,6 +79,7 @@ #include "auth/gensec/gensec.h" #include "../libcli/smb/smbXcli_base.h" #include "lib/param/loadparm.h" +#include "libcli/auth/netlogon_creds_cli.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -1826,6 +1827,9 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn) } conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + conn->netlogon_force_reauth = false; + conn->netlogon_flags = 0; + TALLOC_FREE(conn->netlogon_creds); if (conn->cli) { cli_shutdown(conn->cli); @@ -2292,8 +2296,18 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; struct rpc_pipe_client *netlogon_pipe; - if (lp_client_schannel() == False) { - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + *ppdc = NULL; + + if ((!IS_DC) && (!domain->primary)) { + return NT_STATUS_TRUSTED_DOMAIN_FAILURE; + } + + if (domain->conn.netlogon_creds != NULL) { + if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { + return NT_STATUS_TRUSTED_DOMAIN_FAILURE; + } + *ppdc = domain->conn.netlogon_creds; + return NT_STATUS_OK; } result = cm_connect_netlogon(domain, &netlogon_pipe); @@ -2301,14 +2315,15 @@ static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain, return result; } - /* Return a pointer to the struct netlogon_creds_CredentialState from the - netlogon pipe. */ + if (domain->conn.netlogon_creds == NULL) { + return NT_STATUS_TRUSTED_DOMAIN_FAILURE; + } - if (!domain->conn.netlogon_pipe->netlogon_creds) { - return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */ + if (!(domain->conn.netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { + return NT_STATUS_TRUSTED_DOMAIN_FAILURE; } - *ppdc = domain->conn.netlogon_pipe->netlogon_creds; + *ppdc = domain->conn.netlogon_creds; return NT_STATUS_OK; } @@ -2747,14 +2762,16 @@ NTSTATUS cm_connect_lsat(struct winbindd_domain *domain, NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct rpc_pipe_client **cli) { + struct messaging_context *msg_ctx = winbind_messaging_context(); struct winbindd_cm_conn *conn; NTSTATUS result; - - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; - uint8_t mach_pwd[16]; enum netr_SchannelType sec_chan_type; + const char *_account_name; const char *account_name; - struct rpc_pipe_client *netlogon_pipe = NULL; + struct samr_Password current_nt_hash; + struct samr_Password *previous_nt_hash = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + bool ok; *cli = NULL; @@ -2771,60 +2788,68 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, } TALLOC_FREE(conn->netlogon_pipe); - - result = cli_rpc_pipe_open_noauth(conn->cli, - &ndr_table_netlogon, - &netlogon_pipe); - if (!NT_STATUS_IS_OK(result)) { - return result; - } + conn->netlogon_flags = 0; + TALLOC_FREE(conn->netlogon_creds); if ((!IS_DC) && (!domain->primary)) { - /* Clear the schannel request bit and drop down */ - neg_flags &= ~NETLOGON_NEG_SCHANNEL; goto no_schannel; } - if (lp_client_schannel() != False) { - neg_flags |= NETLOGON_NEG_SCHANNEL; + ok = get_trust_pw_hash(domain->name, + current_nt_hash.hash, + &_account_name, + &sec_chan_type); + if (!ok) { + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - if (!get_trust_pw_hash(domain->name, mach_pwd, &account_name, - &sec_chan_type)) - { - TALLOC_FREE(netlogon_pipe); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name); + if (account_name == NULL) { + return NT_STATUS_NO_MEMORY; } - result = rpccli_netlogon_setup_creds( - netlogon_pipe, - domain->dcname, /* server name. */ - domain->name, /* domain name */ - lp_netbios_name(), /* client name */ - account_name, /* machine account */ - mach_pwd, /* machine password */ - sec_chan_type, /* from get_trust_pw */ - &neg_flags); + result = rpccli_create_netlogon_creds(domain->dcname, + domain->name, + account_name, + sec_chan_type, + msg_ctx, + domain, + &conn->netlogon_creds); + if (!NT_STATUS_IS_OK(result)) { + SAFE_FREE(previous_nt_hash); + return result; + } + result = rpccli_setup_netlogon_creds(conn->cli, + conn->netlogon_creds, + conn->netlogon_force_reauth, + current_nt_hash, + previous_nt_hash); + conn->netlogon_force_reauth = false; + SAFE_FREE(previous_nt_hash); if (!NT_STATUS_IS_OK(result)) { - TALLOC_FREE(netlogon_pipe); return result; } - if ((lp_client_schannel() == True) && - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - DEBUG(3, ("Server did not offer schannel\n")); - TALLOC_FREE(netlogon_pipe); - return NT_STATUS_ACCESS_DENIED; + result = netlogon_creds_cli_get(conn->netlogon_creds, + talloc_tos(), + &creds); + if (!NT_STATUS_IS_OK(result)) { + return result; } + conn->netlogon_flags = creds->negotiate_flags; + TALLOC_FREE(creds); no_schannel: - if ((lp_client_schannel() == False) || - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + if (!(conn->netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { + result = cli_rpc_pipe_open_noauth(conn->cli, + &ndr_table_netlogon, + &conn->netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { + invalidate_cm_connection(conn); + return result; + } - /* We're done - just keep the existing connection to NETLOGON - * open */ - conn->netlogon_pipe = netlogon_pipe; *cli = conn->netlogon_pipe; return NT_STATUS_OK; } @@ -2837,12 +2862,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, result = cli_rpc_pipe_open_schannel_with_key( conn->cli, &ndr_table_netlogon, NCACN_NP, domain->name, - netlogon_pipe->netlogon_creds, + conn->netlogon_creds, &conn->netlogon_pipe); - - /* We can now close the initial netlogon pipe. */ - TALLOC_FREE(netlogon_pipe); - if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error " "was %s\n", nt_errstr(result))); diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index b873655..001591a 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -580,6 +580,7 @@ NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p, again: invalidate_cm_connection(&domain->conn); + domain->conn.netlogon_force_reauth = true; { struct rpc_pipe_client *netlogon_pipe; -- 1.9.3 From dc77edf0b74a88950f4de2472c05a73fcc629dc1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Aug 2013 13:07:45 +0200 Subject: [PATCH 183/249] s3:auth_domain: simplify connect_to_domain_password_server() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit d9d55f5406949187901476d673c7d6ff0fc165c2) --- source3/auth/auth_domain.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 9f88c4a..ae27bf0 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -47,16 +47,17 @@ static struct named_mutex *mutex; * **/ -static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, +static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, const char *domain, const char *dc_name, const struct sockaddr_storage *dc_ss, struct rpc_pipe_client **pipe_ret) { - NTSTATUS result; + NTSTATUS result; + struct cli_state *cli = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; - *cli = NULL; + *cli_ret = NULL; *pipe_ret = NULL; @@ -80,7 +81,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, } /* Attempt connection */ - result = cli_full_connection(cli, lp_netbios_name(), dc_name, dc_ss, 0, + result = cli_full_connection(&cli, lp_netbios_name(), dc_name, dc_ss, 0, "IPC$", "IPC", "", "", "", 0, SMB_SIGNING_DEFAULT); if (!NT_STATUS_IS_OK(result)) { @@ -89,11 +90,6 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, result = NT_STATUS_NO_LOGON_SERVERS; } - if (*cli) { - cli_shutdown(*cli); - *cli = NULL; - } - TALLOC_FREE(mutex); return result; } @@ -115,18 +111,17 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, if (lp_client_schannel()) { /* We also setup the creds chain in the open_schannel call. */ result = cli_rpc_pipe_open_schannel( - *cli, &ndr_table_netlogon, NCACN_NP, + cli, &ndr_table_netlogon, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); } else { result = cli_rpc_pipe_open_noauth( - *cli, &ndr_table_netlogon, &netlogon_pipe); + cli, &ndr_table_netlogon, &netlogon_pipe); } if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); - cli_shutdown(*cli); - *cli = NULL; + cli_shutdown(cli); TALLOC_FREE(mutex); return result; } @@ -145,8 +140,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); DEBUG(0, ("connect_to_domain_password_server: could not fetch " "trust account password for domain '%s'\n", domain)); - cli_shutdown(*cli); - *cli = NULL; + cli_shutdown(cli); TALLOC_FREE(mutex); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -161,8 +155,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); &neg_flags); if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(*cli); - *cli = NULL; + cli_shutdown(cli); TALLOC_FREE(mutex); return result; } @@ -172,14 +165,14 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); DEBUG(0, ("connect_to_domain_password_server: unable to open " "the domain client session to machine %s. Error " "was : %s.\n", dc_name, nt_errstr(result))); - cli_shutdown(*cli); - *cli = NULL; + cli_shutdown(cli); TALLOC_FREE(mutex); return NT_STATUS_NO_LOGON_SERVERS; } /* We exit here with the mutex *locked*. JRA */ + *cli_ret = cli; *pipe_ret = netlogon_pipe; return NT_STATUS_OK; -- 1.9.3 From 8fc2ffafd545dbc4af4c1ebab5fb631da18cade4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Aug 2013 15:01:10 +0200 Subject: [PATCH 184/249] s3:auth_domain: make use of rpccli_{create,setup}_netlogon_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 34e66780e573bebf4b971fb96e1ed8680c1488a9) --- source3/auth/auth_domain.c | 136 ++++++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 51 deletions(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index ae27bf0..bf2671c 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -27,6 +27,7 @@ #include "secrets.h" #include "passdb.h" #include "libsmb/libsmb.h" +#include "libcli/auth/netlogon_creds_cli.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -53,9 +54,20 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, const struct sockaddr_storage *dc_ss, struct rpc_pipe_client **pipe_ret) { + TALLOC_CTX *frame = talloc_stackframe(); + struct messaging_context *msg_ctx = server_messaging_context(); NTSTATUS result; struct cli_state *cli = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; + struct netlogon_creds_cli_context *netlogon_creds = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + uint32_t netlogon_flags = 0; + enum netr_SchannelType sec_chan_type = 0; + const char *_account_name = NULL; + const char *account_name = NULL; + struct samr_Password current_nt_hash; + struct samr_Password *previous_nt_hash = NULL; + bool ok; *cli_ret = NULL; @@ -77,6 +89,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, mutex = grab_named_mutex(NULL, dc_name, 10); if (mutex == NULL) { + TALLOC_FREE(frame); return NT_STATUS_NO_LOGON_SERVERS; } @@ -91,6 +104,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, } TALLOC_FREE(mutex); + TALLOC_FREE(frame); return result; } @@ -98,67 +112,85 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, * We now have an anonymous connection to IPC$ on the domain password server. */ - /* - * Even if the connect succeeds we need to setup the netlogon - * pipe here. We do this as we may just have changed the domain - * account password on the PDC and yet we may be talking to - * a BDC that doesn't have this replicated yet. In this case - * a successful connect to a DC needs to take the netlogon connect - * into account also. This patch from "Bjart Kvarme" . - */ + ok = get_trust_pw_hash(domain, + current_nt_hash.hash, + &_account_name, + &sec_chan_type); + if (!ok) { + cli_shutdown(cli); + TALLOC_FREE(mutex); + TALLOC_FREE(frame); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } - /* open the netlogon pipe. */ - if (lp_client_schannel()) { - /* We also setup the creds chain in the open_schannel call. */ - result = cli_rpc_pipe_open_schannel( - cli, &ndr_table_netlogon, NCACN_NP, - DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe); - } else { - result = cli_rpc_pipe_open_noauth( - cli, &ndr_table_netlogon, &netlogon_pipe); + account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name); + if (account_name == NULL) { + cli_shutdown(cli); + TALLOC_FREE(mutex); + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; } + result = rpccli_create_netlogon_creds(dc_name, + domain, + account_name, + sec_chan_type, + msg_ctx, + talloc_tos(), + &netlogon_creds); if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ -machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); cli_shutdown(cli); TALLOC_FREE(mutex); + TALLOC_FREE(frame); + SAFE_FREE(previous_nt_hash); return result; } - if (!lp_client_schannel()) { - /* We need to set up a creds chain on an unauthenticated netlogon pipe. */ - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | - NETLOGON_NEG_SUPPORTS_AES; - enum netr_SchannelType sec_chan_type = 0; - unsigned char machine_pwd[16]; - const char *account_name; - - if (!get_trust_pw_hash(domain, machine_pwd, &account_name, - &sec_chan_type)) - { - DEBUG(0, ("connect_to_domain_password_server: could not fetch " - "trust account password for domain '%s'\n", - domain)); - cli_shutdown(cli); - TALLOC_FREE(mutex); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } + result = rpccli_setup_netlogon_creds(cli, + netlogon_creds, + false, /* force_reauth */ + current_nt_hash, + previous_nt_hash); + SAFE_FREE(previous_nt_hash); + if (!NT_STATUS_IS_OK(result)) { + cli_shutdown(cli); + TALLOC_FREE(mutex); + TALLOC_FREE(frame); + return result; + } - result = rpccli_netlogon_setup_creds(netlogon_pipe, - dc_name, /* server name */ - domain, /* domain */ - lp_netbios_name(), /* client name */ - account_name, /* machine account name */ - machine_pwd, - sec_chan_type, - &neg_flags); - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(cli); - TALLOC_FREE(mutex); - return result; - } + result = netlogon_creds_cli_get(netlogon_creds, + talloc_tos(), + &creds); + if (!NT_STATUS_IS_OK(result)) { + cli_shutdown(cli); + TALLOC_FREE(mutex); + TALLOC_FREE(frame); + return result; + } + netlogon_flags = creds->negotiate_flags; + TALLOC_FREE(creds); + + if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) { + result = cli_rpc_pipe_open_schannel_with_key( + cli, &ndr_table_netlogon, NCACN_NP, + domain, netlogon_creds, &netlogon_pipe); + } else { + result = cli_rpc_pipe_open_noauth(cli, + &ndr_table_netlogon, + &netlogon_pipe); + } + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("connect_to_domain_password_server: " + "unable to open the domain client session to " + "machine %s. Flags[0x%08X] Error was : %s.\n", + dc_name, (unsigned)netlogon_flags, + nt_errstr(result))); + cli_shutdown(cli); + TALLOC_FREE(mutex); + TALLOC_FREE(frame); + return result; } if(!netlogon_pipe) { @@ -167,6 +199,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); "was : %s.\n", dc_name, nt_errstr(result))); cli_shutdown(cli); TALLOC_FREE(mutex); + TALLOC_FREE(frame); return NT_STATUS_NO_LOGON_SERVERS; } @@ -175,6 +208,7 @@ machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); *cli_ret = cli; *pipe_ret = netlogon_pipe; + TALLOC_FREE(frame); return NT_STATUS_OK; } -- 1.9.3 From 5cc57e577bc7d144176ffe6f21ed24a95661a861 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 27 Aug 2013 15:02:26 +0200 Subject: [PATCH 185/249] s3:auth_domain: make use of rpccli_netlogon_network_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 531bbf3aff3fb08aaf112b21038f20544db60b69) --- source3/auth/auth_domain.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index bf2671c..937841c 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -52,7 +52,8 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, const char *domain, const char *dc_name, const struct sockaddr_storage *dc_ss, - struct rpc_pipe_client **pipe_ret) + struct rpc_pipe_client **pipe_ret, + struct netlogon_creds_cli_context **creds_ret) { TALLOC_CTX *frame = talloc_stackframe(); struct messaging_context *msg_ctx = server_messaging_context(); @@ -72,6 +73,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, *cli_ret = NULL; *pipe_ret = NULL; + *creds_ret = NULL; /* TODO: Send a SAMLOGON request to determine whether this is a valid logonserver. We can avoid a 30-second timeout if the DC is down @@ -207,6 +209,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret, *cli_ret = cli; *pipe_ret = netlogon_pipe; + *creds_ret = netlogon_creds; TALLOC_FREE(frame); return NT_STATUS_OK; @@ -230,8 +233,11 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, struct netr_SamInfo3 *info3 = NULL; struct cli_state *cli = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; + struct netlogon_creds_cli_context *netlogon_creds = NULL; NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS; int i; + uint8_t authoritative = 0; + uint32_t flags = 0; /* * At this point, smb_apasswd points to the lanman response to @@ -248,7 +254,8 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, domain, dc_name, dc_ss, - &netlogon_pipe); + &netlogon_pipe, + &netlogon_creds); } if ( !NT_STATUS_IS_OK(nt_status) ) { @@ -268,18 +275,19 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, * in the info3 structure. */ - nt_status = rpccli_netlogon_sam_network_logon(netlogon_pipe, - mem_ctx, - user_info->logon_parameters, /* flags such as 'allow workstation logon' */ - dc_name, /* server name */ - user_info->client.account_name, /* user name logging on. */ - user_info->client.domain_name, /* domain name */ - user_info->workstation_name, /* workstation name */ - chal, /* 8 byte challenge. */ - 3, /* validation level */ - user_info->password.response.lanman, /* lanman 24 byte response */ - user_info->password.response.nt, /* nt 24 byte response */ - &info3); /* info3 out */ + nt_status = rpccli_netlogon_network_logon(netlogon_creds, + netlogon_pipe->binding_handle, + mem_ctx, + user_info->logon_parameters, /* flags such as 'allow workstation logon' */ + user_info->client.account_name, /* user name logging on. */ + user_info->client.domain_name, /* domain name */ + user_info->workstation_name, /* workstation name */ + chal, /* 8 byte challenge. */ + user_info->password.response.lanman, /* lanman 24 byte response */ + user_info->password.response.nt, /* nt 24 byte response */ + &authoritative, + &flags, + &info3); /* info3 out */ /* Let go as soon as possible so we avoid any potential deadlocks with winbind lookup up users or groups. */ -- 1.9.3 From 5da4eca4d30b3894426a4f7cb0512ae61c097cbc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 2 Sep 2013 19:32:23 +0200 Subject: [PATCH 186/249] s3:libnet_join: make use of rpccli_{create,setup}_netlogon_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 963800539cea7487fc6258f8ac8f7cacc3426b83) --- source3/libnet/libnet_join.c | 110 +++++++++++++++++++++++++++++++------------ source3/libnet/libnet_join.h | 5 +- source3/utils/net_rpc.c | 4 +- 3 files changed, 86 insertions(+), 33 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index b2805ee..6e653c3 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -40,6 +40,8 @@ #include "libsmb/libsmb.h" #include "../libcli/smb/smbXcli_base.h" #include "lib/param/loadparm.h" +#include "libcli/auth/netlogon_creds_cli.h" +#include "auth/credentials/credentials.h" /**************************************************************** ****************************************************************/ @@ -1189,38 +1191,52 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, /**************************************************************** ****************************************************************/ -NTSTATUS libnet_join_ok(const char *netbios_domain_name, - const char *machine_name, +NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx, + const char *netbios_domain_name, const char *dc_name, const bool use_kerberos) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | - NETLOGON_NEG_SUPPORTS_AES; + TALLOC_CTX *frame = talloc_stackframe(); struct cli_state *cli = NULL; - struct rpc_pipe_client *pipe_hnd = NULL; struct rpc_pipe_client *netlogon_pipe = NULL; + struct netlogon_creds_cli_context *netlogon_creds = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + uint32_t netlogon_flags = 0; + enum netr_SchannelType sec_chan_type = 0; NTSTATUS status; char *machine_password = NULL; - char *machine_account = NULL; + const char *machine_name = NULL; + const char *machine_account = NULL; int flags = 0; + struct samr_Password current_nt_hash; + struct samr_Password *previous_nt_hash = NULL; + bool ok; if (!dc_name) { + TALLOC_FREE(frame); return NT_STATUS_INVALID_PARAMETER; } if (!secrets_init()) { + TALLOC_FREE(frame); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - machine_password = secrets_fetch_machine_password(netbios_domain_name, - NULL, NULL); - if (!machine_password) { - return NT_STATUS_NO_TRUST_LSA_SECRET; + ok = get_trust_pw_clear(netbios_domain_name, + &machine_password, + &machine_name, + &sec_chan_type); + if (!ok) { + TALLOC_FREE(frame); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - if (asprintf(&machine_account, "%s$", machine_name) == -1) { + machine_account = talloc_asprintf(frame, "%s$", machine_name); + if (machine_account == NULL) { SAFE_FREE(machine_password); - return NT_STATUS_NO_MEMORY; + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(frame); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } if (use_kerberos) { @@ -1232,12 +1248,13 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, NULL, 0, "IPC$", "IPC", machine_account, - NULL, + netbios_domain_name, machine_password, flags, SMB_SIGNING_DEFAULT); - free(machine_account); - free(machine_password); + + E_md4hash(machine_password, current_nt_hash.hash); + SAFE_FREE(machine_password); if (!NT_STATUS_IS_OK(status)) { status = cli_full_connection(&cli, NULL, @@ -1252,36 +1269,65 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, } if (!NT_STATUS_IS_OK(status)) { + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(frame); return status; } - status = get_schannel_session_key(cli, netbios_domain_name, - &neg_flags, &netlogon_pipe); + status = rpccli_create_netlogon_creds(dc_name, + netbios_domain_name, + machine_account, + sec_chan_type, + msg_ctx, + frame, + &netlogon_creds); if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_NETWORK_RESPONSE)) { - cli_shutdown(cli); - return NT_STATUS_OK; - } + SAFE_FREE(previous_nt_hash); + cli_shutdown(cli); + TALLOC_FREE(frame); + return status; + } - DEBUG(0,("libnet_join_ok: failed to get schannel session " - "key from server %s for domain %s. Error was %s\n", - smbXcli_conn_remote_name(cli->conn), - netbios_domain_name, nt_errstr(status))); + status = rpccli_setup_netlogon_creds(cli, + netlogon_creds, + true, /* force_reauth */ + current_nt_hash, + previous_nt_hash); + SAFE_FREE(previous_nt_hash); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("connect_to_domain_password_server: " + "unable to open the domain client session to " + "machine %s. Flags[0x%08X] Error was : %s.\n", + dc_name, (unsigned)netlogon_flags, + nt_errstr(status))); + cli_shutdown(cli); + TALLOC_FREE(frame); + return status; + } + + status = netlogon_creds_cli_get(netlogon_creds, + talloc_tos(), + &creds); + if (!NT_STATUS_IS_OK(status)) { cli_shutdown(cli); + TALLOC_FREE(frame); return status; } + netlogon_flags = creds->negotiate_flags; + TALLOC_FREE(creds); - if (!lp_client_schannel()) { + if (!(netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { cli_shutdown(cli); + TALLOC_FREE(frame); return NT_STATUS_OK; } status = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon, NCACN_NP, netbios_domain_name, - netlogon_pipe->netlogon_creds, &pipe_hnd); + netlogon_creds, &netlogon_pipe); - cli_shutdown(cli); + TALLOC_FREE(netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("libnet_join_ok: failed to open schannel session " @@ -1289,9 +1335,13 @@ NTSTATUS libnet_join_ok(const char *netbios_domain_name, "Error was %s\n", smbXcli_conn_remote_name(cli->conn), netbios_domain_name, nt_errstr(status))); + cli_shutdown(cli); + TALLOC_FREE(frame); return status; } + cli_shutdown(cli); + TALLOC_FREE(frame); return NT_STATUS_OK; } @@ -1303,8 +1353,8 @@ static WERROR libnet_join_post_verify(TALLOC_CTX *mem_ctx, { NTSTATUS status; - status = libnet_join_ok(r->out.netbios_domain_name, - r->in.machine_name, + status = libnet_join_ok(r->in.msg_ctx, + r->out.netbios_domain_name, r->in.dc_name, r->in.use_kerberos); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/libnet/libnet_join.h b/source3/libnet/libnet_join.h index 58c33b2..b7e2f0b 100644 --- a/source3/libnet/libnet_join.h +++ b/source3/libnet/libnet_join.h @@ -23,8 +23,9 @@ /* The following definitions come from libnet/libnet_join.c */ -NTSTATUS libnet_join_ok(const char *netbios_domain_name, - const char *machine_name, +struct messaging_context; +NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx, + const char *netbios_domain_name, const char *dc_name, const bool use_kerberos); WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx, diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index dff8801..9de74c0 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -493,7 +493,9 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) } /* Display success or failure */ - status = libnet_join_ok(c->opt_workgroup, lp_netbios_name(), dc, + status = libnet_join_ok(c->msg_ctx, + c->opt_workgroup, + dc, c->opt_kerberos); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr,"Join to domain '%s' is not valid: %s\n", -- 1.9.3 From 0da8c0a71d08de50b614e5df69a61e00d0a9cd99 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Sep 2013 20:57:02 +0200 Subject: [PATCH 187/249] s3:libnet: use rpccli_{create,setup}_netlogon_creds() in libnet_join_joindomain_rpc_unsecure Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3a89eee03a95d4b142bf0830f40debc75bfa2e26) --- source3/libnet/libnet_join.c | 66 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 6e653c3..a87eb38 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -817,14 +817,17 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r, struct cli_state *cli) { - struct rpc_pipe_client *pipe_hnd = NULL; - unsigned char orig_trust_passwd_hash[16]; - unsigned char new_trust_passwd_hash[16]; + TALLOC_CTX *frame = talloc_stackframe(); + struct rpc_pipe_client *netlogon_pipe = NULL; + struct netlogon_creds_cli_context *netlogon_creds = NULL; + struct samr_Password current_nt_hash; + const char *account_name = NULL; NTSTATUS status; status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, - &pipe_hnd); + &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); return status; } @@ -832,22 +835,55 @@ static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx, r->in.machine_password = generate_random_password(mem_ctx, DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH, DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); - NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password); + if (r->in.machine_password == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } } - E_md4hash(r->in.machine_password, new_trust_passwd_hash); - /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */ - E_md4hash(r->in.admin_password, orig_trust_passwd_hash); + E_md4hash(r->in.admin_password, current_nt_hash.hash); - status = rpccli_netlogon_set_trust_password(pipe_hnd, mem_ctx, - r->in.machine_name, - orig_trust_passwd_hash, - r->in.machine_password, - new_trust_passwd_hash, - r->in.secure_channel_type); + account_name = talloc_asprintf(frame, "%s$", + r->in.machine_name); + if (account_name == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } - return status; + status = rpccli_create_netlogon_creds(netlogon_pipe->desthost, + r->in.domain_name, + account_name, + r->in.secure_channel_type, + r->in.msg_ctx, + frame, + &netlogon_creds); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + status = rpccli_setup_netlogon_creds(cli, + netlogon_creds, + true, /* force_reauth */ + current_nt_hash, + NULL); /* previous_nt_hash */ + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + status = netlogon_creds_cli_ServerPasswordSet(netlogon_creds, + netlogon_pipe->binding_handle, + r->in.machine_password, + NULL); /* new_version */ + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + TALLOC_FREE(frame); + return NT_STATUS_OK; } /**************************************************************** -- 1.9.3 From 9d192bc1d2dd06efada55792203aaed58b349ab9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 11 Sep 2013 10:06:41 +0200 Subject: [PATCH 188/249] s3:rpc_client: use rpccli_{create,setup}_netlogon_creds() in cli_rpc_pipe_open_schannel() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 94caf7e190563423914b653d0c2fc4a4abf1f899) --- source3/rpc_client/cli_pipe.h | 7 -- source3/rpc_client/cli_pipe_schannel.c | 162 ++++++++++++++------------------- 2 files changed, 66 insertions(+), 103 deletions(-) diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index c21c55d..2a76130 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -109,13 +109,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, DATA_BLOB *session_key); -/* The following definitions come from rpc_client/cli_pipe_schannel.c */ - -NTSTATUS get_schannel_session_key(struct cli_state *cli, - const char *domain, - uint32 *pneg_flags, - struct rpc_pipe_client **presult); - #endif /* _CLI_PIPE_H */ /* vim: set ts=8 sw=8 noet cindent ft=c.doxygen: */ diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index 8f9161f..1fcf62e 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -23,67 +23,15 @@ #include "../libcli/auth/schannel.h" #include "rpc_client/cli_netlogon.h" #include "rpc_client/cli_pipe.h" -#include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/rpc/dcerpc.h" #include "passdb.h" #include "libsmb/libsmb.h" -#include "auth/gensec/gensec.h" #include "../libcli/smb/smbXcli_base.h" +#include "libcli/auth/netlogon_creds_cli.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_CLI - -/**************************************************************************** - Get a the schannel session key out of an already opened netlogon pipe. - ****************************************************************************/ -static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe, - struct cli_state *cli, - const char *domain, - uint32 *pneg_flags) -{ - enum netr_SchannelType sec_chan_type = 0; - unsigned char machine_pwd[16]; - const char *machine_account; - NTSTATUS status; - - /* Get the machine account credentials from secrets.tdb. */ - if (!get_trust_pw_hash(domain, machine_pwd, &machine_account, - &sec_chan_type)) - { - DEBUG(0, ("get_schannel_session_key: could not fetch " - "trust account password for domain '%s'\n", - domain)); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - status = rpccli_netlogon_setup_creds(netlogon_pipe, - smbXcli_conn_remote_name(cli->conn), /* server name */ - domain, /* domain */ - lp_netbios_name(), /* client name */ - machine_account, /* machine account name */ - machine_pwd, - sec_chan_type, - pneg_flags); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("get_schannel_session_key_common: " - "rpccli_netlogon_setup_creds failed with result %s " - "to server %s, domain %s, machine account %s.\n", - nt_errstr(status), smbXcli_conn_remote_name(cli->conn), domain, - machine_account )); - return status; - } - - if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) { - DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n", - smbXcli_conn_remote_name(cli->conn))); - return NT_STATUS_INVALID_NETWORK_RESPONSE; - } - - return NT_STATUS_OK; -} - /**************************************************************************** Open a named pipe to an SMB server and bind using schannel (bind type 68). Fetch the session key ourselves using a temporary netlogon pipe. @@ -96,63 +44,85 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, const char *domain, struct rpc_pipe_client **presult) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | - NETLOGON_NEG_SUPPORTS_AES; - struct rpc_pipe_client *netlogon_pipe = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + struct messaging_context *msg_ctx = NULL; + const char *dc_name = smbXcli_conn_remote_name(cli->conn); struct rpc_pipe_client *result = NULL; NTSTATUS status; + struct netlogon_creds_cli_context *netlogon_creds = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + uint32_t netlogon_flags = 0; + enum netr_SchannelType sec_chan_type = 0; + const char *_account_name = NULL; + const char *account_name = NULL; + struct samr_Password current_nt_hash; + struct samr_Password *previous_nt_hash = NULL; + bool ok; + + ok = get_trust_pw_hash(domain, + current_nt_hash.hash, + &_account_name, + &sec_chan_type); + if (!ok) { + TALLOC_FREE(frame); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + account_name = talloc_asprintf(frame, "%s$", _account_name); + if (account_name == NULL) { + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + status = rpccli_create_netlogon_creds(dc_name, + domain, + account_name, + sec_chan_type, + msg_ctx, + frame, + &netlogon_creds); + if (!NT_STATUS_IS_OK(status)) { + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(frame); + return status; + } - status = get_schannel_session_key(cli, domain, &neg_flags, - &netlogon_pipe); + status = rpccli_setup_netlogon_creds(cli, + netlogon_creds, + false, /* force_reauth */ + current_nt_hash, + previous_nt_hash); + SAFE_FREE(previous_nt_hash); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session " - "key from server %s for domain %s.\n", - smbXcli_conn_remote_name(cli->conn), domain )); + TALLOC_FREE(frame); return status; } + status = netlogon_creds_cli_get(netlogon_creds, + frame, + &creds); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + netlogon_flags = creds->negotiate_flags; + TALLOC_FREE(creds); + + if (!(netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) { + TALLOC_FREE(frame); + return NT_STATUS_DOWNGRADE_DETECTED; + } + status = cli_rpc_pipe_open_schannel_with_key( cli, table, transport, domain, - netlogon_pipe->netlogon_creds, + netlogon_creds, &result); - /* Now we've bound using the session key we can close the netlog pipe. */ - TALLOC_FREE(netlogon_pipe); - if (NT_STATUS_IS_OK(status)) { *presult = result; } + TALLOC_FREE(frame); return status; } - -/**************************************************************************** - Open a netlogon pipe and get the schannel session key. - Now exposed to external callers. - ****************************************************************************/ - - -NTSTATUS get_schannel_session_key(struct cli_state *cli, - const char *domain, - uint32 *pneg_flags, - struct rpc_pipe_client **presult) -{ - struct rpc_pipe_client *netlogon_pipe = NULL; - NTSTATUS status; - - status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon, - &netlogon_pipe); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = get_schannel_session_key_common(netlogon_pipe, cli, domain, - pneg_flags); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(netlogon_pipe); - return status; - } - - *presult = netlogon_pipe; - return NT_STATUS_OK; -} -- 1.9.3 From 5fba6641f79a14c208c5947886c005a87b9f3256 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:24:44 +0200 Subject: [PATCH 189/249] s3:rpcclient: add rpcclient_msg_ctx Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a1c468e1d75d490f0e531feb08188ddc3f0d77b5) --- source3/rpcclient/rpcclient.c | 5 +++++ source3/rpcclient/rpcclient.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 0cbec20..39bf613 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -33,6 +33,7 @@ #include "libsmb/libsmb.h" #include "auth/gensec/gensec.h" #include "../libcli/smb/smbXcli_base.h" +#include "messages.h" enum pipe_auth_type_spnego { PIPE_AUTH_TYPE_SPNEGO_NONE = 0, @@ -48,6 +49,7 @@ static enum dcerpc_AuthLevel pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE; static unsigned int timeout = 0; static enum dcerpc_transport_t default_transport = NCACN_NP; +struct messaging_context *rpcclient_msg_ctx; struct user_auth_info *rpcclient_auth_info; /* List to hold groups of commands. @@ -985,6 +987,9 @@ out_free: /* We must load interfaces after we load the smb.conf */ load_interfaces(); + rpcclient_msg_ctx = messaging_init(talloc_autofree_context(), + samba_tevent_context_init(talloc_autofree_context())); + /* * Get password * from stdin if necessary diff --git a/source3/rpcclient/rpcclient.h b/source3/rpcclient/rpcclient.h index 762c54a..219da2a 100644 --- a/source3/rpcclient/rpcclient.h +++ b/source3/rpcclient/rpcclient.h @@ -41,4 +41,6 @@ struct cmd_set { const char *usage; }; +extern struct messaging_context *rpcclient_msg_ctx; + #endif /* RPCCLIENT_H */ -- 1.9.3 From c6e02d60ef12431cd1a5615fcf514548e86d6dc8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:29:30 +0200 Subject: [PATCH 190/249] s3:rpcclient: add rpcclient_netlogon_creds Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 1696b127c61fea76fce3d992632a822ed78de07c) --- source3/rpcclient/rpcclient.c | 3 +++ source3/rpcclient/rpcclient.h | 1 + 2 files changed, 4 insertions(+) diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 39bf613..a875ff5 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -51,6 +51,7 @@ static enum dcerpc_transport_t default_transport = NCACN_NP; struct messaging_context *rpcclient_msg_ctx; struct user_auth_info *rpcclient_auth_info; +struct netlogon_creds_cli_context *rpcclient_netlogon_creds; /* List to hold groups of commands. * @@ -797,6 +798,8 @@ static NTSTATUS do_cmd(struct cli_state *cli, } } + rpcclient_netlogon_creds = cmd_entry->rpc_pipe->netlogon_creds; + /* Run command */ if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { diff --git a/source3/rpcclient/rpcclient.h b/source3/rpcclient/rpcclient.h index 219da2a..9288249 100644 --- a/source3/rpcclient/rpcclient.h +++ b/source3/rpcclient/rpcclient.h @@ -42,5 +42,6 @@ struct cmd_set { }; extern struct messaging_context *rpcclient_msg_ctx; +extern struct netlogon_creds_cli_context *rpcclient_netlogon_creds; #endif /* RPCCLIENT_H */ -- 1.9.3 From 849cb578d3aa38e7d6508353914d39501cd6b2c8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:57:09 +0200 Subject: [PATCH 191/249] s3:rpcclient: remove unused rpccli_netlogon_setup_creds() from cmd_netlogon_database_redo() rpccli_netlogon_setup_creds() is already called in the main do_cmd() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit fb13b002d599049f229d2014e1b94f82952b7150) --- source3/rpcclient/cmd_netlogon.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 2e0b5e5..8a865a9 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -1141,12 +1141,8 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS result; const char *server_name = cli->desthost; - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | - NETLOGON_NEG_SUPPORTS_AES; struct netr_Authenticator clnt_creds, srv_cred; struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; - unsigned char trust_passwd_hash[16]; - enum netr_SchannelType sec_channel_type = 0; struct netr_ChangeLogEntry e; uint32_t rid = 500; struct dcerpc_binding_handle *b = cli->binding_handle; @@ -1161,25 +1157,10 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, sscanf(argv[1], "%d", &rid); } - if (!secrets_fetch_trust_account_password(lp_workgroup(), - trust_passwd_hash, - NULL, &sec_channel_type)) { + if (cli->netlogon_creds == NULL) { return NT_STATUS_UNSUCCESSFUL; } - status = rpccli_netlogon_setup_creds(cli, - server_name, /* server name */ - lp_workgroup(), /* domain */ - lp_netbios_name(), /* client name */ - lp_netbios_name(), /* machine account name */ - trust_passwd_hash, - sec_channel_type, - &neg_flags); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = netlogon_creds_cli_lock(cli->netlogon_creds, mem_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { -- 1.9.3 From df5ce2ceb4c41e2a952cd9f011626028f8d230ff Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 19:00:22 +0200 Subject: [PATCH 192/249] s3:rpcclient: make use of rpcclient_netlogon_creds instead of cli->netlogon_creds Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3bf77812e80b50f254af64e4935301719f78987e) --- source3/rpcclient/cmd_netlogon.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 8a865a9..59e1e4e 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -633,7 +633,11 @@ static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; struct netlogon_creds_CredentialState *creds = NULL; - status = netlogon_creds_cli_lock(cli->netlogon_creds, + if (rpcclient_netlogon_creds == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + + status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, mem_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { return status; @@ -712,7 +716,11 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; struct netlogon_creds_CredentialState *creds = NULL; - status = netlogon_creds_cli_lock(cli->netlogon_creds, + if (rpcclient_netlogon_creds == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + + status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, mem_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { return status; @@ -1157,11 +1165,11 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, sscanf(argv[1], "%d", &rid); } - if (cli->netlogon_creds == NULL) { + if (rpcclient_netlogon_creds == NULL) { return NT_STATUS_UNSUCCESSFUL; } - status = netlogon_creds_cli_lock(cli->netlogon_creds, + status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, mem_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { return status; @@ -1223,7 +1231,11 @@ static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli, ZERO_STRUCT(return_authenticator); - status = netlogon_creds_cli_lock(cli->netlogon_creds, + if (rpcclient_netlogon_creds == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + + status = netlogon_creds_cli_lock(rpcclient_netlogon_creds, mem_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { return status; -- 1.9.3 From 4e9d9abc0bae5ca08c3a91cc5d1b2bacffc6cbfc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 19:59:11 +0200 Subject: [PATCH 193/249] s3:net_rpc: add net_context->netlogon_creds Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit d1340c20b0900f54e2c73c4a363f45988b1ba097) --- source3/utils/net.h | 1 + source3/utils/net_rpc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/source3/utils/net.h b/source3/utils/net.h index e97734a..ce19c57 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -90,6 +90,7 @@ struct net_context { bool smb_encrypt; struct libnetapi_ctx *netapi_ctx; struct messaging_context *msg_ctx; + struct netlogon_creds_cli_context *netlogon_creds; bool display_usage; void *private_data; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 9de74c0..3bf3f30 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -201,6 +201,7 @@ int run_rpc_command(struct net_context *c, nt_errstr(nt_status) )); goto fail; } + c->netlogon_creds = pipe_hnd->netlogon_creds; } else { if (conn_flags & NET_FLAGS_SEAL) { nt_status = cli_rpc_pipe_open_generic_auth( -- 1.9.3 From 7a4535c1e61de498230abd1f99bfe875ae59c2e0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 15 Sep 2013 13:19:52 +0200 Subject: [PATCH 194/249] s3:libsmb: add trust_pw_change() This protects the password change using a domain specific g_lock, so multiple parts 'net rpc', 'rpcclient', 'winbindd', 'wbinfo --change-secret' even on multiple cluster nodes doesn't race anymore. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 16c6e4992fa882207eeaff0a1c4d9fe217be48b7) --- source3/include/proto.h | 8 ++ source3/libsmb/trusts_util.c | 179 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) diff --git a/source3/include/proto.h b/source3/include/proto.h index 216a377..edda119 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -984,6 +984,14 @@ void update_trustdom_cache( void ); NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *domain) ; +struct netlogon_creds_cli_context; +struct messaging_context; +struct dcerpc_binding_handle; +NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, + struct messaging_context *msg_ctx, + struct dcerpc_binding_handle *b, + const char *domain, + bool force); /* The following definitions come from param/loadparm.c */ diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 52fb481..b1bc006 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -20,12 +20,15 @@ #include "includes.h" #include "../libcli/auth/libcli_auth.h" +#include "../libcli/auth/netlogon_creds_cli.h" #include "rpc_client/cli_netlogon.h" #include "rpc_client/cli_pipe.h" #include "../librpc/gen_ndr/ndr_netlogon.h" #include "secrets.h" #include "passdb.h" #include "libsmb/libsmb.h" +#include "source3/include/messages.h" +#include "source3/include/g_lock.h" /********************************************************* Change the domain password on the PDC. @@ -113,3 +116,179 @@ NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, return nt_status; } + +struct trust_pw_change_state { + struct g_lock_ctx *g_ctx; + char *g_lock_key; +}; + +static int trust_pw_change_state_destructor(struct trust_pw_change_state *state) +{ + g_lock_unlock(state->g_ctx, state->g_lock_key); + return 0; +} + +NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context, + struct messaging_context *msg_ctx, + struct dcerpc_binding_handle *b, + const char *domain, + bool force) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct trust_pw_change_state *state; + struct samr_Password current_nt_hash; + const struct samr_Password *previous_nt_hash = NULL; + enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; + const char *account_name; + char *new_trust_passwd; + char *pwd; + struct dom_sid sid; + time_t pass_last_set_time; + struct timeval g_timeout = { 0, }; + int timeout = 0; + struct timeval tv = { 0, }; + NTSTATUS status; + + state = talloc_zero(frame, struct trust_pw_change_state); + if (state == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + state->g_ctx = g_lock_ctx_init(state, msg_ctx); + if (state->g_ctx == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + state->g_lock_key = talloc_asprintf(state, + "trust_password_change_%s", + domain); + if (state->g_lock_key == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + g_timeout = timeval_current_ofs(10, 0); + status = g_lock_lock(state->g_ctx, + state->g_lock_key, + G_LOCK_WRITE, g_timeout); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("could not get g_lock on [%s]!\n", + state->g_lock_key)); + TALLOC_FREE(frame); + return status; + } + + talloc_set_destructor(state, trust_pw_change_state_destructor); + + if (!get_trust_pw_hash(domain, current_nt_hash.hash, + &account_name, + &sec_channel_type)) { + DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); + TALLOC_FREE(frame); + return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; + } + + switch (sec_channel_type) { + case SEC_CHAN_WKSTA: + pwd = secrets_fetch_machine_password(domain, + &pass_last_set_time, + NULL); + if (pwd == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; + } + break; + case SEC_CHAN_DOMAIN: + if (!pdb_get_trusteddom_pw(domain, &pwd, &sid, &pass_last_set_time)) { + TALLOC_FREE(frame); + return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; + } + break; + default: + TALLOC_FREE(frame); + return NT_STATUS_NOT_SUPPORTED; + } + + timeout = lp_machine_password_timeout(); + if (timeout == 0) { + if (!force) { + DEBUG(10,("machine password never expires\n")); + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + } + + tv.tv_sec = pass_last_set_time; + DEBUG(10, ("password last changed %s\n", + timeval_string(talloc_tos(), &tv, false))); + tv.tv_sec += timeout; + DEBUGADD(10, ("password valid until %s\n", + timeval_string(talloc_tos(), &tv, false))); + + if (!force && !timeval_expired(&tv)) { + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + /* Create a random machine account password */ + new_trust_passwd = generate_random_password(frame, + DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH, + DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); + if (new_trust_passwd == NULL) { + DEBUG(0, ("generate_random_password failed\n")); + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + status = netlogon_creds_cli_auth(context, b, + current_nt_hash, + previous_nt_hash); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + status = netlogon_creds_cli_ServerPasswordSet(context, b, + new_trust_passwd, NULL); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + + DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", + current_timestring(talloc_tos(), False))); + + /* + * Return the result of trying to write the new password + * back into the trust account file. + */ + + switch (sec_channel_type) { + + case SEC_CHAN_WKSTA: + if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) { + TALLOC_FREE(frame); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + break; + + case SEC_CHAN_DOMAIN: + /* + * we need to get the sid first for the + * pdb_set_trusteddom_pw call + */ + if (!pdb_set_trusteddom_pw(domain, new_trust_passwd, &sid)) { + TALLOC_FREE(frame); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + break; + + default: + break; + } + + TALLOC_FREE(frame); + return NT_STATUS_OK; +} -- 1.9.3 From 09dae290b1d49a30eef5b93f5260dc44fb628437 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:33:51 +0200 Subject: [PATCH 195/249] s3:rpcclient: make use of trust_pw_change() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a9281e6570fcc5ff5abe3149615bed7029d1cf71) --- source3/rpcclient/cmd_netlogon.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 59e1e4e..000d65c 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -829,11 +829,11 @@ static NTSTATUS cmd_netlogon_change_trust_pw(struct rpc_pipe_client *cli, return NT_STATUS_OK; } - /* Perform the sam logon */ - - result = trust_pw_find_change_and_store_it(cli, mem_ctx, - lp_workgroup()); - + result = trust_pw_change(rpcclient_netlogon_creds, + rpcclient_msg_ctx, + cli->binding_handle, + lp_workgroup(), + true); /* force */ if (!NT_STATUS_IS_OK(result)) goto done; -- 1.9.3 From 3731b2163f6bb88922a9fa84e60fa48afbbbda9a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:34:48 +0200 Subject: [PATCH 196/249] s3:net_rpc: make use of trust_pw_change() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit cfd139347c21f4f4ddd16026c2c8c221feabd6c5) --- source3/utils/net_rpc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 3bf3f30..ba49f3e 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -279,7 +279,11 @@ static NTSTATUS rpc_changetrustpw_internals(struct net_context *c, { NTSTATUS status; - status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup); + status = trust_pw_change(c->netlogon_creds, + c->msg_ctx, + pipe_hnd->binding_handle, + c->opt_target_workgroup, + true); /* force */ if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, _("Failed to change machine account password: %s\n"), nt_errstr(status)); -- 1.9.3 From cd8fdfc923adcc5b6c700ec52d1bba4643079247 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:35:39 +0200 Subject: [PATCH 197/249] s3:winbindd: use invalidate_cm_connection() to kill the netlogon connection Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit dbd49d90bbf175525557eaa983ad57ca5076d710) --- source3/winbindd/winbindd_dual.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 64af571..b26cdca 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1056,7 +1056,7 @@ static void machine_password_change_handler(struct tevent_context *ctx, "password was changed and we didn't know it. " "Killing connections to domain %s\n", child->domain->name)); - TALLOC_FREE(child->domain->conn.netlogon_pipe); + invalidate_cm_connection(&child->domain->conn); } if (!calculate_next_machine_pwd_change(child->domain->name, -- 1.9.3 From 6369757af75412746c0d9950971a77be72826b92 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:36:43 +0200 Subject: [PATCH 198/249] s3:winbindd: make use of trust_pw_change() for periodic password changes Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 57741dd4ba5a9ed3abf7aad35a2a69fd66b49b4b) --- source3/winbindd/winbindd_dual.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index b26cdca..1d6a5ba 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -29,6 +29,7 @@ #include "includes.h" #include "winbindd.h" +#include "rpc_client/rpc_client.h" #include "nsswitch/wb_reqtrans.h" #include "secrets.h" #include "../lib/util/select.h" @@ -999,10 +1000,10 @@ static void machine_password_change_handler(struct tevent_context *ctx, struct timeval now, void *private_data) { + struct messaging_context *msg_ctx = winbind_messaging_context(); struct winbindd_child *child = (struct winbindd_child *)private_data; struct rpc_pipe_client *netlogon_pipe = NULL; - TALLOC_CTX *frame; NTSTATUS result; struct timeval next_change; @@ -1039,15 +1040,14 @@ static void machine_password_change_handler(struct tevent_context *ctx, return; } - frame = talloc_stackframe(); - - result = trust_pw_find_change_and_store_it(netlogon_pipe, - frame, - child->domain->name); - TALLOC_FREE(frame); + result = trust_pw_change(child->domain->conn.netlogon_creds, + msg_ctx, + netlogon_pipe->binding_handle, + child->domain->name, + false); /* force */ DEBUG(10, ("machine_password_change_handler: " - "trust_pw_find_change_and_store_it returned %s\n", + "trust_pw_change returned %s\n", nt_errstr(result))); if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) { -- 1.9.3 From 5fe11c760d853dff63ad9b3505f3d3721b7e14f6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:37:34 +0200 Subject: [PATCH 199/249] s3:winbindd: make use of trust_pw_change() in _wbint_ChangeMachineAccount() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3c30e19c4a0e60e355b2f1d35edbb0a3b7688089) --- source3/winbindd/winbindd_dual_srv.c | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 001591a..f064467 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -622,48 +622,27 @@ again: NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p, struct wbint_ChangeMachineAccount *r) { + struct messaging_context *msg_ctx = winbind_messaging_context(); struct winbindd_domain *domain; - int num_retries = 0; NTSTATUS status; struct rpc_pipe_client *netlogon_pipe; - TALLOC_CTX *tmp_ctx; -again: domain = wb_child_domain(); if (domain == NULL) { return NT_STATUS_REQUEST_NOT_ACCEPTED; } - invalidate_cm_connection(&domain->conn); - - { - status = cm_connect_netlogon(domain, &netlogon_pipe); - } - - /* There is a race condition between fetching the trust account - password and the periodic machine password change. So it's - possible that the trust account password has been changed on us. - We are returned NT_STATUS_ACCESS_DENIED if this happens. */ - -#define MAX_RETRIES 3 - - if ((num_retries < MAX_RETRIES) - && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - num_retries++; - goto again; - } - + status = cm_connect_netlogon(domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); goto done; } - tmp_ctx = talloc_new(p->mem_ctx); - - status = trust_pw_find_change_and_store_it(netlogon_pipe, - tmp_ctx, - domain->name); - talloc_destroy(tmp_ctx); + status = trust_pw_change(domain->conn.netlogon_creds, + msg_ctx, + netlogon_pipe->binding_handle, + domain->name, + true); /* force */ /* Pass back result code - zero for success, other values for specific failures. */ -- 1.9.3 From 9956ea8b561da89fb79739dd8a8552116c7867f7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 18:39:52 +0200 Subject: [PATCH 200/249] s3:libsmb: remove unused trust_pw_find_change_and_store_it() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a8ecebe3e840005c81df043cb07773972aaa2371) --- source3/include/proto.h | 3 -- source3/libsmb/trusts_util.c | 81 -------------------------------------------- 2 files changed, 84 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index edda119..18348e5 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -981,9 +981,6 @@ void update_trustdom_cache( void ); /* The following definitions come from libsmb/trusts_util.c */ -NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - const char *domain) ; struct netlogon_creds_cli_context; struct messaging_context; struct dcerpc_binding_handle; diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index b1bc006..b38aec6 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -36,87 +36,6 @@ already setup the connection to the NETLOGON pipe **********************************************************/ -NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - const char *domain) -{ - unsigned char old_trust_passwd_hash[16]; - unsigned char new_trust_passwd_hash[16]; - enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL; - const char *account_name; - char *new_trust_passwd; - NTSTATUS nt_status; - - if (!get_trust_pw_hash(domain, old_trust_passwd_hash, &account_name, - &sec_channel_type)) { - DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); - return NT_STATUS_UNSUCCESSFUL; - } - - switch (sec_channel_type) { - case SEC_CHAN_WKSTA: - case SEC_CHAN_DOMAIN: - break; - default: - return NT_STATUS_NOT_SUPPORTED; - } - - /* Create a random machine account password */ - new_trust_passwd = generate_random_password(mem_ctx, - DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH, - DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); - if (new_trust_passwd == NULL) { - DEBUG(0, ("generate_random_password failed\n")); - return NT_STATUS_NO_MEMORY; - } - - E_md4hash(new_trust_passwd, new_trust_passwd_hash); - - nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx, - account_name, - old_trust_passwd_hash, - new_trust_passwd, - new_trust_passwd_hash, - sec_channel_type); - - if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", - current_timestring(talloc_tos(), False))); - /* - * Return the result of trying to write the new password - * back into the trust account file. - */ - - switch (sec_channel_type) { - - case SEC_CHAN_WKSTA: - if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) { - nt_status = NT_STATUS_UNSUCCESSFUL; - } - break; - - case SEC_CHAN_DOMAIN: { - char *pwd; - struct dom_sid sid; - time_t pass_last_set_time; - - /* we need to get the sid first for the - * pdb_set_trusteddom_pw call */ - - if (!pdb_get_trusteddom_pw(domain, &pwd, &sid, &pass_last_set_time)) { - nt_status = NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE; - } - if (!pdb_set_trusteddom_pw(domain, new_trust_passwd, &sid)) { - nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; - } - break; - } - } - } - - return nt_status; -} - struct trust_pw_change_state { struct g_lock_ctx *g_ctx; char *g_lock_key; -- 1.9.3 From f71cb73d7f034165802aad97e9be6f45ba32d519 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 19:19:39 +0200 Subject: [PATCH 201/249] s3:libnet: pass in struct netlogon_creds_cli_context from the caller. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 77defb175e3ffd1b096485ac7de38ad161594b72) --- source3/libnet/libnet_samsync.c | 2 +- source3/libnet/libnet_samsync.h | 1 + source3/utils/net_rpc_samsync.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c index 02d3fc6..e7e1393 100644 --- a/source3/libnet/libnet_samsync.c +++ b/source3/libnet/libnet_samsync.c @@ -216,7 +216,7 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx, struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; struct netlogon_creds_CredentialState *creds = NULL; - status = netlogon_creds_cli_lock(ctx->cli->netlogon_creds, + status = netlogon_creds_cli_lock(ctx->netlogon_creds, mem_ctx, &creds); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source3/libnet/libnet_samsync.h b/source3/libnet/libnet_samsync.h index efdbb37..e1d66ec 100644 --- a/source3/libnet/libnet_samsync.h +++ b/source3/libnet/libnet_samsync.h @@ -75,6 +75,7 @@ struct samsync_context { struct samsync_object *objects; struct rpc_pipe_client *cli; + struct netlogon_creds_cli_context *netlogon_creds; struct messaging_context *msg_ctx; const struct samsync_ops *ops; diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 772651f..6377ad4 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -129,6 +129,7 @@ NTSTATUS rpc_samdump_internals(struct net_context *c, ctx->mode = NET_SAMSYNC_MODE_DUMP; ctx->cli = pipe_hnd; + ctx->netlogon_creds = c->netlogon_creds; ctx->ops = &libnet_samsync_display_ops; ctx->domain_name = domain_name; -- 1.9.3 From acb678ce415403e1442116b32eb8b8b32b677f4a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 20:51:25 +0200 Subject: [PATCH 202/249] s3:rpcclient: make use of rpccli_{create,setup}_netlogon_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 5107ca02a41673739a1fc4a1c2a0fbe8465f211a) --- source3/rpcclient/rpcclient.c | 59 ++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index a875ff5..490f8df 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -676,6 +676,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, { NTSTATUS ntresult; WERROR wresult; + bool ok; TALLOC_CTX *mem_ctx; @@ -759,17 +760,20 @@ static NTSTATUS do_cmd(struct cli_state *cli, return ntresult; } - if (ndr_syntax_id_equal(&cmd_entry->table->syntax_id, - &ndr_table_netlogon.syntax_id)) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | - NETLOGON_NEG_SUPPORTS_AES; - enum netr_SchannelType sec_channel_type; - uchar trust_password[16]; - const char *machine_account; + ok = ndr_syntax_id_equal(&cmd_entry->table->syntax_id, + &ndr_table_netlogon.syntax_id); + if (cmd_entry->rpc_pipe->netlogon_creds == NULL && ok) { + const char *dc_name = cmd_entry->rpc_pipe->desthost; + const char *domain = get_cmdline_auth_info_domain(auth_info); + enum netr_SchannelType sec_chan_type = 0; + const char *_account_name = NULL; + const char *account_name = NULL; + struct samr_Password current_nt_hash; + struct samr_Password *previous_nt_hash = NULL; if (!get_trust_pw_hash(get_cmdline_auth_info_domain(auth_info), - trust_password, &machine_account, - &sec_channel_type)) + current_nt_hash.hash, &_account_name, + &sec_chan_type)) { DEBUG(0, ("Failed to fetch trust password for %s to connect to %s.\n", get_cmdline_auth_info_domain(auth_info), @@ -779,22 +783,41 @@ static NTSTATUS do_cmd(struct cli_state *cli, return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } - ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe, - cmd_entry->rpc_pipe->desthost, /* server name */ - get_cmdline_auth_info_domain(auth_info), /* domain */ - lp_netbios_name(), /* client name */ - machine_account, /* machine account name */ - trust_password, - sec_channel_type, - &neg_flags); + account_name = talloc_asprintf(mem_ctx, "%s$", _account_name); + if (account_name == NULL) { + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + ntresult = rpccli_create_netlogon_creds(dc_name, + domain, + account_name, + sec_chan_type, + rpcclient_msg_ctx, + talloc_autofree_context(), + &rpcclient_netlogon_creds); + if (!NT_STATUS_IS_OK(ntresult)) { + SAFE_FREE(previous_nt_hash); + TALLOC_FREE(mem_ctx); + return ntresult; + } + ntresult = rpccli_setup_netlogon_creds(cli, + rpcclient_netlogon_creds, + false, /* force_reauth */ + current_nt_hash, + previous_nt_hash); + SAFE_FREE(previous_nt_hash); if (!NT_STATUS_IS_OK(ntresult)) { DEBUG(0, ("Could not initialise credentials for %s.\n", cmd_entry->table->name)); TALLOC_FREE(cmd_entry->rpc_pipe); - talloc_free(mem_ctx); + TALLOC_FREE(rpcclient_netlogon_creds); + TALLOC_FREE(mem_ctx); return ntresult; } + cmd_entry->rpc_pipe->netlogon_creds = rpcclient_netlogon_creds; } } -- 1.9.3 From b04744971aa9cc696aa4a3c56dd46d58db8dda75 Mon Sep 17 00:00:00 2001 From: Garming Sam Date: Fri, 29 Nov 2013 14:45:20 +1300 Subject: [PATCH 203/249] s3:rpcclient: give errors and clean up correctly after failing to obtain secret Signed-off-by: Garming Sam Reviewed-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a012e2fdd6733e871ddeb68874a2df8413ad91ed) --- source3/rpcclient/rpcclient.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 490f8df..fd3ebdf 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -785,6 +785,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, account_name = talloc_asprintf(mem_ctx, "%s$", _account_name); if (account_name == NULL) { + DEBUG(0, ("Out of memory creating account name to connect to %s.\n", + cmd_entry->table->name)); + TALLOC_FREE(cmd_entry->rpc_pipe); SAFE_FREE(previous_nt_hash); TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; @@ -798,6 +801,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, talloc_autofree_context(), &rpcclient_netlogon_creds); if (!NT_STATUS_IS_OK(ntresult)) { + DEBUG(0, ("Could not initialise credentials for %s.\n", + cmd_entry->table->name)); + TALLOC_FREE(cmd_entry->rpc_pipe); SAFE_FREE(previous_nt_hash); TALLOC_FREE(mem_ctx); return ntresult; -- 1.9.3 From 564e6df9361025ff7da6fa92d83491cfd9e60b2b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Sep 2013 00:46:09 +0200 Subject: [PATCH 204/249] s3:rpcclient: remove optional auth_level parameter of the 'samlogon' cmd Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 4c99e49898151a514e334a07f38eed83fe608c05) --- source3/rpcclient/cmd_netlogon.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 000d65c..97b79cb 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -782,9 +782,9 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, /* Check arguments */ - if (argc < 3 || argc > 7) { + if (argc < 3 || argc > 6) { fprintf(stderr, "Usage: samlogon [workstation]" - "[logon_type (1 or 2)] [auth level (2 or 3)] [logon_parameter]\n"); + "[logon_type (1 or 2)] [logon_parameter]\n"); return NT_STATUS_OK; } @@ -797,11 +797,8 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, if (argc >= 5) sscanf(argv[4], "%i", &logon_type); - if (argc >= 6) - validation_level = atoi(argv[5]); - - if (argc == 7) - sscanf(argv[6], "%x", &logon_param); + if (argc == 6) + sscanf(argv[5], "%x", &logon_param); /* Perform the sam logon */ -- 1.9.3 From a61d399c13c9f46e283f85f3d076b0607c2729f3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Sep 2013 00:48:31 +0200 Subject: [PATCH 205/249] s3:rpcclient: make use of rpccli_netlogon_password_logon() in the 'samlogon' cmd Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit c6bb47f2f199cc13101dccf656ac36e9eb879201) --- source3/rpcclient/cmd_netlogon.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 97b79cb..b637b3e 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -776,7 +776,6 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; int logon_type = NetlogonNetworkInformation; const char *username, *password; - uint16_t validation_level = 3; uint32 logon_param = 0; const char *workstation = NULL; @@ -802,8 +801,14 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, /* Perform the sam logon */ - result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, workstation, validation_level, logon_type); - + result = rpccli_netlogon_password_logon(rpcclient_netlogon_creds, + cli->binding_handle, + logon_param, + lp_workgroup(), + username, + password, + workstation, + logon_type); if (!NT_STATUS_IS_OK(result)) goto done; -- 1.9.3 From fbe0154a63d401acd47c5190be37b8d69d3d64ba Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Sep 2013 00:56:15 +0200 Subject: [PATCH 206/249] s3:winbindd: make use of rpccli_netlogon_network_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a34c837fdb59df1e66be9b5f23a07990e34fea1c) --- source3/winbindd/winbindd_pam.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 39483a5..3f3ec70 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1228,6 +1228,8 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, do { struct rpc_pipe_client *netlogon_pipe; + uint8_t authoritative = 0; + uint32_t flags = 0; ZERO_STRUCTP(info3); retry = false; @@ -1276,19 +1278,19 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, } netr_attempts = 0; - result = rpccli_netlogon_sam_network_logon( - netlogon_pipe, - mem_ctx, - logon_parameters, - server, /* server name */ - username, /* user name */ - domainname, /* target domain */ - workstation, /* workstation */ - chal, - -1, /* ignored */ - lm_response, - nt_response, - info3); + result = rpccli_netlogon_network_logon(domain->conn.netlogon_creds, + netlogon_pipe->binding_handle, + mem_ctx, + logon_parameters, + username, + domainname, + workstation, + chal, + lm_response, + nt_response, + &authoritative, + &flags, + info3); /* * we increment this after the "feature negotiation" -- 1.9.3 From cfcb681d6f80253b6f2db769f5c5be1ffb54cc0e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 20:53:51 +0200 Subject: [PATCH 207/249] s3:rpc_client: make cli_rpc_pipe_open_schannel() more flexible It expects a messaging_context now and returns a netlogon_creds_cli_context. This way we can finally avoid having a rpc_pipe_client->netlogon_creds. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 660150b12a637da7f9ebb820e687f27ac22fb93a) --- source3/rpc_client/cli_pipe.h | 5 ++++- source3/rpc_client/cli_pipe_schannel.c | 9 +++++++-- source3/rpcclient/rpcclient.c | 13 +++++++------ source3/utils/net_rpc.c | 6 +++--- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/source3/rpc_client/cli_pipe.h b/source3/rpc_client/cli_pipe.h index 2a76130..b704d8a 100644 --- a/source3/rpc_client/cli_pipe.h +++ b/source3/rpc_client/cli_pipe.h @@ -99,11 +99,14 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, struct rpc_pipe_client **presult); NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + struct messaging_context *msg_ctx, const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, - struct rpc_pipe_client **presult); + struct rpc_pipe_client **presult, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **pcreds); NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, diff --git a/source3/rpc_client/cli_pipe_schannel.c b/source3/rpc_client/cli_pipe_schannel.c index 1fcf62e..a842333 100644 --- a/source3/rpc_client/cli_pipe_schannel.c +++ b/source3/rpc_client/cli_pipe_schannel.c @@ -38,14 +38,16 @@ ****************************************************************************/ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, + struct messaging_context *msg_ctx, const struct ndr_interface_table *table, enum dcerpc_transport_t transport, enum dcerpc_AuthLevel auth_level, const char *domain, - struct rpc_pipe_client **presult) + struct rpc_pipe_client **presult, + TALLOC_CTX *mem_ctx, + struct netlogon_creds_cli_context **pcreds) { TALLOC_CTX *frame = talloc_stackframe(); - struct messaging_context *msg_ctx = NULL; const char *dc_name = smbXcli_conn_remote_name(cli->conn); struct rpc_pipe_client *result = NULL; NTSTATUS status; @@ -121,6 +123,9 @@ NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli, if (NT_STATUS_IS_OK(status)) { *presult = result; + if (pcreds != NULL) { + *pcreds = talloc_move(mem_ctx, &netlogon_creds); + } } TALLOC_FREE(frame); diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index fd3ebdf..43343e8 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -737,12 +737,16 @@ static NTSTATUS do_cmd(struct cli_state *cli, &cmd_entry->rpc_pipe); break; case DCERPC_AUTH_TYPE_SCHANNEL: + TALLOC_FREE(rpcclient_netlogon_creds); ntresult = cli_rpc_pipe_open_schannel( - cli, cmd_entry->table, + cli, rpcclient_msg_ctx, + cmd_entry->table, default_transport, pipe_default_auth_level, get_cmdline_auth_info_domain(auth_info), - &cmd_entry->rpc_pipe); + &cmd_entry->rpc_pipe, + talloc_autofree_context(), + &rpcclient_netlogon_creds); break; default: DEBUG(0, ("Could not initialise %s. Invalid " @@ -762,7 +766,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, ok = ndr_syntax_id_equal(&cmd_entry->table->syntax_id, &ndr_table_netlogon.syntax_id); - if (cmd_entry->rpc_pipe->netlogon_creds == NULL && ok) { + if (rpcclient_netlogon_creds == NULL && ok) { const char *dc_name = cmd_entry->rpc_pipe->desthost; const char *domain = get_cmdline_auth_info_domain(auth_info); enum netr_SchannelType sec_chan_type = 0; @@ -823,12 +827,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, TALLOC_FREE(mem_ctx); return ntresult; } - cmd_entry->rpc_pipe->netlogon_creds = rpcclient_netlogon_creds; } } - rpcclient_netlogon_creds = cmd_entry->rpc_pipe->netlogon_creds; - /* Run command */ if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index ba49f3e..d0f699a 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -192,16 +192,16 @@ int run_rpc_command(struct net_context *c, && (ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id))) { /* Always try and create an schannel netlogon pipe. */ + TALLOC_FREE(c->netlogon_creds); nt_status = cli_rpc_pipe_open_schannel( - cli, table, NCACN_NP, + cli, c->msg_ctx, table, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain_name, - &pipe_hnd); + &pipe_hnd, c, &c->netlogon_creds); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n", nt_errstr(nt_status) )); goto fail; } - c->netlogon_creds = pipe_hnd->netlogon_creds; } else { if (conn_flags & NET_FLAGS_SEAL) { nt_status = cli_rpc_pipe_open_generic_auth( -- 1.9.3 From 603b40eeee3cf21de94f11471889d0443713ba4f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 6 Sep 2013 13:54:30 +0200 Subject: [PATCH 208/249] s3:rpc_client: remove unused rpccli_netlogon_set_trust_password() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 6d457ad9c156cf86d99e58dea21dba170defad1b) --- source3/rpc_client/cli_netlogon.c | 51 --------------------------------------- source3/rpc_client/cli_netlogon.h | 7 ------ 2 files changed, 58 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index a9f8604..2f23d1b 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -759,54 +759,3 @@ NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, return NT_STATUS_OK; } - -/********************************************************* - Change the domain password on the PDC. - - Just changes the password betwen the two values specified. - - Caller must have the cli connected to the netlogon pipe - already. -**********************************************************/ - -NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - const char *account_name, - const unsigned char orig_trust_passwd_hash[16], - const char *new_trust_pwd_cleartext, - const unsigned char new_trust_passwd_hash[16], - enum netr_SchannelType sec_channel_type) -{ - NTSTATUS result; - - if (cli->netlogon_creds == NULL) { - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | - NETLOGON_NEG_SUPPORTS_AES; - result = rpccli_netlogon_setup_creds(cli, - cli->desthost, /* server name */ - lp_workgroup(), /* domain */ - lp_netbios_name(), /* client name */ - account_name, /* machine account name */ - orig_trust_passwd_hash, - sec_channel_type, - &neg_flags); - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n", - nt_errstr(result))); - return result; - } - } - - result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds, - cli->binding_handle, - new_trust_pwd_cleartext, - NULL); /* new_version */ - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n", - nt_errstr(result))); - return result; - } - - return NT_STATUS_OK; -} - diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index d4c6670..8547db6 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -93,12 +93,5 @@ NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, uint8_t *authoritative, uint32_t *flags, struct netr_SamInfo3 **info3); -NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - const char *account_name, - const unsigned char orig_trust_passwd_hash[16], - const char *new_trust_pwd_cleartext, - const unsigned char new_trust_passwd_hash[16], - enum netr_SchannelType sec_channel_type); #endif /* _RPC_CLIENT_CLI_NETLOGON_H_ */ -- 1.9.3 From c9dc23d434bc7015f400b1969a055b95faac6594 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 6 Sep 2013 13:06:53 +0200 Subject: [PATCH 209/249] s3:rpc_client: remove unused rpccli_netlogon_setup_creds() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit a4faf57b47095bfc0f4370ac093c8c4cef17584f) --- source3/rpc_client/cli_netlogon.c | 92 --------------------------------------- source3/rpc_client/cli_netlogon.h | 8 ---- 2 files changed, 100 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 2f23d1b..687d0c2 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -35,98 +35,6 @@ #include "lib/param/param.h" #include "libcli/smb/smbXcli_base.h" -/**************************************************************************** - Wrapper function that uses the auth and auth2 calls to set up a NETLOGON - credentials chain. Stores the credentials in the struct dcinfo in the - netlogon pipe struct. -****************************************************************************/ - -NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, - const char *server_name, - const char *domain, - const char *clnt_name, - const char *machine_account, - const unsigned char machine_pwd[16], - enum netr_SchannelType sec_chan_type, - uint32_t *neg_flags_inout) -{ - TALLOC_CTX *frame = talloc_stackframe(); - struct loadparm_context *lp_ctx; - NTSTATUS status; - struct samr_Password password; - fstring mach_acct; - struct dcerpc_binding_handle *b = cli->binding_handle; - struct netlogon_creds_CredentialState *creds = NULL; - - if (!ndr_syntax_id_equal(&cli->abstract_syntax, - &ndr_table_netlogon.syntax_id)) { - TALLOC_FREE(frame); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!strequal(lp_netbios_name(), clnt_name)) { - TALLOC_FREE(frame); - return NT_STATUS_INVALID_PARAMETER; - } - - TALLOC_FREE(cli->netlogon_creds); - - fstr_sprintf( mach_acct, "%s$", machine_account); - - lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); - if (lp_ctx == NULL) { - TALLOC_FREE(frame); - return NT_STATUS_NO_MEMORY; - } - status = netlogon_creds_cli_context_global(lp_ctx, - NULL, /* msg_ctx */ - mach_acct, - sec_chan_type, - server_name, - domain, - cli, &cli->netlogon_creds); - talloc_unlink(frame, lp_ctx); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(frame); - return status; - } - - status = netlogon_creds_cli_get(cli->netlogon_creds, - frame, &creds); - if (NT_STATUS_IS_OK(status)) { - DEBUG(5,("rpccli_netlogon_setup_creds: server %s using " - "cached credential\n", - cli->desthost)); - *neg_flags_inout = creds->negotiate_flags; - TALLOC_FREE(frame); - return NT_STATUS_OK; - } - - /* Store the machine account password we're going to use. */ - memcpy(password.hash, machine_pwd, 16); - - DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential " - "chain established.\n", - cli->desthost )); - - status = netlogon_creds_cli_auth(cli->netlogon_creds, b, - password, NULL); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(frame); - return status; - } - - status = netlogon_creds_cli_get(cli->netlogon_creds, - frame, &creds); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(frame); - return NT_STATUS_INTERNAL_ERROR; - } - - *neg_flags_inout = creds->negotiate_flags; - TALLOC_FREE(frame); - return NT_STATUS_OK; -} NTSTATUS rpccli_pre_open_netlogon_creds(void) { diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index 8547db6..0de836a 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -30,14 +30,6 @@ struct dcerpc_binding_handle; /* The following definitions come from rpc_client/cli_netlogon.c */ -NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, - const char *server_name, - const char *domain, - const char *clnt_name, - const char *machine_account, - const unsigned char machine_pwd[16], - enum netr_SchannelType sec_chan_type, - uint32_t *neg_flags_inout); NTSTATUS rpccli_pre_open_netlogon_creds(void); NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, const char *server_netbios_domain, -- 1.9.3 From 2a072da1cc18acc7eb6d82769dc96b7e94ec57fe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 19:23:18 +0200 Subject: [PATCH 210/249] s3:rpc_client: remove unused rpccli_netlogon_sam_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit e4fea80693b49e79a96acdac09d5ea292756635c) --- source3/rpc_client/cli_netlogon.c | 124 -------------------------------------- source3/rpc_client/cli_netlogon.h | 9 --- 2 files changed, 133 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 687d0c2..171337a 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -160,130 +160,6 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, /* Logon domain user */ -NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *domain, - const char *username, - const char *password, - const char *workstation, - uint16_t _ignored_validation_level, - int logon_type) -{ - NTSTATUS status; - union netr_LogonLevel *logon; - uint16_t validation_level = 0; - union netr_Validation *validation = NULL; - uint8_t authoritative = 0; - uint32_t flags = 0; - fstring clnt_name_slash; - - logon = talloc_zero(mem_ctx, union netr_LogonLevel); - if (!logon) { - return NT_STATUS_NO_MEMORY; - } - - if (workstation) { - fstr_sprintf( clnt_name_slash, "\\\\%s", workstation ); - } else { - fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() ); - } - - /* Initialise input parameters */ - - switch (logon_type) { - case NetlogonInteractiveInformation: { - - struct netr_PasswordInfo *password_info; - - struct samr_Password lmpassword; - struct samr_Password ntpassword; - - password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo); - if (!password_info) { - return NT_STATUS_NO_MEMORY; - } - - nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); - - password_info->identity_info.domain_name.string = domain; - password_info->identity_info.parameter_control = logon_parameters; - password_info->identity_info.logon_id_low = 0xdead; - password_info->identity_info.logon_id_high = 0xbeef; - password_info->identity_info.account_name.string = username; - password_info->identity_info.workstation.string = clnt_name_slash; - - password_info->lmpassword = lmpassword; - password_info->ntpassword = ntpassword; - - logon->password = password_info; - - break; - } - case NetlogonNetworkInformation: { - struct netr_NetworkInfo *network_info; - uint8 chal[8]; - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - struct netr_ChallengeResponse lm; - struct netr_ChallengeResponse nt; - - ZERO_STRUCT(lm); - ZERO_STRUCT(nt); - - network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); - if (!network_info) { - return NT_STATUS_NO_MEMORY; - } - - generate_random_buffer(chal, 8); - - SMBencrypt(password, chal, local_lm_response); - SMBNTencrypt(password, chal, local_nt_response); - - lm.length = 24; - lm.data = local_lm_response; - - nt.length = 24; - nt.data = local_nt_response; - - network_info->identity_info.domain_name.string = domain; - network_info->identity_info.parameter_control = logon_parameters; - network_info->identity_info.logon_id_low = 0xdead; - network_info->identity_info.logon_id_high = 0xbeef; - network_info->identity_info.account_name.string = username; - network_info->identity_info.workstation.string = clnt_name_slash; - - memcpy(network_info->challenge, chal, 8); - network_info->nt = nt; - network_info->lm = lm; - - logon->network = network_info; - - break; - } - default: - DEBUG(0, ("switch value %d not supported\n", - logon_type)); - return NT_STATUS_INVALID_INFO_CLASS; - } - - status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, - cli->binding_handle, - logon_type, - logon, - mem_ctx, - &validation_level, - &validation, - &authoritative, - &flags); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} - NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, struct dcerpc_binding_handle *binding_handle, uint32_t logon_parameters, diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index 0de836a..eaa5b0c 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -43,15 +43,6 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, bool force_reauth, struct samr_Password current_nt_hash, const struct samr_Password *previous_nt_hash); -NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *domain, - const char *username, - const char *password, - const char *workstation, - uint16_t validation_level, - int logon_type); NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, struct dcerpc_binding_handle *binding_handle, uint32_t logon_parameters, -- 1.9.3 From 4092fca5daf42e1cd26af8069b09b97a7d01df9c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 19:23:54 +0200 Subject: [PATCH 211/249] s3:rpc_client: remove unused rpccli_netlogon_sam_network_logon() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3f41b583840ffa2220f61eea61833bf3c6bd33db) --- source3/rpc_client/cli_netlogon.c | 94 --------------------------------------- source3/rpc_client/cli_netlogon.h | 12 ----- 2 files changed, 106 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 171337a..ca2d9bf 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -346,100 +346,6 @@ static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller. **/ -NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - uint16_t _ignored_validation_level, - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **info3) -{ - NTSTATUS status; - const char *workstation_name_slash; - union netr_LogonLevel *logon = NULL; - struct netr_NetworkInfo *network_info; - uint16_t validation_level = 0; - union netr_Validation *validation = NULL; - uint8_t authoritative = 0; - uint32_t flags = 0; - struct netr_ChallengeResponse lm; - struct netr_ChallengeResponse nt; - - *info3 = NULL; - - ZERO_STRUCT(lm); - ZERO_STRUCT(nt); - - logon = talloc_zero(mem_ctx, union netr_LogonLevel); - if (!logon) { - return NT_STATUS_NO_MEMORY; - } - - network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); - if (!network_info) { - return NT_STATUS_NO_MEMORY; - } - - if (workstation[0] != '\\' && workstation[1] != '\\') { - workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); - } else { - workstation_name_slash = workstation; - } - - if (!workstation_name_slash) { - DEBUG(0, ("talloc_asprintf failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - /* Initialise input parameters */ - - lm.data = lm_response.data; - lm.length = lm_response.length; - nt.data = nt_response.data; - nt.length = nt_response.length; - - network_info->identity_info.domain_name.string = domain; - network_info->identity_info.parameter_control = logon_parameters; - network_info->identity_info.logon_id_low = 0xdead; - network_info->identity_info.logon_id_high = 0xbeef; - network_info->identity_info.account_name.string = username; - network_info->identity_info.workstation.string = workstation_name_slash; - - memcpy(network_info->challenge, chal, 8); - network_info->nt = nt; - network_info->lm = lm; - - logon->network = network_info; - - /* Marshall data and send request */ - - status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds, - cli->binding_handle, - NetlogonNetworkInformation, - logon, - mem_ctx, - &validation_level, - &validation, - &authoritative, - &flags); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = map_validation_to_info3(mem_ctx, - validation_level, validation, - info3); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, struct dcerpc_binding_handle *binding_handle, diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index eaa5b0c..61fed4a 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -51,18 +51,6 @@ NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds const char *password, const char *workstation, enum netr_LogonInfoClass logon_type); -NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, - TALLOC_CTX *mem_ctx, - uint32 logon_parameters, - const char *server, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - uint16_t validation_level, - DATA_BLOB lm_response, - DATA_BLOB nt_response, - struct netr_SamInfo3 **info3); NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, struct dcerpc_binding_handle *binding_handle, TALLOC_CTX *mem_ctx, -- 1.9.3 From bdfc02fd5830ed6e2f14aaf90456e572028ada6a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Sep 2013 19:25:27 +0200 Subject: [PATCH 212/249] s3:rpc_client: finally remove unused rpc_pipe_client->netlogon_creds Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit c0761c3eae34175d772476006caf5caad68bd8c6) --- source3/rpc_client/cli_pipe.c | 9 --------- source3/rpc_client/rpc_client.h | 3 --- 2 files changed, 12 deletions(-) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 31cd7f5..8613a21 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3097,15 +3097,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return status; } - status = netlogon_creds_cli_context_copy(netlogon_creds, - rpccli, - &rpccli->netlogon_creds); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("netlogon_creds_cli_context_copy failed with %s\n", - nt_errstr(status))); - TALLOC_FREE(rpccli); - return status; - } done: DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " diff --git a/source3/rpc_client/rpc_client.h b/source3/rpc_client/rpc_client.h index 7c4cceb..7c5ff0e 100644 --- a/source3/rpc_client/rpc_client.h +++ b/source3/rpc_client/rpc_client.h @@ -48,9 +48,6 @@ struct rpc_pipe_client { uint16 max_recv_frag; struct pipe_auth_data *auth; - - /* The following is only non-null on a netlogon client pipe. */ - struct netlogon_creds_cli_context *netlogon_creds; }; #endif /* _RPC_CLIENT_H */ -- 1.9.3 From 710124dca6a97d9148d62bc9aa727568d5284e45 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Oct 2013 19:17:12 +0200 Subject: [PATCH 213/249] libcli/auth: remove unused netlogon_creds_cli_context_copy() Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3d45d4dc3c69557bf1d1fe6d4a880ad74a2a41f1) --- libcli/auth/netlogon_creds_cli.c | 47 ---------------------------------------- libcli/auth/netlogon_creds_cli.h | 4 ---- 2 files changed, 51 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 6590b21..1724064 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -488,53 +488,6 @@ NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, return NT_STATUS_OK; } -NTSTATUS netlogon_creds_cli_context_copy( - const struct netlogon_creds_cli_context *src, - TALLOC_CTX *mem_ctx, - struct netlogon_creds_cli_context **_dst) -{ - struct netlogon_creds_cli_context *dst; - - dst = talloc_zero(mem_ctx, struct netlogon_creds_cli_context); - if (dst == NULL) { - return NT_STATUS_NO_MEMORY; - } - - *dst = *src; - - dst->client.computer = talloc_strdup(dst, src->client.computer); - if (dst->client.computer == NULL) { - TALLOC_FREE(dst); - return NT_STATUS_NO_MEMORY; - } - dst->client.account = talloc_strdup(dst, src->client.account); - if (dst->client.account == NULL) { - TALLOC_FREE(dst); - return NT_STATUS_NO_MEMORY; - } - dst->server.computer = talloc_strdup(dst, src->server.computer); - if (dst->server.computer == NULL) { - TALLOC_FREE(dst); - return NT_STATUS_NO_MEMORY; - } - dst->server.netbios_domain = talloc_strdup(dst, src->server.netbios_domain); - if (dst->server.netbios_domain == NULL) { - TALLOC_FREE(dst); - return NT_STATUS_NO_MEMORY; - } - - dst->db.key_name = talloc_strdup(dst, src->db.key_name); - if (dst->db.key_name == NULL) { - TALLOC_FREE(dst); - return NT_STATUS_NO_MEMORY; - } - - dst->db.key_data = string_term_tdb_data(dst->db.key_name); - - *_dst = dst; - return NT_STATUS_OK; -} - enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( struct netlogon_creds_cli_context *context) { diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h index f8f2bef..5bd8bd3 100644 --- a/libcli/auth/netlogon_creds_cli.h +++ b/libcli/auth/netlogon_creds_cli.h @@ -49,10 +49,6 @@ NTSTATUS netlogon_creds_cli_context_tmp(const char *client_computer, const char *server_netbios_domain, TALLOC_CTX *mem_ctx, struct netlogon_creds_cli_context **_context); -NTSTATUS netlogon_creds_cli_context_copy( - const struct netlogon_creds_cli_context *src, - TALLOC_CTX *mem_ctx, - struct netlogon_creds_cli_context **_dst); enum dcerpc_AuthLevel netlogon_creds_cli_auth_level( struct netlogon_creds_cli_context *context); -- 1.9.3 From aa3a65e9770bb81e73b30e71b49855b18d012e68 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 6 Dec 2013 11:38:21 +0100 Subject: [PATCH 214/249] lib/param: add "allow nt4 crypto" option, defaulting to false Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 87bdc88328568359e51af6615b378ba8dc67f647) --- docs-xml/smbdotconf/logon/allownt4crypto.xml | 26 ++++++++++++++++++++++++++ lib/param/param_functions.c | 1 + lib/param/param_table.c | 9 +++++++++ 3 files changed, 36 insertions(+) create mode 100644 docs-xml/smbdotconf/logon/allownt4crypto.xml diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml new file mode 100644 index 0000000..4d417c7 --- /dev/null +++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml @@ -0,0 +1,26 @@ + + + This option controls whether the netlogon server (currently + only in 'active directory domain controller' mode), will + reject clients which does not support NETLOGON_NEG_STRONG_KEYS + nor NETLOGON_NEG_SUPPORTS_AES. + + This option was added with Samba 4.2.0. It may lock out clients + which worked fine with Samba versions up to 4.1.x. as the effective default + was "yes" there, while it is "no" now. + + If you have clients without RequireStrongKey = 1 in the registry, + you may need to set "allow nt4 crypto = yes", until you have fixed all clients. + + + "allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks. + + This option yields precedence to the 'reject md5 clients' option. + + +no + diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c index 41b137f..bf931c6 100644 --- a/lib/param/param_functions.c +++ b/lib/param/param_functions.c @@ -154,6 +154,7 @@ FN_LOCAL_PARM_BOOL(kernel_change_notify, bKernelChangeNotify) FN_LOCAL_BOOL(durable_handles, bDurableHandles) FN_GLOBAL_BOOL(allow_insecure_widelinks, bAllowInsecureWidelinks) +FN_GLOBAL_BOOL(allow_nt4_crypto, bAllowNT4Crypto) FN_GLOBAL_BOOL(allow_trusted_domains, bAllowTrustedDomains) FN_GLOBAL_BOOL(async_smb_echo_handler, bAsyncSMBEchoHandler) FN_GLOBAL_BOOL(bind_interfaces_only, bBindInterfacesOnly) diff --git a/lib/param/param_table.c b/lib/param/param_table.c index 36e8554..5ef78de 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -4324,6 +4324,15 @@ static struct parm_struct parm_table[] = { .special = NULL, .enum_list = NULL }, + { + .label = "allow nt4 crypto", + .type = P_BOOL, + .p_class = P_GLOBAL, + .offset = GLOBAL_VAR(bAllowNT4Crypto), + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, {N_("TLS options"), P_SEP, P_SEPARATOR}, -- 1.9.3 From 51323c0574963065e2edf9346f310f08ce2b59e8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 6 Dec 2013 11:39:15 +0100 Subject: [PATCH 215/249] lib/param: add "reject md5 client" option, defaulting to false Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 807bcb4981fb20a9b97e69f01c3545ea7e85666e) --- docs-xml/smbdotconf/logon/rejectmd5clients.xml | 18 ++++++++++++++++++ lib/param/param_functions.c | 1 + lib/param/param_table.c | 9 +++++++++ 3 files changed, 28 insertions(+) create mode 100644 docs-xml/smbdotconf/logon/rejectmd5clients.xml diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml new file mode 100644 index 0000000..04a5b4d --- /dev/null +++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml @@ -0,0 +1,18 @@ + + + This option controls whether the netlogon server (currently + only in 'active directory domain controller' mode), will + reject clients which does not support NETLOGON_NEG_SUPPORTS_AES. + + You can set this to yes if all domain members support aes. + This will prevent downgrade attacks. + + This option takes precedence to the 'allow nt4 crypto' option. + + +no + diff --git a/lib/param/param_functions.c b/lib/param/param_functions.c index bf931c6..99f0b7f 100644 --- a/lib/param/param_functions.c +++ b/lib/param/param_functions.c @@ -205,6 +205,7 @@ FN_GLOBAL_BOOL(pam_password_change, bPamPasswordChange) FN_GLOBAL_BOOL(passdb_expand_explicit, bPassdbExpandExplicit) FN_GLOBAL_BOOL(passwd_chat_debug, bPasswdChatDebug) FN_GLOBAL_BOOL(registry_shares, bRegistryShares) +FN_GLOBAL_BOOL(reject_md5_clients, bRejectMD5Clients) FN_GLOBAL_BOOL(reject_md5_servers, bRejectMD5Servers) FN_GLOBAL_BOOL(require_strong_key, bRequireStrongKey) FN_GLOBAL_BOOL(reset_on_zero_vc, bResetOnZeroVC) diff --git a/lib/param/param_table.c b/lib/param/param_table.c index 5ef78de..4850324 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -4333,6 +4333,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "reject md5 clients", + .type = P_BOOL, + .p_class = P_GLOBAL, + .offset = GLOBAL_VAR(bRejectMD5Clients), + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, {N_("TLS options"), P_SEP, P_SEPARATOR}, -- 1.9.3 From 4f3cd17f89ddedaf6e34bc17b220f6ae6993d0c0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 6 Dec 2013 13:41:43 +0100 Subject: [PATCH 216/249] selftest/Samba4: use "allow nt4 crypto = yes" for testing Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 0d4806f9f056c3e37f5aed1ef19e2924aa8f4151) --- selftest/target/Samba4.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index ac2fdd9..ee6a365 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -776,6 +776,7 @@ sub provision($$$$$$$$$) server max protocol = SMB2 host msdfs = $msdfs lanman auth = yes + allow nt4 crypto = yes $extra_smbconf_options -- 1.9.3 From 32f88ae5a3d254c6e1b94ea2aaa45febf475af9e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Dec 2013 10:12:24 +0100 Subject: [PATCH 217/249] s4:netlogon: correctly calculate the negotiate_flags We need to bit-wise AND the client and server flags. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 3b77b804cdc9e7621f026ef9bc8e7059f471348e) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 59 +++++++++++++-------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index c41cd02..b001cb5 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -120,6 +120,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca const char *trust_dom_attrs[] = {"flatname", NULL}; const char *account_name; + uint32_t server_flags = 0; uint32_t negotiate_flags = 0; ZERO_STRUCTP(r->out.return_credentials); @@ -176,37 +177,33 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca memcache_delete(global_challenge_table, SINGLETON_CACHE, challenge_key); - negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT | - NETLOGON_NEG_PERSISTENT_SAMREPL | - NETLOGON_NEG_ARCFOUR | - NETLOGON_NEG_PROMOTION_COUNT | - NETLOGON_NEG_CHANGELOG_BDC | - NETLOGON_NEG_FULL_SYNC_REPL | - NETLOGON_NEG_MULTIPLE_SIDS | - NETLOGON_NEG_REDO | - NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | - NETLOGON_NEG_SEND_PASSWORD_INFO_PDC | - NETLOGON_NEG_GENERIC_PASSTHROUGH | - NETLOGON_NEG_CONCURRENT_RPC | - NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL | - NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL | - NETLOGON_NEG_TRANSITIVE_TRUSTS | - NETLOGON_NEG_DNS_DOMAIN_TRUSTS | - NETLOGON_NEG_PASSWORD_SET2 | - NETLOGON_NEG_GETDOMAININFO | - NETLOGON_NEG_CROSS_FOREST_TRUSTS | - NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION | - NETLOGON_NEG_RODC_PASSTHROUGH | - NETLOGON_NEG_AUTHENTICATED_RPC_LSASS | - NETLOGON_NEG_AUTHENTICATED_RPC; - - if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { - negotiate_flags |= NETLOGON_NEG_STRONG_KEYS; - } - - if (*r->in.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES; - } + server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT | + NETLOGON_NEG_PERSISTENT_SAMREPL | + NETLOGON_NEG_ARCFOUR | + NETLOGON_NEG_PROMOTION_COUNT | + NETLOGON_NEG_CHANGELOG_BDC | + NETLOGON_NEG_FULL_SYNC_REPL | + NETLOGON_NEG_MULTIPLE_SIDS | + NETLOGON_NEG_REDO | + NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL | + NETLOGON_NEG_SEND_PASSWORD_INFO_PDC | + NETLOGON_NEG_GENERIC_PASSTHROUGH | + NETLOGON_NEG_CONCURRENT_RPC | + NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL | + NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL | + NETLOGON_NEG_STRONG_KEYS | + NETLOGON_NEG_TRANSITIVE_TRUSTS | + NETLOGON_NEG_DNS_DOMAIN_TRUSTS | + NETLOGON_NEG_PASSWORD_SET2 | + NETLOGON_NEG_GETDOMAININFO | + NETLOGON_NEG_CROSS_FOREST_TRUSTS | + NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION | + NETLOGON_NEG_RODC_PASSTHROUGH | + NETLOGON_NEG_SUPPORTS_AES | + NETLOGON_NEG_AUTHENTICATED_RPC_LSASS | + NETLOGON_NEG_AUTHENTICATED_RPC; + + negotiate_flags = *r->in.negotiate_flags & server_flags; /* * According to Microsoft (see bugid #6099) -- 1.9.3 From ce8c9b651d9da88a13a8cd0fe02e5f3e2f1f6b51 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Dec 2013 10:10:17 +0100 Subject: [PATCH 218/249] s4:netlogon: don't generate a debug message for SEC_CHAN_NULL. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 2e36fbc77dc43f31ec78cdbef23b94bd00d6f565) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index b001cb5..45a7262 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -220,6 +220,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca case SEC_CHAN_BDC: case SEC_CHAN_RODC: break; + case SEC_CHAN_NULL: + return NT_STATUS_INVALID_PARAMETER; default: DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", r->in.secure_channel_type)); -- 1.9.3 From b4d5ace784d207f8562a4c93b55de415a81cec42 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 6 Dec 2013 12:08:50 +0100 Subject: [PATCH 219/249] s4:netlogon: implement "allow nt4 crypto" and "reject md5 clients" features. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Tue Jan 7 16:53:31 CET 2014 on sn-devel-104 (cherry picked from commit 7d2abf520df1ff46d79dfd8ff579c230f2bc3c2a) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 45a7262..6b57cda 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -122,6 +122,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca const char *account_name; uint32_t server_flags = 0; uint32_t negotiate_flags = 0; + bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx); + bool reject_des_client = !allow_nt4_crypto; + bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx); ZERO_STRUCTP(r->out.return_credentials); *r->out.rid = 0; @@ -205,6 +208,23 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca negotiate_flags = *r->in.negotiate_flags & server_flags; + if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { + reject_des_client = false; + } + + if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + reject_des_client = false; + reject_md5_client = false; + } + + if (reject_des_client || reject_md5_client) { + /* + * Here we match Windows 2012 and return no flags. + */ + *r->out.negotiate_flags = 0; + return NT_STATUS_DOWNGRADE_DETECTED; + } + /* * According to Microsoft (see bugid #6099) * Windows 7 looks at the negotiate_flags -- 1.9.3 From ff28e17cdcbe8e1ec4a275d80b3e749da4920c6d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 8 Jan 2014 12:04:22 +0100 Subject: [PATCH 220/249] libcli/auth: fix usage of an uninitialized variable in netlogon_creds_cli_check_caps() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If status is RPC_PROCNUM_OUT_OF_RANGE, result might be uninitialized. Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider Reviewed-by: Günther Deschner (cherry picked from commit 0e62f3279525ea864590f713f334f4dc5f5d3a32) --- libcli/auth/netlogon_creds_cli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 1724064..51b30a1 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1390,7 +1390,7 @@ struct netlogon_creds_cli_check_state { }; static void netlogon_creds_cli_check_cleanup(struct tevent_req *req, - NTSTATUS status); + NTSTATUS status); static void netlogon_creds_cli_check_locked(struct tevent_req *subreq); struct tevent_req *netlogon_creds_cli_check_send(TALLOC_CTX *mem_ctx, @@ -1582,7 +1582,7 @@ static void netlogon_creds_cli_check_caps(struct tevent_req *subreq) * with the next request as the sequence number processing * gets out of sync. */ - netlogon_creds_cli_check_cleanup(req, result); + netlogon_creds_cli_check_cleanup(req, status); tevent_req_done(req); return; } -- 1.9.3 From d4902881482eeecf5a219342b3862ac0fbb7b7a9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 17 Jan 2014 14:00:27 +0100 Subject: [PATCH 221/249] libcli/auth: add netlogon_creds_cli_set_global_db() This can be used to inject a db_context from dbwrap_ctdb. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit ece3ba10a16138a75b207a0cf9fe299759253d99) --- libcli/auth/netlogon_creds_cli.c | 10 ++++++++++ libcli/auth/netlogon_creds_cli.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 51b30a1..37bdf74 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -199,6 +199,16 @@ static NTSTATUS netlogon_creds_cli_context_common( static struct db_context *netlogon_creds_cli_global_db; +NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db) +{ + if (netlogon_creds_cli_global_db != NULL) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + netlogon_creds_cli_global_db = talloc_move(talloc_autofree_context(), db); + return NT_STATUS_OK; +} + NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx) { char *fname; diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h index 5bd8bd3..90d0182 100644 --- a/libcli/auth/netlogon_creds_cli.h +++ b/libcli/auth/netlogon_creds_cli.h @@ -28,7 +28,9 @@ struct netlogon_creds_cli_context; struct messaging_context; struct dcerpc_binding_handle; +struct db_context; +NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db); NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, -- 1.9.3 From 80407a74da35cac64bef252698a2477787f0997d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 17 Jan 2014 14:07:37 +0100 Subject: [PATCH 222/249] s3:rpc_client: use db_open() to open "netlogon_creds_cli.tdb" This uses dbwrap_ctdb if running in a cluster. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 8cf4eff201aa9e1ba8127311bcfc2a357fb4ef03) --- source3/rpc_client/cli_netlogon.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index ca2d9bf..b7b490f 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -21,6 +21,7 @@ */ #include "includes.h" +#include "system/filesys.h" #include "libsmb/libsmb.h" #include "rpc_client/rpc_client.h" #include "rpc_client/cli_pipe.h" @@ -34,26 +35,53 @@ #include "../libcli/security/security.h" #include "lib/param/param.h" #include "libcli/smb/smbXcli_base.h" +#include "dbwrap/dbwrap.h" +#include "dbwrap/dbwrap_open.h" +#include "util_tdb.h" NTSTATUS rpccli_pre_open_netlogon_creds(void) { - TALLOC_CTX *frame = talloc_stackframe(); + static bool already_open = false; + TALLOC_CTX *frame; struct loadparm_context *lp_ctx; + char *fname; + struct db_context *global_db; NTSTATUS status; + if (already_open) { + return NT_STATUS_OK; + } + + frame = talloc_stackframe(); + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); if (lp_ctx == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } - status = netlogon_creds_cli_open_global_db(lp_ctx); + fname = lpcfg_private_db_path(frame, lp_ctx, "netlogon_creds_cli"); + if (fname == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + global_db = db_open(talloc_autofree_context(), fname, + 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, + O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2); + if (global_db == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + status = netlogon_creds_cli_set_global_db(&global_db); TALLOC_FREE(frame); if (!NT_STATUS_IS_OK(status)) { return status; } + already_open = true; return NT_STATUS_OK; } @@ -69,6 +97,12 @@ NTSTATUS rpccli_create_netlogon_creds(const char *server_computer, struct loadparm_context *lp_ctx; NTSTATUS status; + status = rpccli_pre_open_netlogon_creds(); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); if (lp_ctx == NULL) { TALLOC_FREE(frame); -- 1.9.3 From 2ed3041405f5808031f2d5fd0e42f48246d22b7b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 17 Jan 2014 14:08:59 +0100 Subject: [PATCH 223/249] libcli/auth: don't alter the computer_name in cluster mode. This breaks NTLMv2 authentication. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 387ed2e15df085274f72cebda341040a1e767a4b) --- libcli/auth/netlogon_creds_cli.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 37bdf74..88893ad 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -261,28 +261,12 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, bool seal_secure_channel = true; enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; bool neutralize_nt4_emulation = false; - struct server_id self = { - .vnn = NONCLUSTER_VNN, - .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY, - }; - - if (msg_ctx != NULL) { - self = messaging_server_id(msg_ctx); - } *_context = NULL; - if (self.vnn != NONCLUSTER_VNN) { - client_computer = talloc_asprintf(frame, - "%s_cluster_vnn_%u", - lpcfg_netbios_name(lp_ctx), - (unsigned)self.vnn); - if (client_computer == NULL) { - TALLOC_FREE(frame); - return NT_STATUS_NO_MEMORY; - } - } else { - client_computer = lpcfg_netbios_name(lp_ctx); + client_computer = lpcfg_netbios_name(lp_ctx); + if (strlen(client_computer) > 15) { + return NT_STATUS_INVALID_PARAMETER_MIX; } /* -- 1.9.3 From 8257c3a5d6e8319578d224e544242da81b043a54 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Jan 2014 13:13:40 +0100 Subject: [PATCH 224/249] libcli/auth: reject computer_name longer than 15 chars This matches Windows, it seems they use a fixed size field to store netlogon_creds_CredentialState. Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit b8fdeb8ca7ce362058bb86a4e58b34fb6340867e) --- libcli/auth/schannel_state_tdb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libcli/auth/schannel_state_tdb.c b/libcli/auth/schannel_state_tdb.c index 8f9c1f0..b91e242 100644 --- a/libcli/auth/schannel_state_tdb.c +++ b/libcli/auth/schannel_state_tdb.c @@ -78,6 +78,14 @@ NTSTATUS schannel_store_session_key_tdb(struct db_context *db_sc, char *name_upper; NTSTATUS status; + if (strlen(creds->computer_name) > 15) { + /* + * We may want to check for a completely + * valid netbios name. + */ + return STATUS_BUFFER_OVERFLOW; + } + name_upper = strupper_talloc(mem_ctx, creds->computer_name); if (!name_upper) { return NT_STATUS_NO_MEMORY; -- 1.9.3 From d6af8ed76f728621a8ba7515cf1180d6654c8d83 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 11 Jan 2014 17:13:04 +0100 Subject: [PATCH 225/249] s3:rpc_server/netlogon: return a zero return_authenticator on error Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit dcc2c8362df9af088613722ebd8a6261fb098a5c) --- source3/rpc_server/netlogon/srv_netlog_nt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 09857b6..7bb9dd6 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1020,6 +1020,7 @@ NTSTATUS _netr_ServerAuthenticate3(struct pipes_struct *p, talloc_unlink(p->mem_ctx, lp_ctx); if (!NT_STATUS_IS_OK(status)) { + ZERO_STRUCTP(r->out.return_credentials); goto out; } -- 1.9.3 From be06629b25f8340ac54a9e674e6a5da1eb01e733 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 11 Jan 2014 17:13:04 +0100 Subject: [PATCH 226/249] s4:rpc_server/netlogon: return a zero return_authenticator and rid on error Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 25fb73f2821821630dde4cc263794e754ca03d68) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 6b57cda..afa15d8 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -348,9 +348,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca return NT_STATUS_INTERNAL_ERROR; } - *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], - "objectSid", 0); - mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd"); if (mach_pwd == NULL) { return NT_STATUS_ACCESS_DENIED; @@ -383,8 +380,15 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca nt_status = schannel_save_creds_state(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, creds); + if (!NT_STATUS_IS_OK(nt_status)) { + ZERO_STRUCTP(r->out.return_credentials); + return nt_status; + } - return nt_status; + *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], + "objectSid", 0); + + return NT_STATUS_OK; } static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, -- 1.9.3 From f5fe58d49fc66867db743393a92e1cd8e4cb293b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 29 Jan 2014 16:58:37 +0100 Subject: [PATCH 227/249] dbwrap_tool: remove the short form "-p" of "--persistent" Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 6dd1008c4e8b0b798d589959021c9b578db74ff4) --- source3/utils/dbwrap_tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c index 79b40d2..406e89e 100644 --- a/source3/utils/dbwrap_tool.c +++ b/source3/utils/dbwrap_tool.c @@ -420,7 +420,7 @@ int main(int argc, const char **argv) struct poptOption popt_options[] = { POPT_AUTOHELP POPT_COMMON_SAMBA - { "persistent", 'p', POPT_ARG_NONE, &persistent, 0, "treat the database as persistent", NULL }, + { "persistent", 0, POPT_ARG_NONE, &persistent, 0, "treat the database as persistent", NULL }, POPT_TABLEEND }; int opt; -- 1.9.3 From 209b5ec86620f8caadcc714db0cbec4789db0377 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 30 Jan 2014 10:33:00 +0100 Subject: [PATCH 228/249] docs: remove short form "-p" of --persistent from dbwrap_tool manpage Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 6f748fef652bbea3c8dbbbfb96b95270e6f1dcfc) --- docs-xml/manpages/dbwrap_tool.1.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-xml/manpages/dbwrap_tool.1.xml b/docs-xml/manpages/dbwrap_tool.1.xml index 074d819..94ae281 100644 --- a/docs-xml/manpages/dbwrap_tool.1.xml +++ b/docs-xml/manpages/dbwrap_tool.1.xml @@ -19,7 +19,7 @@ dbwrap_tool - -p|--persistent + --persistent -d <debug level> -s <config file> -l <log file base> @@ -70,7 +70,7 @@ - -p|--persistent + --persistent Open the database as a persistent database. If this option is not specified, the database is opened as non-persistent. -- 1.9.3 From f3b8b74ff6d74fe9a0047256074e21c3363b112f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 30 Jan 2014 10:29:49 +0100 Subject: [PATCH 229/249] dbwrap_tool: add option "--non-persistent" and force excatly one of "--[non-]persistent" We want to force users of dbwrap_tool to explicitly specify persistent or non-persistent. Otherwise, one could easily by accident wipe a whole database that is actually persistent but not currently opened by a samba process, just by openeing the DB with the default non-persistent mode... Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit c3f93271ef447f9f16cd3002307c630c5f149f5a) --- source3/utils/dbwrap_tool.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c index 406e89e..ffca6b6 100644 --- a/source3/utils/dbwrap_tool.c +++ b/source3/utils/dbwrap_tool.c @@ -411,6 +411,7 @@ int main(int argc, const char **argv) enum dbwrap_type type; const char *valuestr = "0"; int persistent = 0; + int non_persistent = 0; int tdb_flags = TDB_DEFAULT; TALLOC_CTX *mem_ctx = talloc_stackframe(); @@ -420,7 +421,13 @@ int main(int argc, const char **argv) struct poptOption popt_options[] = { POPT_AUTOHELP POPT_COMMON_SAMBA - { "persistent", 0, POPT_ARG_NONE, &persistent, 0, "treat the database as persistent", NULL }, + { "non-persistent", 0, POPT_ARG_NONE, &non_persistent, 0, + "treat the database as non-persistent " + "(CAVEAT: This mode might wipe your database!)", + NULL }, + { "persistent", 0, POPT_ARG_NONE, &persistent, 0, + "treat the database as persistent", + NULL }, POPT_TABLEEND }; int opt; @@ -463,6 +470,16 @@ int main(int argc, const char **argv) goto done; } + if ((persistent == 0 && non_persistent == 0) || + (persistent == 1 && non_persistent == 1)) + { + d_fprintf(stderr, "ERROR: you must specify exactly one " + "of --persistent and --non-persistent\n"); + goto done; + } else if (non_persistent == 1) { + tdb_flags |= TDB_CLEAR_IF_FIRST; + } + dbname = extra_argv[0]; opname = extra_argv[1]; @@ -563,10 +580,6 @@ int main(int argc, const char **argv) goto done; } - if (persistent == 0) { - tdb_flags |= TDB_CLEAR_IF_FIRST; - } - switch (op) { case OP_FETCH: case OP_STORE: -- 1.9.3 From 7209e84e02c722365bec4e2a473c24217cbeb22b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 30 Jan 2014 10:36:46 +0100 Subject: [PATCH 230/249] docs: document new --non-persistent option to dbwrap_tool Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 1e3b352f799038ec25437db53e051dadb9d97c95) --- docs-xml/manpages/dbwrap_tool.1.xml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs-xml/manpages/dbwrap_tool.1.xml b/docs-xml/manpages/dbwrap_tool.1.xml index 94ae281..ff0e478 100644 --- a/docs-xml/manpages/dbwrap_tool.1.xml +++ b/docs-xml/manpages/dbwrap_tool.1.xml @@ -20,6 +20,7 @@ dbwrap_tool --persistent + --non-persistent -d <debug level> -s <config file> -l <log file base> @@ -72,8 +73,23 @@ --persistent Open the database as a persistent database. - If this option is not specified, the database is opened as - non-persistent. + + + Exactly one of --persistent and --non-persistent must be + specified. + + + + --non-persistent + Open the database as a non-persistent database. + + + Caveat: opening a database as non-persistent when there + is currently no other opener will wipe the database. + + + Exactly one of --persistent and --non-persistent must be + specified. &popt.common.samba.client; -- 1.9.3 From accf5a617055c161540384fdfe195ad9c43cd048 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 30 Jan 2014 10:47:15 +0100 Subject: [PATCH 231/249] docs: remove extra spaces in synopsis of dbwrap_tool Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit e93f052e37e736e5776fe7f7c7d246f9ecc4b4c8) --- docs-xml/manpages/dbwrap_tool.1.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs-xml/manpages/dbwrap_tool.1.xml b/docs-xml/manpages/dbwrap_tool.1.xml index ff0e478..68a88df 100644 --- a/docs-xml/manpages/dbwrap_tool.1.xml +++ b/docs-xml/manpages/dbwrap_tool.1.xml @@ -30,9 +30,7 @@ <operation> <key> <type> - <value> - - + <value> -- 1.9.3 From 0e193981caa2ad9458e758a46076664d2efdb70e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 24 Jan 2014 00:09:50 +0100 Subject: [PATCH 232/249] smbd:smb2: fix durable reconnect: set fsp->fnum from the smbXsrv_open->local_id Originally, fsp->fnum was left at the INVALID fnum value. Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 6b2d67a345e90306f0d35402d0f4e3067a014057) --- source3/smbd/durable.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c index c3d0a6f..471c5b9 100644 --- a/source3/smbd/durable.c +++ b/source3/smbd/durable.c @@ -703,6 +703,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, fsp->share_access = e->share_access; fsp->can_read = ((fsp->access_mask & (FILE_READ_DATA)) != 0); fsp->can_write = ((fsp->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) != 0); + fsp->fnum = op->local_id; /* * TODO: -- 1.9.3 From dbc1d6f8479cf84c714c4ed6b69df2a3673d0a46 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 24 Dec 2013 09:00:01 +0100 Subject: [PATCH 233/249] s3:smbd: skip empty records in smbXsrv_open_cleanup() This should avoid scary ndr_pull errors, if there's a cleanup race. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Thu Jan 30 18:49:37 CET 2014 on sn-devel-104 (cherry picked from commit 0b23345676c6f02d5bb1a327174d8456705ec0c7) --- source3/smbd/smbXsrv_open.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c index 27dd50c..29c172c 100644 --- a/source3/smbd/smbXsrv_open.c +++ b/source3/smbd/smbXsrv_open.c @@ -1380,6 +1380,7 @@ NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) struct smbXsrv_open_global0 *op = NULL; uint8_t key_buf[SMBXSRV_OPEN_GLOBAL_TDB_KEY_SIZE]; TDB_DATA key; + TDB_DATA val; struct db_record *rec; bool delete_open = false; uint32_t global_id = persistent_id & UINT32_MAX; @@ -1395,6 +1396,14 @@ NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) goto done; } + val = dbwrap_record_get_value(rec); + if (val.dsize == 0) { + DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " + "empty record in %s, skipping...\n", + global_id, dbwrap_name(smbXsrv_open_global_db_ctx))); + goto done; + } + status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " -- 1.9.3 From 838d9da4a7fe6c90ba7cae6563f0af5d8b6cf6d5 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 27 Jan 2014 13:38:51 +0100 Subject: [PATCH 234/249] dbwrap: add flags DBWRAP_FLAG_NONE This is in preparation of adding a dbwrap_flags argument to db_open and firends. Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 229dcfd3501e4743d5d9aea5c9f7a97d7612a499) --- lib/dbwrap/dbwrap.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h index 8bf3286..4064ba2 100644 --- a/lib/dbwrap/dbwrap.h +++ b/lib/dbwrap/dbwrap.h @@ -32,6 +32,8 @@ enum dbwrap_lock_order { }; #define DBWRAP_LOCK_ORDER_MAX DBWRAP_LOCK_ORDER_3 +#define DBWRAP_FLAG_NONE 0x0000000000000000ULL + /* The following definitions come from lib/dbwrap.c */ TDB_DATA dbwrap_record_get_key(const struct db_record *rec); -- 1.9.3 From 868d8e2fa389ab0c697e9a70a4373908aa7df80b Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 27 Jan 2014 14:49:12 +0100 Subject: [PATCH 235/249] dbwrap: add a dbwrap_flags argument to db_open() This is in preparation to support handing flags to backends, in particular activating read only record support for ctdb databases. For a start, this does nothing but adding the parameter, and all databases use DBWRAP_FLAG_NONE. Signed-off-by: Michael Adam (similar to commit cf0cb0add9ed47b8974272237fee0e1a4ba7bf68) --- source3/groupdb/mapping_tdb.c | 2 +- source3/lib/dbwrap/dbwrap_open.c | 3 ++- source3/lib/dbwrap/dbwrap_open.h | 3 ++- source3/lib/dbwrap/dbwrap_watch.c | 3 ++- source3/lib/g_lock.c | 3 ++- source3/lib/serverid.c | 3 ++- source3/lib/sharesec.c | 2 +- source3/locking/brlock.c | 2 +- source3/locking/share_mode_lock.c | 2 +- source3/modules/vfs_acl_tdb.c | 2 +- source3/modules/vfs_xattr_tdb.c | 2 +- source3/passdb/account_pol.c | 4 ++-- source3/passdb/pdb_tdb.c | 6 +++--- source3/passdb/secrets.c | 2 +- source3/printing/printer_list.c | 3 ++- source3/registry/reg_backend_db.c | 6 +++--- source3/rpc_client/cli_netlogon.c | 3 ++- source3/smbd/notify_internal.c | 2 +- source3/smbd/smbXsrv_open.c | 3 ++- source3/smbd/smbXsrv_session.c | 3 ++- source3/smbd/smbXsrv_tcon.c | 3 ++- source3/smbd/smbXsrv_version.c | 3 ++- source3/torture/test_dbwrap_watch.c | 3 ++- source3/torture/test_idmap_tdb_common.c | 2 +- source3/torture/torture.c | 3 ++- source3/utils/dbwrap_tool.c | 2 +- source3/utils/dbwrap_torture.c | 2 +- source3/utils/net_idmap.c | 6 +++--- source3/utils/net_idmap_check.c | 2 +- source3/utils/net_registry_check.c | 4 ++-- source3/utils/status.c | 2 +- source3/winbindd/idmap_autorid.c | 2 +- source3/winbindd/idmap_tdb.c | 2 +- source3/winbindd/idmap_tdb2.c | 2 +- 34 files changed, 55 insertions(+), 42 deletions(-) diff --git a/source3/groupdb/mapping_tdb.c b/source3/groupdb/mapping_tdb.c index 088874f..0863187 100644 --- a/source3/groupdb/mapping_tdb.c +++ b/source3/groupdb/mapping_tdb.c @@ -54,7 +54,7 @@ static bool init_group_mapping(void) db = db_open(NULL, state_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { DEBUG(0, ("Failed to open group mapping database: %s\n", strerror(errno))); diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c index 515b4bf..6c9280c 100644 --- a/source3/lib/dbwrap/dbwrap_open.c +++ b/source3/lib/dbwrap/dbwrap_open.c @@ -60,7 +60,8 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - enum dbwrap_lock_order lock_order) + enum dbwrap_lock_order lock_order, + uint64_t dbwrap_flags) { struct db_context *result = NULL; #ifdef CLUSTER_SUPPORT diff --git a/source3/lib/dbwrap/dbwrap_open.h b/source3/lib/dbwrap/dbwrap_open.h index 51c7dfd..d14794e 100644 --- a/source3/lib/dbwrap/dbwrap_open.h +++ b/source3/lib/dbwrap/dbwrap_open.h @@ -39,6 +39,7 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - enum dbwrap_lock_order lock_order); + enum dbwrap_lock_order lock_order, + uint64_t dbwrap_flags); #endif /* __DBWRAP_OPEN_H__ */ diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c index 7bdcd99..5f3d17d 100644 --- a/source3/lib/dbwrap/dbwrap_watch.c +++ b/source3/lib/dbwrap/dbwrap_watch.c @@ -34,7 +34,8 @@ static struct db_context *dbwrap_record_watchers_db(void) watchers_db = db_open( NULL, lock_path("dbwrap_watchers.tdb"), 0, TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH, - O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_3); + O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_3, + DBWRAP_FLAG_NONE); } return watchers_db; } diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c index 8c7a6c2..6813f06 100644 --- a/source3/lib/g_lock.c +++ b/source3/lib/g_lock.c @@ -61,7 +61,8 @@ struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx, result->db = db_open(result, lock_path("g_lock.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_2); + DBWRAP_LOCK_ORDER_2, + DBWRAP_FLAG_NONE); if (result->db == NULL) { DEBUG(1, ("g_lock_init: Could not open g_lock.tdb\n")); TALLOC_FREE(result); diff --git a/source3/lib/serverid.c b/source3/lib/serverid.c index cb49520..4259887 100644 --- a/source3/lib/serverid.c +++ b/source3/lib/serverid.c @@ -77,7 +77,8 @@ static struct db_context *serverid_db(void) } db = db_open(NULL, lock_path("serverid.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, - O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_2); + O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_2, + DBWRAP_FLAG_NONE); return db; } diff --git a/source3/lib/sharesec.c b/source3/lib/sharesec.c index c7a8e51..095c851 100644 --- a/source3/lib/sharesec.c +++ b/source3/lib/sharesec.c @@ -149,7 +149,7 @@ bool share_info_db_init(void) share_db = db_open(NULL, state_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (share_db == NULL) { DEBUG(0,("Failed to open share info database %s (%s)\n", state_path("share_info.tdb"), strerror(errno) )); diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 5d683dd..d88aa2d 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -292,7 +292,7 @@ void brl_init(bool read_only) brlock_db = db_open(NULL, lock_path("brlock.tdb"), lp_open_files_db_hash_size(), tdb_flags, read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644, - DBWRAP_LOCK_ORDER_2); + DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE); if (!brlock_db) { DEBUG(0,("Failed to open byte range locking database %s\n", lock_path("brlock.tdb"))); diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 4f049bd..22f8d9a 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -67,7 +67,7 @@ static bool locking_init_internal(bool read_only) lp_open_files_db_hash_size(), TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, read_only?O_RDONLY:O_RDWR|O_CREAT, 0644, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (!lock_db) { DEBUG(0,("ERROR: Failed to initialise locking database\n")); diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index 80839e3..8ee4bd5 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -60,7 +60,7 @@ static bool acl_tdb_init(void) become_root(); acl_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); unbecome_root(); if (acl_db == NULL) { diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index 43456cf..63a12fd 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -320,7 +320,7 @@ static bool xattr_tdb_init(int snum, TALLOC_CTX *mem_ctx, struct db_context **p_ become_root(); db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_2); + DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE); unbecome_root(); if (db == NULL) { diff --git a/source3/passdb/account_pol.c b/source3/passdb/account_pol.c index c94df29..09a2d20 100644 --- a/source3/passdb/account_pol.c +++ b/source3/passdb/account_pol.c @@ -220,13 +220,13 @@ bool init_account_policy(void) } db = db_open(NULL, state_path("account_policy.tdb"), 0, TDB_DEFAULT, - O_RDWR, 0600, DBWRAP_LOCK_ORDER_1); + O_RDWR, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { /* the account policies files does not exist or open * failed, try to create a new one */ db = db_open(NULL, state_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { DEBUG(0,("Failed to open account policy database\n")); return False; diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index f256e6c..162083f 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -226,7 +226,7 @@ static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) tmp_db = db_open(NULL, tmp_fname, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (tmp_db == NULL) { DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd " "[%s]\n", tmp_fname)); @@ -293,7 +293,7 @@ static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) orig_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (orig_db == NULL) { DEBUG(0, ("tdbsam_convert_backup: Failed to re-open " "converted passdb TDB [%s]\n", dbname)); @@ -444,7 +444,7 @@ static bool tdbsam_open( const char *name ) /* Try to open tdb passwd. Create a new one if necessary */ db_sam = db_open(NULL, name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db_sam == NULL) { DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd " "[%s]\n", name)); diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 548b030..bff9a0d 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -79,7 +79,7 @@ bool secrets_init_path(const char *private_dir, bool use_ntdb) db_ctx = db_open(NULL, fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db_ctx == NULL) { DEBUG(0,("Failed to open %s\n", fname)); diff --git a/source3/printing/printer_list.c b/source3/printing/printer_list.c index 815f89f..9a9fa0b 100644 --- a/source3/printing/printer_list.c +++ b/source3/printing/printer_list.c @@ -40,7 +40,8 @@ static struct db_context *get_printer_list_db(void) } db = db_open(NULL, PL_DB_NAME(), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, - O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_1); + O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_1, + DBWRAP_FLAG_NONE); return db; } diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 3e561eb..fdaf576 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -732,11 +732,11 @@ WERROR regdb_init(void) regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (!regdb) { regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (!regdb) { werr = ntstatus_to_werror(map_nt_error_from_unix(errno)); DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n", @@ -852,7 +852,7 @@ WERROR regdb_open( void ) regdb = db_open(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if ( !regdb ) { result = ntstatus_to_werror( map_nt_error_from_unix( errno ) ); DEBUG(0,("regdb_open: Failed to open %s! (%s)\n", diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index b7b490f..9e3c1bd 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -69,7 +69,8 @@ NTSTATUS rpccli_pre_open_netlogon_creds(void) global_db = db_open(talloc_autofree_context(), fname, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, - O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2); + O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2, + DBWRAP_FLAG_NONE); if (global_db == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 2dc8674..67d8774 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -145,7 +145,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, notify->db_index = db_open( notify, lock_path("notify_index.tdb"), 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, - O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_3); + O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_3, DBWRAP_FLAG_NONE); if (notify->db_index == NULL) { goto fail; } diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c index 29c172c..830c7aa 100644 --- a/source3/smbd/smbXsrv_open.c +++ b/source3/smbd/smbXsrv_open.c @@ -64,7 +64,8 @@ NTSTATUS smbXsrv_open_global_init(void) TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH, O_RDWR | O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, + DBWRAP_FLAG_NONE); if (db_ctx == NULL) { NTSTATUS status; diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index 017880c..a1ba52d 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -75,7 +75,8 @@ NTSTATUS smbXsrv_session_global_init(void) TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH, O_RDWR | O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, + DBWRAP_FLAG_NONE); if (db_ctx == NULL) { NTSTATUS status; diff --git a/source3/smbd/smbXsrv_tcon.c b/source3/smbd/smbXsrv_tcon.c index b6e2058..2cbd761 100644 --- a/source3/smbd/smbXsrv_tcon.c +++ b/source3/smbd/smbXsrv_tcon.c @@ -62,7 +62,8 @@ NTSTATUS smbXsrv_tcon_global_init(void) TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH, O_RDWR | O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, + DBWRAP_FLAG_NONE); if (db_ctx == NULL) { NTSTATUS status; diff --git a/source3/smbd/smbXsrv_version.c b/source3/smbd/smbXsrv_version.c index 8ba5e1f..b24dae9 100644 --- a/source3/smbd/smbXsrv_version.c +++ b/source3/smbd/smbXsrv_version.c @@ -80,7 +80,8 @@ NTSTATUS smbXsrv_version_global_init(const struct server_id *server_id) TDB_CLEAR_IF_FIRST | TDB_INCOMPATIBLE_HASH, O_RDWR | O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, + DBWRAP_FLAG_NONE); if (db_ctx == NULL) { status = map_nt_error_from_unix_common(errno); DEBUG(0,("smbXsrv_version_global_init: " diff --git a/source3/torture/test_dbwrap_watch.c b/source3/torture/test_dbwrap_watch.c index 9c2a679..4e699fe 100644 --- a/source3/torture/test_dbwrap_watch.c +++ b/source3/torture/test_dbwrap_watch.c @@ -48,7 +48,8 @@ bool run_dbwrap_watch1(int dummy) goto fail; } db = db_open(msg, "test_watch.tdb", 0, TDB_DEFAULT, - O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1); + O_CREAT|O_RDWR, 0644, DBWRAP_LOCK_ORDER_1, + DBWRAP_FLAG_NONE); if (db == NULL) { fprintf(stderr, "db_open failed: %s\n", strerror(errno)); goto fail; diff --git a/source3/torture/test_idmap_tdb_common.c b/source3/torture/test_idmap_tdb_common.c index 6f5f3c5..f7262a2 100644 --- a/source3/torture/test_idmap_tdb_common.c +++ b/source3/torture/test_idmap_tdb_common.c @@ -86,7 +86,7 @@ static bool open_db(struct idmap_tdb_common_context *ctx) ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if(!ctx->db) { DEBUG(0, ("Failed to open database: %s\n", strerror(errno))); diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 2e66912..1dc3eaf 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -9011,7 +9011,8 @@ static bool run_local_dbtrans(int dummy) TDB_DATA value; db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT, - O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1); + O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1, + DBWRAP_FLAG_NONE); if (db == NULL) { printf("Could not open transtest.db\n"); return false; diff --git a/source3/utils/dbwrap_tool.c b/source3/utils/dbwrap_tool.c index ffca6b6..b56e07a 100644 --- a/source3/utils/dbwrap_tool.c +++ b/source3/utils/dbwrap_tool.c @@ -588,7 +588,7 @@ int main(int argc, const char **argv) case OP_LISTKEYS: case OP_EXISTS: db = db_open(mem_ctx, dbname, 0, tdb_flags, O_RDWR | O_CREAT, - 0644, DBWRAP_LOCK_ORDER_1); + 0644, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { d_fprintf(stderr, "ERROR: could not open dbname\n"); goto done; diff --git a/source3/utils/dbwrap_torture.c b/source3/utils/dbwrap_torture.c index 2741820..f748ac2 100644 --- a/source3/utils/dbwrap_torture.c +++ b/source3/utils/dbwrap_torture.c @@ -309,7 +309,7 @@ int main(int argc, const char *argv[]) } db = db_open(mem_ctx, db_name, 0, tdb_flags, O_RDWR | O_CREAT, 0644, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { d_fprintf(stderr, "failed to open db '%s': %s\n", db_name, diff --git a/source3/utils/net_idmap.c b/source3/utils/net_idmap.c index fbeca3e..6fc07e7 100644 --- a/source3/utils/net_idmap.c +++ b/source3/utils/net_idmap.c @@ -210,7 +210,7 @@ static int net_idmap_dump(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, _("dumping id mapping from %s\n"), dbfile); db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDONLY, 0, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"), dbfile, strerror(errno)); @@ -336,7 +336,7 @@ static int net_idmap_restore(struct net_context *c, int argc, const char **argv) } db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"), dbfile, strerror(errno)); @@ -546,7 +546,7 @@ static int net_idmap_delete(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, _("deleting id mapping from %s\n"), dbfile); db = db_open(mem_ctx, dbfile, 0, TDB_DEFAULT, O_RDWR, 0, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { d_fprintf(stderr, _("Could not open idmap db (%s): %s\n"), dbfile, strerror(errno)); diff --git a/source3/utils/net_idmap_check.c b/source3/utils/net_idmap_check.c index e75c890..4b82871 100644 --- a/source3/utils/net_idmap_check.c +++ b/source3/utils/net_idmap_check.c @@ -790,7 +790,7 @@ static bool check_open_db(struct check_ctx* ctx, const char* name, int oflags) } ctx->db = db_open(ctx, name, 0, TDB_DEFAULT, oflags, 0, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (ctx->db == NULL) { d_fprintf(stderr, _("Could not open idmap db (%s) for writing: %s\n"), diff --git a/source3/utils/net_registry_check.c b/source3/utils/net_registry_check.c index 8cdb8fa..d57c2aa 100644 --- a/source3/utils/net_registry_check.c +++ b/source3/utils/net_registry_check.c @@ -338,7 +338,7 @@ static bool check_ctx_open_output(struct check_ctx *ctx) } ctx->odb = db_open(ctx, ctx->opt.output, 0, TDB_DEFAULT, oflags, 0644, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (ctx->odb == NULL) { d_fprintf(stderr, _("Could not open db (%s) for writing: %s\n"), @@ -351,7 +351,7 @@ static bool check_ctx_open_output(struct check_ctx *ctx) static bool check_ctx_open_input(struct check_ctx *ctx) { ctx->idb = db_open(ctx, ctx->fname, 0, TDB_DEFAULT, O_RDONLY, 0, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (ctx->idb == NULL) { d_fprintf(stderr, _("Could not open db (%s) for reading: %s\n"), diff --git a/source3/utils/status.c b/source3/utils/status.c index be7c52f..1ff0e36 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -508,7 +508,7 @@ static void print_notify_recs(const char *path, struct db_context *db; db = db_open(NULL, lock_path("locking.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDONLY, 0, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (!db) { d_printf("%s not initialised\n", diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c index 57d952e..0bd2938 100644 --- a/source3/winbindd/idmap_autorid.c +++ b/source3/winbindd/idmap_autorid.c @@ -728,7 +728,7 @@ static NTSTATUS idmap_autorid_db_init(void) /* Open idmap repository */ autorid_db = db_open(NULL, state_path("autorid.tdb"), 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (!autorid_db) { DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index cc930ff..ebff347 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -321,7 +321,7 @@ static NTSTATUS idmap_tdb_open_db(struct idmap_domain *dom) /* Open idmap repository */ db = db_open(mem_ctx, tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (!db) { DEBUG(0, ("Unable to open idmap database\n")); ret = NT_STATUS_UNSUCCESSFUL; diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index 4a9c2fe..942490d 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -114,7 +114,7 @@ static NTSTATUS idmap_tdb2_open_db(struct idmap_domain *dom) /* Open idmap repository */ ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644, - DBWRAP_LOCK_ORDER_1); + DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); TALLOC_FREE(db_path); if (ctx->db == NULL) { -- 1.9.3 From b904731a81df57b3d33fe0c35663bc47d061d744 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 28 Jan 2014 12:53:24 +0100 Subject: [PATCH 236/249] dbwrap: add a dbwrap_flags argument to db_open_ctdb() This is in preparation of directly supporting ctdb read only record copies when opening a ctdb database from samba. Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 6def1c3f6e145abcc81ea69505133bbe128eacac) --- source3/lib/dbwrap/dbwrap_ctdb.c | 6 ++++-- source3/lib/dbwrap/dbwrap_ctdb.h | 3 ++- source3/lib/dbwrap/dbwrap_open.c | 2 +- source3/torture/test_dbwrap_ctdb.c | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c index 5a473f9..af7a72f 100644 --- a/source3/lib/dbwrap/dbwrap_ctdb.c +++ b/source3/lib/dbwrap/dbwrap_ctdb.c @@ -1498,7 +1498,8 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - enum dbwrap_lock_order lock_order) + enum dbwrap_lock_order lock_order, + uint64_t dbwrap_flags) { struct db_context *result; struct db_ctdb_ctx *db_ctdb; @@ -1624,7 +1625,8 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - enum dbwrap_lock_order lock_order) + enum dbwrap_lock_order lock_order, + uint64_t dbwrap_flags) { DEBUG(3, ("db_open_ctdb: no cluster support!\n")); errno = ENOSYS; diff --git a/source3/lib/dbwrap/dbwrap_ctdb.h b/source3/lib/dbwrap/dbwrap_ctdb.h index bfbe3bd..3196b91 100644 --- a/source3/lib/dbwrap/dbwrap_ctdb.h +++ b/source3/lib/dbwrap/dbwrap_ctdb.h @@ -31,6 +31,7 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - enum dbwrap_lock_order lock_order); + enum dbwrap_lock_order lock_order, + uint64_t dbwrap_flags); #endif /* __DBWRAP_CTDB_H__ */ diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c index 6c9280c..61324f7 100644 --- a/source3/lib/dbwrap/dbwrap_open.c +++ b/source3/lib/dbwrap/dbwrap_open.c @@ -104,7 +104,7 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, if (lp_parm_bool(-1, "ctdb", partname, True)) { result = db_open_ctdb(mem_ctx, partname, hash_size, tdb_flags, open_flags, mode, - lock_order); + lock_order, dbwrap_flags); if (result == NULL) { DEBUG(0,("failed to attach to ctdb %s\n", partname)); diff --git a/source3/torture/test_dbwrap_ctdb.c b/source3/torture/test_dbwrap_ctdb.c index f7672ba..d7380b1 100644 --- a/source3/torture/test_dbwrap_ctdb.c +++ b/source3/torture/test_dbwrap_ctdb.c @@ -32,7 +32,7 @@ bool run_local_dbwrap_ctdb(int dummy) uint32_t val; db = db_open_ctdb(talloc_tos(), "torture.tdb", 0, TDB_DEFAULT, - O_RDWR, 0755, DBWRAP_LOCK_ORDER_1); + O_RDWR, 0755, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); if (db == NULL) { perror("db_open_ctdb failed"); goto fail; -- 1.9.3 From 4f2d14112981d03000b533458e2e60a032d052de Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 28 Jan 2014 11:31:44 +0100 Subject: [PATCH 237/249] dbwrap: add DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 56bd4040889dfe492ff820497b7a6d76624a6048) --- lib/dbwrap/dbwrap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/dbwrap/dbwrap.h b/lib/dbwrap/dbwrap.h index 4064ba2..02b4405 100644 --- a/lib/dbwrap/dbwrap.h +++ b/lib/dbwrap/dbwrap.h @@ -33,6 +33,7 @@ enum dbwrap_lock_order { #define DBWRAP_LOCK_ORDER_MAX DBWRAP_LOCK_ORDER_3 #define DBWRAP_FLAG_NONE 0x0000000000000000ULL +#define DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS 0x0000000000000001ULL /* The following definitions come from lib/dbwrap.c */ -- 1.9.3 From a007f8f7f627c4347f48bd2446637aab137e0608 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Jan 2014 21:24:22 +0100 Subject: [PATCH 238/249] dbwrap_ctdb: implement DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS For non-persistent databases we try to use CTDB_CONTROL_SET_DB_READONLY in order to make use of readonly records. Pair-Programmed-With: Michael Adam Signed-off-by: Stefan Metzmacher Signed-off-by: Michael Adam (cherry picked from commit a97b588b63f437d25c4344c76014326dbf0cbdb0) --- source3/lib/dbwrap/dbwrap_ctdb.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c index af7a72f..3dc86d1 100644 --- a/source3/lib/dbwrap/dbwrap_ctdb.c +++ b/source3/lib/dbwrap/dbwrap_ctdb.c @@ -1578,6 +1578,27 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx, return NULL; } +#ifdef HAVE_CTDB_WANT_READONLY_DECL + if (!result->persistent && + (dbwrap_flags & DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS)) + { + TDB_DATA indata; + + indata = make_tdb_data((uint8_t *)&db_ctdb->db_id, + sizeof(db_ctdb->db_id)); + + status = ctdbd_control_local( + conn, CTDB_CONTROL_SET_DB_READONLY, 0, 0, indata, + NULL, NULL, &cstatus); + if (!NT_STATUS_IS_OK(status) || (cstatus != 0)) { + DEBUG(1, ("CTDB_CONTROL_SET_DB_READONLY failed: " + "%s, %d\n", nt_errstr(status), cstatus)); + TALLOC_FREE(result); + return NULL; + } + } +#endif + lp_ctx = loadparm_init_s3(db_path, loadparm_s3_helpers()); db_ctdb->wtdb = tdb_wrap_open(db_ctdb, db_path, hash_size, tdb_flags, -- 1.9.3 From d1ea222d46a594d45422eacccbd655d7e488792a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 28 Jan 2014 21:31:17 +0100 Subject: [PATCH 239/249] dbwrap_open: add 'dbwrap_optimize_readonly:* = yes' option Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit a20c977c7a58a0c09d01bfa046c00fcd3f1462de) --- source3/lib/dbwrap/dbwrap_open.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/source3/lib/dbwrap/dbwrap_open.c b/source3/lib/dbwrap/dbwrap_open.c index 61324f7..7f3cddf 100644 --- a/source3/lib/dbwrap/dbwrap_open.c +++ b/source3/lib/dbwrap/dbwrap_open.c @@ -81,6 +81,31 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx, return NULL; } + if (tdb_flags & TDB_CLEAR_IF_FIRST) { + const char *base; + bool try_readonly = false; + + base = strrchr_m(name, '/'); + if (base != NULL) { + base += 1; + } else { + base = name; + } + + if (dbwrap_flags & DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS) { + try_readonly = true; + } + + try_readonly = lp_parm_bool(-1, "dbwrap_optimize_readonly", "*", try_readonly); + try_readonly = lp_parm_bool(-1, "dbwrap_optimize_readonly", base, try_readonly); + + if (try_readonly) { + dbwrap_flags |= DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS; + } else { + dbwrap_flags &= ~DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS; + } + } + #ifdef CLUSTER_SUPPORT sockname = lp_ctdbd_socket(); -- 1.9.3 From ce06399f9fab90623a2166d69f1bbfc46f124d73 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 27 Jan 2014 16:21:14 +0100 Subject: [PATCH 240/249] s3:rpc_client: optimize the netlogon_creds_cli.tdb for read-only access Usually a record in this DB will be written once and then read many times by winbindd processes on multiple nodes (when run in a cluster). In order not to introduce a big performance penalty with the increased correctness achieved by storing the netlogon creds, in a cluster setup, we should activate ctdb's read only record copies on this db. Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher (cherry picked from commit 020fab300d2f4f19301eff19ad810c71f77bbb78) --- source3/rpc_client/cli_netlogon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 9e3c1bd..746c7b6 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -70,7 +70,7 @@ NTSTATUS rpccli_pre_open_netlogon_creds(void) global_db = db_open(talloc_autofree_context(), fname, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_2, - DBWRAP_FLAG_NONE); + DBWRAP_FLAG_OPTIMIZE_READONLY_ACCESS); if (global_db == NULL) { TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; -- 1.9.3 From e39b8c0e22e609db117285d47cdbd1d854fe8d02 Mon Sep 17 00:00:00 2001 From: Ira Cooper Date: Thu, 13 Feb 2014 14:45:23 -0500 Subject: [PATCH 241/249] libcli: Overflow array index read possible, in auth code. Changed the if condtion to detect when we'd improperly overflow. Coverity-Id: 1167990 Signed-off-by: Ira Cooper Reviewed-by: Stefan Metzmacher Autobuild-User(master): Ira Cooper Autobuild-Date(master): Mon Feb 24 11:56:38 CET 2014 on sn-devel-104 (cherry picked from commit 8cd8aa6686c21e8c43a6d14c0ae1a21954d6e8cd) --- libcli/auth/netlogon_creds_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 88893ad..e3cf91c 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -1769,7 +1769,7 @@ struct tevent_req *netlogon_creds_cli_ServerPasswordSet_send(TALLOC_CTX *mem_ctx uint32_t ofs = 512 - len; uint8_t *p; - if (ofs < 12) { + if (len > 500) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX); return tevent_req_post(req, ev); } -- 1.9.3 From 4e15aa86c44e906ca30cfa4589e4f45f23625953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 15 Jul 2014 08:28:42 +0200 Subject: [PATCH 242/249] s3-rpc_client: return info3 in rpccli_netlogon_password_logon(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Andreas Schneider --- source3/rpc_client/cli_netlogon.c | 103 +++++++++++++++++++++----------------- source3/rpc_client/cli_netlogon.h | 4 +- source3/rpcclient/cmd_netlogon.c | 5 +- 3 files changed, 64 insertions(+), 48 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 746c7b6..7063351 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -193,16 +193,65 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, return NT_STATUS_OK; } +static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, + uint16_t validation_level, + union netr_Validation *validation, + struct netr_SamInfo3 **info3_p) +{ + struct netr_SamInfo3 *info3; + NTSTATUS status; + + if (validation == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + switch (validation_level) { + case 3: + if (validation->sam3 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + info3 = talloc_move(mem_ctx, &validation->sam3); + break; + case 6: + if (validation->sam6 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); + if (info3 == NULL) { + return NT_STATUS_NO_MEMORY; + } + status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(info3); + return status; + } + + info3->sidcount = validation->sam6->sidcount; + info3->sids = talloc_move(info3, &validation->sam6->sids); + break; + default: + return NT_STATUS_BAD_VALIDATION_CLASS; + } + + *info3_p = info3; + + return NT_STATUS_OK; +} + /* Logon domain user */ NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, struct dcerpc_binding_handle *binding_handle, + TALLOC_CTX *mem_ctx, uint32_t logon_parameters, const char *domain, const char *username, const char *password, const char *workstation, - enum netr_LogonInfoClass logon_type) + enum netr_LogonInfoClass logon_type, + struct netr_SamInfo3 **info3) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; @@ -320,57 +369,19 @@ NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds &validation, &authoritative, &flags); - TALLOC_FREE(frame); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); return status; } - return NT_STATUS_OK; -} - -static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, - uint16_t validation_level, - union netr_Validation *validation, - struct netr_SamInfo3 **info3_p) -{ - struct netr_SamInfo3 *info3; - NTSTATUS status; - - if (validation == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - switch (validation_level) { - case 3: - if (validation->sam3 == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - info3 = talloc_move(mem_ctx, &validation->sam3); - break; - case 6: - if (validation->sam6 == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); - if (info3 == NULL) { - return NT_STATUS_NO_MEMORY; - } - status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(info3); - return status; - } - - info3->sidcount = validation->sam6->sidcount; - info3->sids = talloc_move(info3, &validation->sam6->sids); - break; - default: - return NT_STATUS_BAD_VALIDATION_CLASS; + status = map_validation_to_info3(mem_ctx, + validation_level, validation, + info3); + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + return status; } - *info3_p = info3; return NT_STATUS_OK; } diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index 61fed4a..fee0801 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -45,12 +45,14 @@ NTSTATUS rpccli_setup_netlogon_creds(struct cli_state *cli, const struct samr_Password *previous_nt_hash); NTSTATUS rpccli_netlogon_password_logon(struct netlogon_creds_cli_context *creds, struct dcerpc_binding_handle *binding_handle, + TALLOC_CTX *mem_ctx, uint32_t logon_parameters, const char *domain, const char *username, const char *password, const char *workstation, - enum netr_LogonInfoClass logon_type); + enum netr_LogonInfoClass logon_type, + struct netr_SamInfo3 **info3); NTSTATUS rpccli_netlogon_network_logon(struct netlogon_creds_cli_context *creds, struct dcerpc_binding_handle *binding_handle, TALLOC_CTX *mem_ctx, diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index b637b3e..2d1c351 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -778,6 +778,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, const char *username, *password; uint32 logon_param = 0; const char *workstation = NULL; + struct netr_SamInfo3 *info3 = NULL; /* Check arguments */ @@ -803,12 +804,14 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, result = rpccli_netlogon_password_logon(rpcclient_netlogon_creds, cli->binding_handle, + mem_ctx, logon_param, lp_workgroup(), username, password, workstation, - logon_type); + logon_type, + &info3); if (!NT_STATUS_IS_OK(result)) goto done; -- 1.9.3 From 3459fada96951a57a787944aedc01caabe873c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 15 Jul 2014 08:29:55 +0200 Subject: [PATCH 243/249] s3-winbindd: call interactive samlogon via rpccli_netlogon_password_logon. Guenther Signed-off-by: Guenther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Andreas Schneider Conflicts: source3/winbindd/winbindd_pam.c --- source3/winbindd/winbindd_pam.c | 45 +++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 3f3ec70..2a1b74a 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1214,11 +1214,13 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, uint32_t logon_parameters, const char *server, const char *username, + const char *password, const char *domainname, const char *workstation, const uint8_t chal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, + bool interactive, struct netr_SamInfo3 **info3) { int attempts = 0; @@ -1278,19 +1280,32 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, } netr_attempts = 0; - result = rpccli_netlogon_network_logon(domain->conn.netlogon_creds, - netlogon_pipe->binding_handle, - mem_ctx, - logon_parameters, - username, - domainname, - workstation, - chal, - lm_response, - nt_response, - &authoritative, - &flags, - info3); + if (interactive && username != NULL && password != NULL) { + result = rpccli_netlogon_password_logon(domain->conn.netlogon_creds, + netlogon_pipe->binding_handle, + mem_ctx, + logon_parameters, + domainname, + username, + password, + workstation, + NetlogonInteractiveInformation, + info3); + } else { + result = rpccli_netlogon_network_logon(domain->conn.netlogon_creds, + netlogon_pipe->binding_handle, + mem_ctx, + logon_parameters, + username, + domainname, + workstation, + chal, + lm_response, + nt_response, + &authoritative, + &flags, + info3); + } /* * we increment this after the "feature negotiation" @@ -1433,11 +1448,13 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx, 0, domain->dcname, name_user, + pass, name_domain, lp_netbios_name(), chal, lm_resp, nt_resp, + true, /* interactive */ &my_info3); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -1856,12 +1873,14 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request->data.auth_crap.logon_parameters, domain->dcname, name_user, + NULL, /* password */ name_domain, /* Bug #3248 - found by Stefan Burkei. */ workstation, /* We carefully set this above so use it... */ state->request->data.auth_crap.chal, lm_resp, nt_resp, + false, /* interactive */ &info3); if (!NT_STATUS_IS_OK(result)) { goto done; -- 1.9.3 From ad27b750ea3766581e528a41c132bb57927cc64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Mon, 7 Jul 2014 17:14:37 +0200 Subject: [PATCH 244/249] s3-winbindd: add wcache_query_user_fullname(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helper function is used to query the full name of a cached user object (for further gecos processing). Thanks to Matt Rogers . BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Guenther Pair-Programmed-With: Andreas Schneider Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd_cache.c | 34 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 4 ++++ 2 files changed, 38 insertions(+) diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 59ce515..d1e10e6c 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2309,6 +2309,40 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain, return status; } + +/** +* @brief Query a fullname from the username cache (for further gecos processing) +* +* @param domain A pointer to the winbindd_domain struct. +* @param mem_ctx The talloc context. +* @param user_sid The user sid. +* @param full_name A pointer to the full_name string. +* +* @return NTSTATUS code +*/ +NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *user_sid, + const char **full_name) +{ + NTSTATUS status; + struct wbint_userinfo info; + + status = wcache_query_user(domain, mem_ctx, user_sid, &info); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (info.full_name != NULL) { + *full_name = talloc_strdup(mem_ctx, info.full_name); + if (*full_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + + return NT_STATUS_OK; +} + /* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index cfc19d0..cfb7812 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -105,6 +105,10 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid, struct wbint_userinfo *info); +NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *user_sid, + const char **full_name); NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 num_sids, const struct dom_sid *sids, -- 1.9.3 From e89ca0b90887930a2f86dcaa4f6d3d05565f919c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Mon, 7 Jul 2014 17:16:32 +0200 Subject: [PATCH 245/249] s3-winbindd: use wcache_query_user_fullname after inspecting samlogon cache. The reason for this followup query is that very often the samlogon cache only contains a info3 netlogon user structure that has been retrieved during a netlogon samlogon authentication using "network" logon level. With that logon level only a few info3 fields are filled in; the user's fullname is never filled in that case. This is problematic when the cache is used to fill in the user's gecos field (for NSS queries). When we have retrieved the user's fullname during other queries, reuse it from the other caches. Thanks to Matt Rogers . BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Guenther Pair-Programmed-With: Andreas Schneider Signed-off-by: Guenther Deschner Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd_ads.c | 8 ++++++++ source3/winbindd/winbindd_msrpc.c | 8 ++++++++ source3/winbindd/winbindd_pam.c | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 4c26389..a20fba5 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -619,6 +619,14 @@ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_FREE(user); + if (info->full_name == NULL) { + /* this might fail so we dont check the return code */ + wcache_query_user_fullname(domain, + mem_ctx, + sid, + &info->full_name); + } + return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c index 426d64c..c097bf3 100644 --- a/source3/winbindd/winbindd_msrpc.c +++ b/source3/winbindd/winbindd_msrpc.c @@ -439,6 +439,14 @@ static NTSTATUS msrpc_query_user(struct winbindd_domain *domain, user_info->full_name = talloc_strdup(user_info, user->base.full_name.string); + if (user_info->full_name == NULL) { + /* this might fail so we dont check the return code */ + wcache_query_user_fullname(domain, + mem_ctx, + user_sid, + &user_info->full_name); + } + status = NT_STATUS_OK; goto done; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 2a1b74a..bf71d97 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1720,6 +1720,26 @@ process_result: sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); + if (info3->base.full_name.string == NULL) { + struct netr_SamInfo3 *cached_info3; + + cached_info3 = netsamlogon_cache_get(state->mem_ctx, + &user_sid); + if (cached_info3 != NULL && + cached_info3->base.full_name.string != NULL) { + info3->base.full_name.string = + talloc_strdup(info3, + cached_info3->base.full_name.string); + } else { + + /* this might fail so we dont check the return code */ + wcache_query_user_fullname(domain, + info3, + &user_sid, + &info3->base.full_name.string); + } + } + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &user_sid); netsamlogon_cache_store(name_user, info3); -- 1.9.3 From aa042d490b2cccb7b6cc394e024004321a6c156c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 9 Jul 2014 13:36:06 +0200 Subject: [PATCH 246/249] samlogon_cache: use a talloc_stackframe inside netsamlogon_cache_store. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider --- source3/libsmb/samlogon_cache.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index b04cf0a..f7457ae 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -125,7 +125,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) bool result = false; struct dom_sid user_sid; time_t t = time(NULL); - TALLOC_CTX *mem_ctx; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); DATA_BLOB blob; enum ndr_err_code ndr_err; struct netsamlogoncache_entry r; @@ -149,11 +149,6 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) /* Prepare data */ - if (!(mem_ctx = talloc( NULL, int))) { - DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n")); - return false; - } - /* only Samba fills in the username, not sure why NT doesn't */ /* so we fill it in since winbindd_getpwnam() makes use of it */ @@ -168,11 +163,11 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); } - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r, + ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, &r, (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n")); - TALLOC_FREE(mem_ctx); + TALLOC_FREE(tmp_ctx); return false; } @@ -183,7 +178,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) result = true; } - TALLOC_FREE(mem_ctx); + TALLOC_FREE(tmp_ctx); return result; } -- 1.9.3 From 8283d1acec0c0afd17197339a4986975d05abf29 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 3 Jul 2014 16:17:46 +0200 Subject: [PATCH 247/249] samlogon_cache: avoid overwriting info3->base.full_name.string. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This field servers as a source for the gecos field. We should not overwrite it when a info3 struct from a samlogon network level gets saved in which case this field is always NULL. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Signed-off-by: Andreas Schneider Reviewed-by: Guenther Deschner Autobuild-User(master): Günther Deschner Autobuild-Date(master): Tue Jul 15 18:25:28 CEST 2014 on sn-devel-104 --- source3/libsmb/samlogon_cache.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index f7457ae..0a157d4 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -149,6 +149,20 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) /* Prepare data */ + if (info3->base.full_name.string == NULL) { + struct netr_SamInfo3 *cached_info3; + const char *full_name = NULL; + + cached_info3 = netsamlogon_cache_get(tmp_ctx, &user_sid); + if (cached_info3 != NULL) { + full_name = cached_info3->base.full_name.string; + } + + if (full_name != NULL) { + info3->base.full_name.string = talloc_strdup(info3, full_name); + } + } + /* only Samba fills in the username, not sure why NT doesn't */ /* so we fill it in since winbindd_getpwnam() makes use of it */ -- 1.9.3 From fe9d7458001a952d1df23dcd584a1835df5d43d1 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 3 Jul 2014 16:19:42 +0200 Subject: [PATCH 248/249] s3-winbind: Don't set the gecos field to NULL. The value is loaded from the cache anyway. So it will be set to NULL if it is not available. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Signed-off-by: Andreas Schneider Reviewed-by: Guenther Deschner --- source3/winbindd/nss_info_template.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source3/winbindd/nss_info_template.c b/source3/winbindd/nss_info_template.c index 5fdfd9b..de93803 100644 --- a/source3/winbindd/nss_info_template.c +++ b/source3/winbindd/nss_info_template.c @@ -48,7 +48,6 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, username */ *homedir = talloc_strdup( ctx, lp_template_homedir() ); *shell = talloc_strdup( ctx, lp_template_shell() ); - *gecos = NULL; if ( !*homedir || !*shell ) { return NT_STATUS_NO_MEMORY; -- 1.9.3 From d2f3347a264bb7b8b0335404348990f52320b672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Mon, 14 Jul 2014 18:22:26 +0200 Subject: [PATCH 249/249] s3-winbindd: prefer "displayName" over "name" in ads user queries for the fullname. This makes use more consistent with security=domain as well where the gecos field is also filled using the displayName field. Guenther Signed-off-by: Guenther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd_ads.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index a20fba5..4b5b2fa 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -327,7 +327,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, } info->acct_name = ads_pull_username(ads, mem_ctx, msg); - info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); + info->full_name = ads_pull_string(ads, mem_ctx, msg, "displayName"); + if (info->full_name == NULL) { + info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); + } info->homedir = NULL; info->shell = NULL; info->primary_gid = (gid_t)-1; @@ -592,7 +595,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, struct netr_SamInfo3 *user = NULL; gid_t gid = -1; int ret; - char *ads_name; + char *full_name; DEBUG(3,("ads: query_user\n")); @@ -704,7 +707,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain, * nss_get_info_cached call. nss_get_info_cached might destroy * the ads struct, potentially invalidating the ldap message. */ - ads_name = ads_pull_string(ads, mem_ctx, msg, "name"); + full_name = ads_pull_string(ads, mem_ctx, msg, "displayName"); + if (full_name == NULL) { + full_name = ads_pull_string(ads, mem_ctx, msg, "name"); + } ads_msgfree(ads, msg); msg = NULL; @@ -720,9 +726,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain, } if (info->full_name == NULL) { - info->full_name = ads_name; + info->full_name = full_name; } else { - TALLOC_FREE(ads_name); + TALLOC_FREE(full_name); } status = NT_STATUS_OK; -- 1.9.3