The branch, v3-6-test has been updated via 7add712 s3-winbindd: let winbind try to use samlogon validation level 6. (bug #7945) via 0a1d8c2 s3-auth: add copy_netr_SamBaseInfo(). via 3eb4f82 s3:lib/addrchange: set ctx->sock to -1 after close via cc62408 s3:lib/addrchange: remove unused pointer via b53b401 s3:lib/addrchange: let addrchange_done() retry and ignore unknown message types via 060ee24 s3:winbindd: fix segfaults on addrchange errors and make DEBUG() statements more usefull from 7ebb874 s3:rpc_server/netlogon: reject validation level 6 without ads support
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test - Log ----------------------------------------------------------------- commit 7add712498fe93603b1bffff2c633e097ce8fbdf Author: Günther Deschner <g...@samba.org> Date: Fri Jan 7 17:28:29 2011 +0100 s3-winbindd: let winbind try to use samlogon validation level 6. (bug #7945) The benefit of this that it makes us more robust to secure channel resets triggered from tools outside the winbind process. Long term we need to have a shared tdb secure channel store though as well. Guenther Signed-off-by: Stefan Metzmacher <me...@samba.org> Autobuild-User: Stefan Metzmacher <me...@samba.org> Autobuild-Date: Fri Feb 4 18:11:04 CET 2011 on sn-devel-104 (cherry picked from commit f60398d7b20869d7b09d81854f3727fdcd897430) commit 0a1d8c2b2218bdc77938ab0f33aa4431e6aae3ea Author: Günther Deschner <g...@samba.org> Date: Tue Jan 11 15:08:41 2011 +0100 s3-auth: add copy_netr_SamBaseInfo(). Guenther Signed-off-by: Stefan Metzmacher <me...@samba.org> (cherry picked from commit ac4127a9f432f762cb728c161d7fbf80de31b60e) commit 3eb4f829cca3299cec22f54d3e4906ca71f10994 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 4 12:54:36 2011 +0100 s3:lib/addrchange: set ctx->sock to -1 after close The makes the code more consistent with similar destructors. metze Autobuild-User: Stefan Metzmacher <me...@samba.org> Autobuild-Date: Fri Feb 4 15:52:55 CET 2011 on sn-devel-104 (cherry picked from commit e9c45a3973c85fbe40c017724c7909fefa05b656) commit cc62408ba58b1f8c4a18a2d565c692203cb124b3 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 4 12:53:38 2011 +0100 s3:lib/addrchange: remove unused pointer metze (cherry picked from commit d8d5a3fb3a7754a71ba78399ab0fdcd8b3854dfa) commit b53b40157cc9ea390b30cdf07085d85f721dcf28 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 4 12:32:41 2011 +0100 s3:lib/addrchange: let addrchange_done() retry and ignore unknown message types Messages like RTM_NEWLINK should be just ignored. metze (cherry picked from commit ff935ddf8b22be269abb730904d324efb1e3e8f2) commit 060ee243e758db4281a0ce10e959a67dd2d13494 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 4 12:29:42 2011 +0100 s3:winbindd: fix segfaults on addrchange errors and make DEBUG() statements more usefull metze (cherry picked from commit 902fbd91a19c414b61bc18ef24d7d84b30d37b1b) ----------------------------------------------------------------------- Summary of changes: source3/Makefile.in | 3 +- source3/auth/auth_domain.c | 1 + source3/auth/auth_netlogond.c | 1 + source3/auth/server_info.c | 62 +++-------------------------------- source3/lib/addrchange.c | 24 ++++++++++---- source3/rpc_client/cli_netlogon.c | 62 +++++++++++++++++++++++++++++++++-- source3/rpc_client/cli_netlogon.h | 2 + source3/rpc_client/util_netlogon.c | 63 ++++++++++++++++++++++++++++++++++++ source3/rpc_client/util_netlogon.h | 5 +++ source3/winbindd/winbindd.c | 9 +++-- source3/winbindd/winbindd.h | 1 + source3/winbindd/winbindd_cm.c | 1 + source3/winbindd/winbindd_pam.c | 59 ++++++++++++++++++++++++++++++++- source3/wscript_build | 2 +- 14 files changed, 221 insertions(+), 74 deletions(-) create mode 100644 source3/rpc_client/util_netlogon.c create mode 100644 source3/rpc_client/util_netlogon.h Changeset truncated at 500 lines: diff --git a/source3/Makefile.in b/source3/Makefile.in index 09cd713..ebfee9f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -375,7 +375,8 @@ LIBCLI_SAMR_OBJ = librpc/gen_ndr/ndr_samr_c.o \ rpc_client/cli_samr.o LIBCLI_NETLOGON_OBJ = librpc/gen_ndr/ndr_netlogon_c.o \ - rpc_client/cli_netlogon.o + rpc_client/cli_netlogon.o \ + rpc_client/util_netlogon.o LIBCLI_EPMAPPER_OBJ = librpc/gen_ndr/ndr_epmapper_c.o diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 0f541cd..05421de 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -309,6 +309,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, 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 */ diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c index 889371c..1e3ccb1 100644 --- a/source3/auth/auth_netlogond.c +++ b/source3/auth/auth_netlogond.c @@ -88,6 +88,7 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx, user_info->client.domain_name, /* domain name */ user_info->workstation_name, /* workstation name */ (uchar *)auth_context->challenge.data, /* 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 */ diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c index 01c7a96..0f62983 100644 --- a/source3/auth/server_info.c +++ b/source3/auth/server_info.c @@ -21,6 +21,7 @@ #include "../lib/crypto/arcfour.h" #include "../librpc/gen_ndr/netlogon.h" #include "../libcli/security/security.h" +#include "rpc_client/util_netlogon.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -490,66 +491,15 @@ struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, { struct netr_SamInfo3 *info3; unsigned int i; + NTSTATUS status; info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); if (!info3) return NULL; - /* first copy all, then realloc pointers */ - info3->base = orig->base; - - if (orig->base.account_name.string) { - info3->base.account_name.string = - talloc_strdup(info3, orig->base.account_name.string); - RET_NOMEM(info3->base.account_name.string); - } - if (orig->base.full_name.string) { - info3->base.full_name.string = - talloc_strdup(info3, orig->base.full_name.string); - RET_NOMEM(info3->base.full_name.string); - } - if (orig->base.logon_script.string) { - info3->base.logon_script.string = - talloc_strdup(info3, orig->base.logon_script.string); - RET_NOMEM(info3->base.logon_script.string); - } - if (orig->base.profile_path.string) { - info3->base.profile_path.string = - talloc_strdup(info3, orig->base.profile_path.string); - RET_NOMEM(info3->base.profile_path.string); - } - if (orig->base.home_directory.string) { - info3->base.home_directory.string = - talloc_strdup(info3, orig->base.home_directory.string); - RET_NOMEM(info3->base.home_directory.string); - } - if (orig->base.home_drive.string) { - info3->base.home_drive.string = - talloc_strdup(info3, orig->base.home_drive.string); - RET_NOMEM(info3->base.home_drive.string); - } - - if (orig->base.groups.count) { - info3->base.groups.rids = (struct samr_RidWithAttribute *) - talloc_memdup(info3, orig->base.groups.rids, - (sizeof(struct samr_RidWithAttribute) * - orig->base.groups.count)); - RET_NOMEM(info3->base.groups.rids); - } - - if (orig->base.logon_server.string) { - info3->base.logon_server.string = - talloc_strdup(info3, orig->base.logon_server.string); - RET_NOMEM(info3->base.logon_server.string); - } - if (orig->base.domain.string) { - info3->base.domain.string = - talloc_strdup(info3, orig->base.domain.string); - RET_NOMEM(info3->base.domain.string); - } - - if (orig->base.domain_sid) { - info3->base.domain_sid = dom_sid_dup(info3, orig->base.domain_sid); - RET_NOMEM(info3->base.domain_sid); + status = copy_netr_SamBaseInfo(info3, &orig->base, &info3->base); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(info3); + return NULL; } if (orig->sidcount) { diff --git a/source3/lib/addrchange.c b/source3/lib/addrchange.c index f3606e2..8cd3c19 100644 --- a/source3/lib/addrchange.c +++ b/source3/lib/addrchange.c @@ -28,7 +28,6 @@ struct addrchange_context { int sock; - uint8_t *buf; }; static int addrchange_context_destructor(struct addrchange_context *c); @@ -77,12 +76,14 @@ static int addrchange_context_destructor(struct addrchange_context *c) { if (c->sock != -1) { close(c->sock); - c->sock = 0; + c->sock = -1; } return 0; } struct addrchange_state { + struct tevent_context *ev; + struct addrchange_context *ctx; uint8_t buf[8192]; struct sockaddr_storage fromaddr; socklen_t fromaddr_len; @@ -104,14 +105,15 @@ struct tevent_req *addrchange_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + state->ev = ev; + state->ctx = ctx; state->fromaddr_len = sizeof(state->fromaddr); - - subreq = recvfrom_send(state, ev, ctx->sock, + subreq = recvfrom_send(state, state->ev, state->ctx->sock, state->buf, sizeof(state->buf), 0, &state->fromaddr, &state->fromaddr_len); if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); + return tevent_req_post(req, state->ev); } tevent_req_set_callback(subreq, addrchange_done, req); return req; @@ -166,8 +168,16 @@ static void addrchange_done(struct tevent_req *subreq) state->type = ADDRCHANGE_DEL; break; default: - DEBUG(10, ("Got unexpected type %d\n", h->nlmsg_type)); - tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS); + DEBUG(10, ("Got unexpected type %d - ignoring\n", h->nlmsg_type)); + + state->fromaddr_len = sizeof(state->fromaddr); + subreq = recvfrom_send(state, state->ev, state->ctx->sock, + state->buf, sizeof(state->buf), 0, + &state->fromaddr, &state->fromaddr_len); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, addrchange_done, req); return; } diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 914bfd3..f34d794 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -25,6 +25,8 @@ #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" /**************************************************************************** Wrapper function that uses the auth and auth2 calls to set up a NETLOGON @@ -298,6 +300,52 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, return result; } +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 with an 'network' SAM logon @@ -313,13 +361,13 @@ 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, DATA_BLOB lm_response, DATA_BLOB nt_response, struct netr_SamInfo3 **info3) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; NTSTATUS status; - int validation_level = 3; const char *workstation_name_slash; const char *server_name_slash; struct netr_Authenticator clnt_creds; @@ -417,7 +465,10 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation); - *info3 = validation.sam3; + result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); + if (!NT_STATUS_IS_OK(result)) { + return result; + } return result; } @@ -430,13 +481,13 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, 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 result = NT_STATUS_UNSUCCESSFUL; NTSTATUS status; - int validation_level = 3; const char *workstation_name_slash; const char *server_name_slash; union netr_LogonLevel *logon = NULL; @@ -522,7 +573,10 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation); - *info3 = validation.sam3; + result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); + if (!NT_STATUS_IS_OK(result)) { + return result; + } return result; } diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index bb38b75..808a428 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -25,6 +25,7 @@ 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, DATA_BLOB lm_response, DATA_BLOB nt_response, struct netr_SamInfo3 **info3); @@ -36,6 +37,7 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, 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); diff --git a/source3/rpc_client/util_netlogon.c b/source3/rpc_client/util_netlogon.c new file mode 100644 index 0000000..558a4da --- /dev/null +++ b/source3/rpc_client/util_netlogon.c @@ -0,0 +1,63 @@ +/* + Unix SMB/CIFS implementation. + Authentication utility functions + Copyright (C) Volker Lendecke 2010 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "../librpc/gen_ndr/netlogon.h" +#include "../libcli/security/security.h" +#include "rpc_client/util_netlogon.h" + +#define COPY_LSA_STRING(mem_ctx, in, out, name) do { \ + if (in->name.string) { \ + out->name.string = talloc_strdup(mem_ctx, in->name.string); \ + NT_STATUS_HAVE_NO_MEMORY(out->name.string); \ + } \ +} while (0) + +NTSTATUS copy_netr_SamBaseInfo(TALLOC_CTX *mem_ctx, + const struct netr_SamBaseInfo *in, + struct netr_SamBaseInfo *out) +{ + /* first copy all, then realloc pointers */ + *out = *in; + + COPY_LSA_STRING(mem_ctx, in, out, account_name); + COPY_LSA_STRING(mem_ctx, in, out, full_name); + COPY_LSA_STRING(mem_ctx, in, out, logon_script); + COPY_LSA_STRING(mem_ctx, in, out, profile_path); + COPY_LSA_STRING(mem_ctx, in, out, home_directory); + COPY_LSA_STRING(mem_ctx, in, out, home_drive); + + if (in->groups.count) { + out->groups.rids = (struct samr_RidWithAttribute *) + talloc_memdup(mem_ctx, in->groups.rids, + (sizeof(struct samr_RidWithAttribute) * + in->groups.count)); + NT_STATUS_HAVE_NO_MEMORY(out->groups.rids); + } + + COPY_LSA_STRING(mem_ctx, in, out, logon_server); + COPY_LSA_STRING(mem_ctx, in, out, domain); + + if (in->domain_sid) { + out->domain_sid = dom_sid_dup(mem_ctx, in->domain_sid); + NT_STATUS_HAVE_NO_MEMORY(out->domain_sid); + } + + return NT_STATUS_OK; +} diff --git a/source3/rpc_client/util_netlogon.h b/source3/rpc_client/util_netlogon.h new file mode 100644 index 0000000..42e4326 --- /dev/null +++ b/source3/rpc_client/util_netlogon.h @@ -0,0 +1,5 @@ +/* The following definitions come from rpc_client/util_netlogon.c */ + +NTSTATUS copy_netr_SamBaseInfo(TALLOC_CTX *mem_ctx, + const struct netr_SamBaseInfo *in, + struct netr_SamBaseInfo *out); diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 701f7a0..3a76231 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1142,8 +1142,9 @@ static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx, } req = addrchange_send(state, ev, state->ctx); if (req == NULL) { - DEBUG(10, ("addrchange_send failed\n")); + DEBUG(0, ("addrchange_send failed\n")); TALLOC_FREE(state); + return; } tevent_req_set_callback(req, winbindd_addr_changed, state); } @@ -1162,6 +1163,7 @@ static void winbindd_addr_changed(struct tevent_req *req) DEBUG(10, ("addrchange_recv failed: %s, stop listening\n", nt_errstr(status))); TALLOC_FREE(state); + return; } if (type == ADDRCHANGE_DEL) { char addrstr[INET6_ADDRSTRLEN]; @@ -1178,14 +1180,15 @@ static void winbindd_addr_changed(struct tevent_req *req) messaging_server_id(state->msg_ctx), MSG_WINBIND_IP_DROPPED, &blob); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("messaging_send failed: %s\n", + DEBUG(10, ("messaging_send failed: %s - ignoring\n", nt_errstr(status))); } } req = addrchange_send(state, state->ev, state->ctx); if (req == NULL) { - DEBUG(10, ("addrchange_send failed\n")); + DEBUG(0, ("addrchange_send failed\n")); TALLOC_FREE(state); + return; } tevent_req_set_callback(req, winbindd_addr_changed, state); } diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index 3217acc..a32c78f 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -169,6 +169,7 @@ struct winbindd_domain { * 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 c692ffe..c53a553 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2086,6 +2086,7 @@ 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); diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 760fa3b..68fa01f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1148,6 +1148,8 @@ 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; @@ -1159,6 +1161,10 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, nt_errstr(result))); return result; } + 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 @@ -1179,8 +1185,35 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, * wrapping SamLogon context. * -- Samba Shared Repository