diff options
author | Gerald Carter <jerry@samba.org> | 2005-09-30 17:13:37 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:04:48 -0500 |
commit | 54abd2aa66069e6baf7769c496f46d9dba18db39 (patch) | |
tree | 9cf8e88168011797319ba9e9866749201b1eac1e /source3/nsswitch | |
parent | 4a2cc231d22a82ed21771a72508f15d21ed63227 (diff) | |
download | samba-54abd2aa66069e6baf7769c496f46d9dba18db39.tar.gz samba-54abd2aa66069e6baf7769c496f46d9dba18db39.tar.bz2 samba-54abd2aa66069e6baf7769c496f46d9dba18db39.zip |
r10656: BIG merge from trunk. Features not copied over
* \PIPE\unixinfo
* winbindd's {group,alias}membership new functions
* winbindd's lookupsids() functionality
* swat (trunk changes to be reverted as per discussion with Deryck)
(This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3)
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/wb_common.c | 5 | ||||
-rw-r--r-- | source3/nsswitch/wbinfo.c | 1 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.c | 67 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.h | 16 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_ads.c | 11 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_async.c | 97 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 86 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 513 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_dual.c | 151 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 23 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_misc.c | 30 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_nss.h | 8 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 172 |
13 files changed, 658 insertions, 522 deletions
diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index 6d09666525..5521614965 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -543,6 +543,11 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) if (write_sock(request, sizeof(*request), request->flags & WBFLAG_RECURSE) == -1) { return NSS_STATUS_UNAVAIL; } + + if ((request->extra_len != 0) && + (write_sock(request->extra_data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) { + return NSS_STATUS_UNAVAIL; + } return NSS_STATUS_SUCCESS; } diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 34b2d6c929..60f1d6b722 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -192,7 +192,6 @@ static BOOL wbinfo_get_userdomgroups(const char *user_sid) return True; } - /* Convert NetBIOS name to IP */ static BOOL wbinfo_wins_byname(char *name) diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index dffaad5ef0..565764fa4b 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -204,7 +204,7 @@ static void sigchld_handler(int signum) } /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ -static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len) +static void msg_reload_services(int msg_type, struct process_id src, void *buf, size_t len) { /* Flush various caches */ flush_caches(); @@ -212,7 +212,7 @@ static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len) } /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ -static void msg_shutdown(int msg_type, pid_t src, void *buf, size_t len) +static void msg_shutdown(int msg_type, struct process_id src, void *buf, size_t len) { terminate(); } @@ -455,6 +455,7 @@ void setup_async_write(struct fd_event *event, void *data, size_t length, static void request_len_recv(void *private_data, BOOL success); static void request_recv(void *private_data, BOOL success); +static void request_main_recv(void *private_data, BOOL success); static void request_finished(struct winbindd_cli_state *state); void request_finished_cont(void *private_data, BOOL success); static void response_main_sent(void *private_data, BOOL success); @@ -475,6 +476,7 @@ static void response_extra_sent(void *private_data, BOOL success) return; } + SAFE_FREE(state->request.extra_data); SAFE_FREE(state->response.extra_data); setup_async_read(&state->fd_event, &state->request, sizeof(uint32), @@ -538,7 +540,7 @@ void request_finished_cont(void *private_data, BOOL success) request_error(state); } -static void request_recv(void *private_data, BOOL success) +static void request_len_recv(void *private_data, BOOL success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -548,10 +550,19 @@ static void request_recv(void *private_data, BOOL success) return; } - process_request(state); + if (*(uint32 *)(&state->request) != sizeof(state->request)) { + DEBUG(0,("request_len_recv: Invalid request size received: %d\n", + *(uint32 *)(&state->request))); + state->finished = True; + return; + } + + setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1, + sizeof(state->request) - sizeof(uint32), + request_main_recv, state); } -static void request_len_recv(void *private_data, BOOL success) +static void request_main_recv(void *private_data, BOOL success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -561,16 +572,48 @@ static void request_len_recv(void *private_data, BOOL success) return; } - if (*(uint32 *)(&state->request) != sizeof(state->request)) { - DEBUG(0,("request_len_recv: Invalid request size received: %d\n", - *(uint32 *)(&state->request))); + if (state->request.extra_len == 0) { + state->request.extra_data = NULL; + request_recv(state, True); + return; + } + + if ((!state->privileged) && + (state->request.extra_len > WINBINDD_MAX_EXTRA_DATA)) { + DEBUG(3, ("Got request with %d bytes extra data on " + "unprivileged socket\n", (int)state->request.extra_len)); + state->request.extra_data = NULL; state->finished = True; return; } - setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1, - sizeof(state->request) - sizeof(uint32), - request_recv, state); + state->request.extra_data = + SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); + + if (state->request.extra_data == NULL) { + DEBUG(0, ("malloc failed\n")); + state->finished = True; + return; + } + + /* Ensure null termination */ + state->request.extra_data[state->request.extra_len] = '\0'; + + setup_async_read(&state->fd_event, state->request.extra_data, + state->request.extra_len, request_recv, state); +} + +static void request_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + state->finished = True; + return; + } + + process_request(state); } /* Process a new connection by adding it to the client connection list */ @@ -842,7 +885,7 @@ static void process_loop(void) DEBUG(3, ("got SIGHUP\n")); - msg_reload_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, NULL, 0); + msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0); do_sighup = False; } diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 3a7728e4a2..0db109dacd 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -47,6 +47,14 @@ struct fd_event { void *private_data; }; +struct sid_ctr { + DOM_SID *sid; + BOOL finished; + const char *domain; + const char *name; + enum SID_NAME_USE type; +}; + struct winbindd_cli_state { struct winbindd_cli_state *prev, *next; /* Linked list pointers */ int sock; /* Open socket from client */ @@ -122,12 +130,6 @@ struct winbindd_cm_conn { struct rpc_pipe_client *lsa_pipe; POLICY_HND lsa_policy; - /* Auth2 pipe is the pipe used to setup the netlogon schannel key - * using rpccli_net_auth2. It needs to be kept open. */ - - struct rpc_pipe_client *netlogon_auth2_pipe; - unsigned char sess_key[16]; /* Current session key. */ - DOM_CRED clnt_cred; /* Client NETLOGON credential. */ struct rpc_pipe_client *netlogon_pipe; }; @@ -305,8 +307,6 @@ struct winbindd_idmap_methods { #include "nsswitch/winbindd_proto.h" -#include "rpc_parse.h" - #define WINBINDD_ESTABLISH_LOOP 30 #define WINBINDD_RESCAN_FREQ 300 diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index eda6dea2c4..dfabccd419 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -830,13 +830,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, *names = NULL; *dom_sids = NULL; - { - unsigned char *session_key; - DOM_CRED *creds; - - result = cm_connect_netlogon(domain, mem_ctx, &cli, - &session_key, &creds); - } + result = cm_connect_netlogon(domain, &cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(5, ("trusted_domains: Could not open a connection to %s " @@ -845,11 +839,12 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, return NT_STATUS_UNSUCCESSFUL; } - if ( NT_STATUS_IS_OK(result) ) + if ( NT_STATUS_IS_OK(result) ) { result = rpccli_ds_enum_domain_trusts(cli, mem_ctx, cli->cli->desthost, flags, &domains, (unsigned int *)&count); + } if ( NT_STATUS_IS_OK(result) && count) { diff --git a/source3/nsswitch/winbindd_async.c b/source3/nsswitch/winbindd_async.c index acae7e7f37..d43671380d 100644 --- a/source3/nsswitch/winbindd_async.c +++ b/source3/nsswitch/winbindd_async.c @@ -84,12 +84,12 @@ static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, &state->response, do_async_recv, state); } -static void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, - const struct winbindd_request *request, - void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data), - void *c, void *private_data) +void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data) { struct do_async_state *state; @@ -706,16 +706,16 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, return WINBINDD_OK; } -static BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, - int num_sids, char **result) +BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, + int num_sids, char **result, ssize_t *len) { int i; size_t buflen = 0; - ssize_t len = 0; + *len = 0; *result = NULL; for (i=0; i<num_sids; i++) { - sprintf_append(mem_ctx, result, &len, &buflen, + sprintf_append(mem_ctx, result, len, &buflen, "%s\n", sid_string_static(&sids[i])); } @@ -726,14 +726,14 @@ static BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, return True; } -static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, - DOM_SID **sids, int *num_sids) +BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, + DOM_SID **sids, int *num_sids) { char *p, *q; p = sidstr; if (p == NULL) - return True; + return False; while (p[0] != '\0') { DOM_SID sid; @@ -754,6 +754,49 @@ static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr, return True; } +BOOL print_ridlist(TALLOC_CTX *mem_ctx, uint32 *rids, int num_rids, + char **result, ssize_t *len) +{ + int i; + size_t buflen = 0; + + *len = 0; + *result = NULL; + for (i=0; i<num_rids; i++) { + sprintf_append(mem_ctx, result, len, &buflen, + "%ld\n", rids[i]); + } + + if ((num_rids != 0) && (*result == NULL)) { + return False; + } + + return True; +} + +BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr, + uint32 **sids, int *num_rids) +{ + char *p; + + p = ridstr; + if (p == NULL) + return False; + + while (p[0] != '\0') { + uint32 rid; + char *q; + rid = strtoul(p, &q, 10); + if (*q != '\n') { + DEBUG(0, ("Got invalid ridstr: %s\n", p)); + return False; + } + p = q+1; + ADD_TO_ARRAY(mem_ctx, uint32, rid, sids, num_rids); + } + return True; +} + static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success, struct winbindd_response *response, void *c, void *private_data) @@ -806,28 +849,22 @@ void winbindd_getsidaliases_async(struct winbindd_domain *domain, { struct winbindd_request request; char *sidstr = NULL; - char *keystr; + ssize_t len; if (num_sids == 0) { cont(private_data, True, NULL, 0); return; } - if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr)) { - cont(private_data, False, NULL, 0); - return; - } - - keystr = cache_store_request_data(mem_ctx, sidstr); - if (keystr == NULL) { + if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) { cont(private_data, False, NULL, 0); return; } ZERO_STRUCT(request); request.cmd = WINBINDD_DUAL_GETSIDALIASES; - fstrcpy(request.domain_name, domain->name); - fstrcpy(request.data.dual_sidaliases.cache_key, keystr); + request.extra_len = len; + request.extra_data = sidstr; do_async_domain(mem_ctx, domain, &request, getsidaliases_recv, cont, private_data); @@ -838,20 +875,15 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, { DOM_SID *sids = NULL; int num_sids = 0; - char *key = state->request.data.dual_sidaliases.cache_key; char *sidstr; + size_t len; int i, num_aliases; uint32 *alias_rids; NTSTATUS result; DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid)); - /* Ensure null termination */ - state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; - state->request.data.dual_sidaliases.cache_key - [sizeof(state->request.data.dual_sidaliases.cache_key)-1]='\0'; - - sidstr = cache_retrieve_request_data(state->mem_ctx, key); + sidstr = state->request.extra_data; if (sidstr == NULL) sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */ @@ -891,7 +923,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, } if (!print_sidlist(NULL, sids, num_sids, - (char **)&state->response.extra_data)) { + (char **)&state->response.extra_data, &len)) { DEBUG(0, ("Could not print_sidlist\n")); return WINBINDD_ERROR; } @@ -899,7 +931,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, if (state->response.extra_data != NULL) { DEBUG(10, ("aliases_list: %s\n", (char *)state->response.extra_data)); - state->response.length += strlen(state->response.extra_data)+1; + state->response.length += len+1; } return WINBINDD_OK; @@ -1405,3 +1437,4 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, do_async_domain(mem_ctx, domain, &request, query_user_recv, cont, private_data); } + diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index ce291a6c25..78b49d01ea 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -469,6 +469,7 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, centry->sequence_number = centry_uint32(centry); if (centry_expired(domain, kstr, centry)) { + DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n", kstr, domain->name )); @@ -1048,7 +1049,6 @@ do_query: return status; } - /* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -1466,7 +1466,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response) /* There's extra data */ DEBUG(10, ("Storing extra data: len=%d\n", - response->length - sizeof(*response))); + (int)(response->length - sizeof(*response)))); fstr_sprintf(key_str, "DE/%d", pid); if (tdb_store(wcache->tdb, string_tdb_data(key_str), @@ -1514,7 +1514,7 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response) /* There's extra data */ DEBUG(10, ("Retrieving extra data length=%d\n", - response->length - sizeof(*response))); + (int)(response->length - sizeof(*response)))); fstr_sprintf(key_str, "DE/%d", pid); data = tdb_fetch(wcache->tdb, string_tdb_data(key_str)); @@ -1525,63 +1525,57 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response) } if (data.dsize != (response->length - sizeof(*response))) { - DEBUG(0, ("Invalid extra data length: %d\n", data.dsize)); + DEBUG(0, ("Invalid extra data length: %d\n", (int)data.dsize)); SAFE_FREE(data.dptr); return False; } + dump_data(11, data.dptr, data.dsize); + response->extra_data = data.dptr; return True; } -char *cache_store_request_data(TALLOC_CTX *mem_ctx, char *request_string) +BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + const char **domain_name, const char **name, + enum SID_NAME_USE *type) { - int i; - - if (!init_wcache()) - return NULL; + struct winbindd_domain *domain; + struct winbind_cache *cache; + struct cache_entry *centry = NULL; + NTSTATUS status; - for (i=0; i<2; i++) { - char *key = talloc_strdup(mem_ctx, generate_random_str(16)); - if (key == NULL) - return NULL; - DEBUG(10, ("Storing request key %s\n", key)); - if (tdb_store_bystring(wcache->tdb, key, - string_tdb_data(request_string), - TDB_INSERT) == 0) - return key; + domain = find_lookup_domain_from_sid(sid); + if (domain == NULL) { + return False; } - return NULL; -} -char *cache_retrieve_request_data(TALLOC_CTX *mem_ctx, char *key) -{ - TDB_DATA data; - char *result = NULL; + cache = get_cache(domain); - if (!init_wcache()) - return NULL; - - DEBUG(10, ("Retrieving key %s\n", key)); - - data = tdb_fetch_bystring(wcache->tdb, key); - if (data.dptr == NULL) - return NULL; - - if (strnlen(data.dptr, data.dsize) != (data.dsize)) { - DEBUG(0, ("Received invalid request string\n")); - goto done; + if (cache->tdb == NULL) { + return False; } - result = TALLOC_ARRAY(mem_ctx, char, data.dsize+1); - if (result != NULL) { - memcpy(result, data.dptr, data.dsize); - result[data.dsize] = '\0'; + + centry = wcache_fetch(cache, domain, "SN/%s", sid_string_static(sid)); + if (centry == NULL) { + return False; } - if (tdb_delete_bystring(wcache->tdb, key) != 0) { - DEBUG(0, ("Could not delete key %s\n", key)); - result = NULL; + + if (NT_STATUS_IS_OK(centry->status)) { + *type = (enum SID_NAME_USE)centry_uint32(centry); + *domain_name = centry_string(centry, mem_ctx); + *name = centry_string(centry, mem_ctx); } - done: - SAFE_FREE(data.dptr); - return result; + + status = centry->status; + centry_free(centry); + return NT_STATUS_IS_OK(status); +} + +void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid, + const char *domain_name, const char *name, + enum SID_NAME_USE type) +{ + wcache_save_sid_to_name(domain, NT_STATUS_OK, sid, domain_name, + name, type); } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 14221483ad..c91f955568 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -73,7 +73,7 @@ SAMR pipe as well for now. --jerry ******************************************************************/ -#define DISABLE_SCHANNEL_WIN2K3_SP1 1 +/* #define DISABLE_SCHANNEL_WIN2K3_SP1 1 */ /* Choose between anonymous or authenticated connections. We need to use @@ -113,8 +113,8 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, fstring dcname, struct in_addr *dc_ip) { struct winbindd_domain *our_domain; + struct rpc_pipe_client *netlogon_pipe; NTSTATUS result; - struct rpc_pipe_client *cli; TALLOC_CTX *mem_ctx; fstring tmp; @@ -123,30 +123,26 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, /* Hmmmm. We can only open one connection to the NETLOGON pipe at the * moment.... */ - if (IS_DC) + if (IS_DC) { return False; + } - if (domain->primary) + if (domain->primary) { return False; + } our_domain = find_our_domain(); - if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) + if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) { return False; - - { - /* These var's can be ignored -- we're not requesting - anything in the credential chain here */ - unsigned char *session_key; - DOM_CRED *creds; - result = cm_connect_netlogon(our_domain, mem_ctx, &cli, - &session_key, &creds); } - if (!NT_STATUS_IS_OK(result)) + result = cm_connect_netlogon(our_domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { return False; + } - result = rpccli_netlogon_getdcname(cli, mem_ctx, domain->dcname, + result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, domain->dcname, domain->name, tmp); talloc_destroy(mem_ctx); @@ -156,13 +152,18 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, /* cli_netlogon_getdcname gives us a name with \\ */ p = tmp; - if (*p == '\\') p+=1; - if (*p == '\\') p+=1; + if (*p == '\\') { + p+=1; + } + if (*p == '\\') { + p+=1; + } fstrcpy(dcname, p); - if (!resolve_name(dcname, dc_ip, 0x20)) + if (!resolve_name(dcname, dc_ip, 0x20)) { return False; + } return True; } @@ -178,7 +179,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, struct cli_state **cli, BOOL *retry) { - char *machine_password, *machine_krb5_principal; + char *machine_password, *machine_krb5_principal, *machine_account; char *ipc_username, *ipc_domain, *ipc_password; BOOL got_mutex; @@ -194,8 +195,14 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + if (asprintf(&machine_account, "%s$", global_myname()) == -1) { + SAFE_FREE(machine_password); + return NT_STATUS_NO_MEMORY; + } + if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) { + SAFE_FREE(machine_account); SAFE_FREE(machine_password); return NT_STATUS_NO_MEMORY; } @@ -257,33 +264,61 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, goto done; } - /* Krb5 session */ - if ((lp_security() == SEC_ADS) - && ((*cli)->protocol >= PROTOCOL_NT1 && - (*cli)->capabilities & CAP_EXTENDED_SECURITY)) { - + if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { ADS_STATUS ads_status; - (*cli)->use_kerberos = True; - DEBUG(5, ("connecting to %s from %s with kerberos principal " - "[%s]\n", controller, global_myname(), - machine_krb5_principal)); + + if (lp_security() == SEC_ADS) { + + /* Try a krb5 session */ + + (*cli)->use_kerberos = True; + DEBUG(5, ("connecting to %s from %s with kerberos principal " + "[%s]\n", controller, global_myname(), + machine_krb5_principal)); + + ads_status = cli_session_setup_spnego(*cli, + machine_krb5_principal, + machine_password, + lp_workgroup()); + + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4,("failed kerberos session setup with %s\n", + ads_errstr(ads_status))); + } + + result = ads_ntstatus(ads_status); + if (NT_STATUS_IS_OK(result)) { + /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + goto session_setup_done; + } + } + + /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */ + (*cli)->use_kerberos = False; + + DEBUG(5, ("connecting to %s from %s with username " + "[%s]\\[%s]\n", controller, global_myname(), + machine_account, machine_password)); ads_status = cli_session_setup_spnego(*cli, - machine_krb5_principal, + machine_account, machine_password, lp_workgroup()); - - if (!ADS_ERR_OK(ads_status)) - DEBUG(4,("failed kerberos session setup with %s\n", - ads_errstr(ads_status))); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4, ("authenticated session setup failed with %s\n", + ads_errstr(ads_status))); + } result = ads_ntstatus(ads_status); + if (NT_STATUS_IS_OK(result)) { + /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + goto session_setup_done; + } } - if (NT_STATUS_IS_OK(result)) - goto session_setup_done; - /* Fall back to non-kerberos session setup */ (*cli)->use_kerberos = False; @@ -301,8 +336,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, ipc_password, strlen(ipc_password)+1, ipc_password, strlen(ipc_password)+1, ipc_domain)) { - DEBUG(5, ("authenticated session setup failed\n")); + /* Successful logon with given username. */ + cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password); goto session_setup_done; + } else { + DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n", + ipc_domain, ipc_username )); } } @@ -310,6 +349,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) { DEBUG(5, ("Connected anonymously\n")); + cli_init_creds(*cli, "", "", ""); goto session_setup_done; } @@ -342,26 +382,28 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, *retry = False; /* set the domain if empty; needed for schannel connections */ - if ( !*(*cli)->domain ) + if ( !*(*cli)->domain ) { fstrcpy( (*cli)->domain, domain->name ); - - (*cli)->pipe_auth_flags = 0; + } result = NT_STATUS_OK; add_failed_connection = False; done: - if (got_mutex) + if (got_mutex) { secrets_named_mutex_release(controller); + } + SAFE_FREE(machine_account); SAFE_FREE(machine_password); SAFE_FREE(machine_krb5_principal); SAFE_FREE(ipc_username); SAFE_FREE(ipc_domain); SAFE_FREE(ipc_password); - if (add_failed_connection) + if (add_failed_connection) { add_failed_connection_entry(domain->name, controller, result); + } return result; } @@ -721,7 +763,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, for (retries = 0; retries < 3; retries++) { int fd = -1; - BOOL retry; + BOOL retry = False; result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; @@ -758,27 +800,23 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, void invalidate_cm_connection(struct winbindd_cm_conn *conn) { if (conn->samr_pipe != NULL) { - cli_rpc_close(conn->samr_pipe); + cli_rpc_pipe_close(conn->samr_pipe); conn->samr_pipe = NULL; } if (conn->lsa_pipe != NULL) { - cli_rpc_close(conn->lsa_pipe); + cli_rpc_pipe_close(conn->lsa_pipe); conn->lsa_pipe = NULL; } - if (conn->netlogon_auth2_pipe != NULL) { - cli_rpc_close(conn->netlogon_auth2_pipe); - conn->netlogon_auth2_pipe = NULL; - } - if (conn->netlogon_pipe != NULL) { - cli_rpc_close(conn->netlogon_pipe); + cli_rpc_pipe_close(conn->netlogon_pipe); conn->netlogon_pipe = NULL; } - if (conn->cli) + if (conn->cli) { cli_shutdown(conn->cli); + } conn->cli = NULL; } @@ -872,7 +910,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) return; } - cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC_DS); + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, &result); if (cli == NULL) { DEBUG(5, ("set_dc_type_and_flags: Could not bind to " @@ -885,7 +923,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr); - cli_rpc_close(cli); + cli_rpc_pipe_close(cli); if (!NT_STATUS_IS_OK(result)) { domain->initialized = True; @@ -896,7 +934,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) domain->native_mode = True; - cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC); + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result); if (cli == NULL) { domain->initialized = True; @@ -907,6 +945,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) domain->name); if (!mem_ctx) { DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n")); + cli_rpc_pipe_close(cli); return; } @@ -956,7 +995,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) } done: - cli_rpc_close(cli); + cli_rpc_pipe_close(cli); talloc_destroy(mem_ctx); @@ -965,20 +1004,28 @@ done: return; } -static BOOL cm_get_schannel_key(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - unsigned char **session_key) +#ifndef DISABLE_SCHANNEL_WIN2K3_SP1 +static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain, struct dcinfo **ppdc) { - struct rpc_pipe_client *cli; - DOM_CRED *credentials; + NTSTATUS result; + struct rpc_pipe_client *netlogon_pipe; - if (lp_client_schannel() == False) + if (lp_client_schannel() == False) { return False; + } - return NT_STATUS_IS_OK(cm_connect_netlogon(domain, mem_ctx, - &cli, session_key, - &credentials)); + result = cm_connect_netlogon(domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { + return False; + } + + /* Return a pointer to the struct dcinfo from the + netlogon pipe. */ + + *ppdc = domain->conn.netlogon_pipe->dc; + return True; } +#endif NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct rpc_pipe_client **cli, POLICY_HND *sam_handle) @@ -987,24 +1034,85 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, NTSTATUS result; result = init_dc_connection(domain); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } conn = &domain->conn; if (conn->samr_pipe == NULL) { + /* + * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO + * authenticated sign and sealed pipe using the machine + * account password by preference. If we can't - try schannel, + * if that fails, try anonymous. + */ + + fstring conn_pwd; + pwd_get_cleartext(&conn->cli->pwd, conn_pwd); + if (conn->cli->user_name[0] && conn->cli->domain[0] && + conn_pwd[0]) { + /* We have an authenticated connection. Use + a NTLMSSP SPNEGO authenticated SAMR pipe with + sign & seal. */ + conn->samr_pipe = + cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, + PI_SAMR, + PIPE_AUTH_LEVEL_PRIVACY, + conn->cli->domain, + conn->cli->user_name, + conn_pwd, + &result); + if (conn->samr_pipe == NULL) { + DEBUG(10,("cm_connect_sam: failed to connect " + "to SAMR pipe for domain %s using " + "NTLMSSP authenticated pipe: user " + "%s\\%s. Error was %s\n", + domain->name, conn->cli->domain, + conn->cli->user_name, + nt_errstr(result))); + } else { + DEBUG(10,("cm_connect_sam: connected to SAMR " + "pipe for domain %s using NTLMSSP " + "authenticated pipe: user %s\\%s\n", + domain->name, conn->cli->domain, + conn->cli->user_name )); + } + } + #ifndef DISABLE_SCHANNEL_WIN2K3_SP1 - unsigned char *session_key; - - if (cm_get_schannel_key(domain, mem_ctx, &session_key)) - conn->samr_pipe = cli_rpc_open_schannel(conn->cli, - PI_SAMR, - session_key, - domain->name); - else + /* Fall back to schannel if it's a W2K pre-SP1 box. */ + if (conn->samr_pipe == NULL) { + struct dcinfo *p_dcinfo; + + if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + conn->samr_pipe = + cli_rpc_pipe_open_schannel_with_key(conn->cli, + PI_SAMR, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, + p_dcinfo, + &result); + } + if (conn->samr_pipe == NULL) { + DEBUG(10,("cm_connect_sam: failed to connect " + "to SAMR pipe for domain %s using " + "schannel authenticated. Error " + "was %s\n", domain->name, + nt_errstr(result) )); + } else { + DEBUG(10,("cm_connect_sam: connected to SAMR " + "pipe for domain %s using schannel.\n", + domain->name )); + } + } #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */ - conn->samr_pipe = cli_rpc_open_noauth(conn->cli, - PI_SAMR); + + /* Finally fall back to anonymous. */ + if (conn->samr_pipe == NULL) { + conn->samr_pipe = + cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, &result); + } if (conn->samr_pipe == NULL) { result = NT_STATUS_PIPE_NOT_AVAILABLE; @@ -1014,8 +1122,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed " + "for domain %s Error was %s\n", + domain->name, nt_errstr(result) )); goto done; + } result = rpccli_samr_open_domain(conn->samr_pipe, mem_ctx, @@ -1026,9 +1138,10 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, } done: + if (!NT_STATUS_IS_OK(result)) { invalidate_cm_connection(conn); - return NT_STATUS_UNSUCCESSFUL; + return result; } *cli = conn->samr_pipe; @@ -1049,18 +1162,72 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, conn = &domain->conn; if (conn->lsa_pipe == NULL) { + fstring conn_pwd; + pwd_get_cleartext(&conn->cli->pwd, conn_pwd); + if (conn->cli->user_name[0] && conn->cli->domain[0] && + conn_pwd[0]) { + /* We have an authenticated connection. Use + a NTLMSSP SPNEGO authenticated LSA pipe with + sign & seal. */ + conn->lsa_pipe = + cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, + PI_LSARPC, + PIPE_AUTH_LEVEL_PRIVACY, + conn->cli->domain, + conn->cli->user_name, + conn_pwd, + &result); + if (conn->lsa_pipe == NULL) { + DEBUG(10,("cm_connect_lsa: failed to connect " + "to LSA pipe for domain %s using " + "NTLMSSP authenticated pipe: user " + "%s\\%s. Error was %s\n", + domain->name, conn->cli->domain, + conn->cli->user_name, + nt_errstr(result))); + } else { + DEBUG(10,("cm_connect_lsa: connected to LSA " + "pipe for domain %s using NTLMSSP " + "authenticated pipe: user %s\\%s\n", + domain->name, conn->cli->domain, + conn->cli->user_name )); + } + } + #ifndef DISABLE_SCHANNEL_WIN2K3_SP1 - unsigned char *session_key; - - if (cm_get_schannel_key(domain, mem_ctx, &session_key)) - conn->lsa_pipe = cli_rpc_open_schannel(conn->cli, - PI_LSARPC, - session_key, - domain->name); - else + /* Fall back to schannel if it's a W2K pre-SP1 box. */ + if (conn->lsa_pipe == NULL) { + struct dcinfo *p_dcinfo; + + if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + conn->lsa_pipe = + cli_rpc_pipe_open_schannel_with_key(conn->cli, + PI_LSARPC, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, + p_dcinfo, + &result); + } + if (conn->lsa_pipe == NULL) { + DEBUG(10,("cm_connect_lsa: failed to connect " + "to LSA pipe for domain %s using " + "schannel authenticated. Error " + "was %s\n", domain->name, + nt_errstr(result) )); + } else { + DEBUG(10,("cm_connect_lsa: connected to LSA " + "pipe for domain %s using schannel.\n", + domain->name )); + } + } #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */ - conn->lsa_pipe = cli_rpc_open_noauth(conn->cli, - PI_LSARPC); + + /* Finally fall back to anonymous. */ + if (conn->lsa_pipe == NULL) { + conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, + PI_LSARPC, + &result); + } if (conn->lsa_pipe == NULL) { result = NT_STATUS_PIPE_NOT_AVAILABLE; @@ -1083,55 +1250,12 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, return result; } -/******************************************************************* - wrapper around retrieving the trust account password -*******************************************************************/ +/**************************************************************************** + Open the netlogon pipe to this DC. Use schannel if specified in client conf. + session key stored in conn->netlogon_pipe->dc->sess_key. +****************************************************************************/ -static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], - uint32 *channel) -{ - DOM_SID sid; - char *pwd; - time_t last_set_time; - - /* if we are a DC and this is not our domain, then lookup an account - for the domain trust */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && - lp_allow_trusted_domains() ) { - - if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid, - &last_set_time)) { - DEBUG(0, ("get_trust_pw: could not fetch trust " - "account password for trusted domain %s\n", - domain)); - return False; - } - - *channel = SEC_CHAN_DOMAIN; - E_md4hash(pwd, ret_pwd); - SAFE_FREE(pwd); - - return True; - } - - /* Just get the account for the requested domain. In the future this - * might also cover to be member of more than one domain. */ - - if (secrets_fetch_trust_account_password(domain, ret_pwd, - &last_set_time, channel)) - return True; - - DEBUG(5, ("get_trust_pw: could not fetch trust account " - "password for domain %s\n", domain)); - return False; -} - -NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - struct rpc_pipe_client **cli, - unsigned char **session_key, - DOM_CRED **credentials) +NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct rpc_pipe_client **cli) { struct winbindd_cm_conn *conn; NTSTATUS result; @@ -1139,119 +1263,100 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; - DOM_CHAL clnt_chal, srv_chal, rcv_chal; - const char *server_name; const char *account_name; - UTIME zerotime; + struct rpc_pipe_client *netlogon_pipe; result = init_dc_connection(domain); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } conn = &domain->conn; if (conn->netlogon_pipe != NULL) { *cli = conn->netlogon_pipe; - *session_key = (unsigned char *)&conn->sess_key; - *credentials = &conn->clnt_cred; return NT_STATUS_OK; } - if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) + if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } - conn->netlogon_auth2_pipe = cli_rpc_open_noauth(conn->cli, - PI_NETLOGON); - if (conn->netlogon_auth2_pipe == NULL) - return NT_STATUS_UNSUCCESSFUL; + netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result); + if (netlogon_pipe == NULL) { + return result; + } - if (lp_client_schannel() != False) + if (lp_client_schannel() != False) { neg_flags |= NETLOGON_NEG_SCHANNEL; - - generate_random_buffer(clnt_chal.data, 8); - - server_name = talloc_asprintf(mem_ctx, "\\\\%s", domain->dcname); + } /* if we are a DC and this is a trusted domain, then we need to use our domain name in the net_req_auth2() request */ - if ( IS_DC + if ( IS_DC && !strequal(domain->name, lp_workgroup()) && lp_allow_trusted_domains() ) { - account_name = talloc_asprintf( mem_ctx, "%s$", lp_workgroup() ); - } - else { - account_name = talloc_asprintf(mem_ctx, "%s$", - domain->primary ? global_myname() : domain->name); + account_name = lp_workgroup(); + } else { + account_name = domain->primary ? global_myname() : domain->name; } - if ((server_name == NULL) || (account_name == NULL)) + if (account_name == NULL) { + cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_NO_MEMORY; + } - result = rpccli_net_req_chal(conn->netlogon_auth2_pipe, server_name, - global_myname(), &clnt_chal, &srv_chal); - if (!NT_STATUS_IS_OK(result)) - return result; - - /**************** Long-term Session key **************/ - - /* calculate the session key */ - cred_session_key(&clnt_chal, &srv_chal, mach_pwd, conn->sess_key); - memset((char *)conn->sess_key+8, '\0', 8); - - /* calculate auth2 credentials */ - zerotime.time = 0; - cred_create(conn->sess_key, &clnt_chal, zerotime, - &conn->clnt_cred.challenge); - - result = rpccli_net_auth2(conn->netlogon_auth2_pipe, server_name, - account_name, sec_chan_type, global_myname(), - &conn->clnt_cred.challenge, &neg_flags, - &rcv_chal); + result = rpccli_netlogon_setup_creds(netlogon_pipe, + domain->dcname, /* server name. */ + domain->name, /* domain name */ + account_name, /* machine account */ + mach_pwd, /* machine password */ + sec_chan_type, /* from get_trust_pw */ + &neg_flags); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { + cli_rpc_pipe_close(netlogon_pipe); return result; - - zerotime.time = 0; - if (!cred_assert(&rcv_chal, conn->sess_key, &srv_chal, zerotime)) { - DEBUG(0, ("Server replied with bad credential\n")); - return NT_STATUS_ACCESS_DENIED; } if ((lp_client_schannel() == True) && - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { DEBUG(3, ("Server did not offer schannel\n")); - cli_rpc_close(conn->netlogon_auth2_pipe); - conn->netlogon_auth2_pipe = NULL; + cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_ACCESS_DENIED; } if ((lp_client_schannel() == False) || - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - /* keep the existing connection to NETLOGON open */ - conn->netlogon_pipe = conn->netlogon_auth2_pipe; - conn->netlogon_auth2_pipe = NULL; + ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + /* We're done - just keep the existing connection to NETLOGON open */ + conn->netlogon_pipe = netlogon_pipe; *cli = conn->netlogon_pipe; - *session_key = (unsigned char *)&conn->sess_key; - *credentials = &conn->clnt_cred; return NT_STATUS_OK; } - conn->netlogon_pipe = cli_rpc_open_schannel(conn->cli, PI_NETLOGON, - conn->sess_key, - domain->name); + /* Using the credentials from the first pipe, open a signed and sealed + second netlogon pipe. The session key is stored in the schannel + part of the new pipe auth struct. + */ + + conn->netlogon_pipe = cli_rpc_pipe_open_schannel_with_key(conn->cli, + PI_NETLOGON, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, + netlogon_pipe->dc, + &result); + + /* We can now close the initial netlogon pipe. */ + cli_rpc_pipe_close(netlogon_pipe); if (conn->netlogon_pipe == NULL) { - DEBUG(3, ("Could not open schannel'ed NETLOGON pipe\n")); - cli_rpc_close(conn->netlogon_auth2_pipe); - conn->netlogon_auth2_pipe = NULL; - return NT_STATUS_ACCESS_DENIED; + DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error was %s\n", + nt_errstr(result))); + return result; } *cli = conn->netlogon_pipe; - *session_key = (unsigned char *)&conn->sess_key; - *credentials = &conn->clnt_cred; - return NT_STATUS_OK; } diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index ec0b7a36e2..60b7411417 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -38,35 +38,48 @@ /* Read some data from a client connection */ -static void dual_client_read(struct winbindd_cli_state *state) +static void child_read_request(struct winbindd_cli_state *state) { - int n; - + ssize_t len; + /* Read data */ - n = sys_read(state->sock, state->read_buf_len + - (char *)&state->request, - sizeof(state->request) - state->read_buf_len); - - DEBUG(10,("client_read: read %d bytes. Need %ld more for a full " - "request.\n", n, (unsigned long)(sizeof(state->request) - n - - state->read_buf_len) )); + len = read_data(state->sock, (char *)&state->request, + sizeof(state->request)); - /* Read failed, kill client */ - - if (n == -1 || n == 0) { - DEBUG(5,("read failed on sock %d, pid %lu: %s\n", - state->sock, (unsigned long)state->pid, - (n == -1) ? strerror(errno) : "EOF")); - + if (len != sizeof(state->request)) { + DEBUG(0, ("Got invalid request length: %d\n", (int)len)); + state->finished = True; + return; + } + + if (state->request.extra_len == 0) { + state->request.extra_data = NULL; + return; + } + + DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request.extra_len)); + + state->request.extra_data = + SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); + + if (state->request.extra_data == NULL) { + DEBUG(0, ("malloc failed\n")); + state->finished = True; + return; + } + + /* Ensure null termination */ + state->request.extra_data[state->request.extra_len] = '\0'; + + len = read_data(state->sock, state->request.extra_data, + state->request.extra_len); + + if (len != state->request.extra_len) { + DEBUG(0, ("Could not read extra data\n")); state->finished = True; return; } - - /* Update client state */ - - state->read_buf_len += n; - state->last_access = time(NULL); } /* @@ -86,6 +99,7 @@ struct winbindd_async_request { void *private_data; }; +static void async_main_request_sent(void *private_data, BOOL success); static void async_request_sent(void *private_data, BOOL success); static void async_reply_recv(void *private_data, BOOL success); static void schedule_async_request(struct winbindd_child *child); @@ -122,7 +136,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, return; } -static void async_request_sent(void *private_data, BOOL success) +static void async_main_request_sent(void *private_data, BOOL success) { struct winbindd_async_request *state = talloc_get_type_abort(private_data, struct winbindd_async_request); @@ -136,6 +150,30 @@ static void async_request_sent(void *private_data, BOOL success) return; } + if (state->request->extra_len == 0) { + async_request_sent(private_data, True); + return; + } + + setup_async_write(&state->child->event, state->request->extra_data, + state->request->extra_len, + async_request_sent, state); +} + +static void async_request_sent(void *private_data_data, BOOL success) +{ + struct winbindd_async_request *state = + talloc_get_type_abort(private_data_data, struct winbindd_async_request); + + if (!success) { + DEBUG(5, ("Could not send async request\n")); + + state->response->length = sizeof(struct winbindd_response); + state->response->result = WINBINDD_ERROR; + state->continuation(state->private_data, False); + return; + } + /* Request successfully sent to the child, setup the wait for reply */ setup_async_read(&state->child->event, @@ -196,7 +234,7 @@ static void schedule_async_request(struct winbindd_child *child) setup_async_write(&child->event, request->request, sizeof(*request->request), - async_request_sent, request); + async_main_request_sent, request); return; } @@ -205,31 +243,31 @@ struct domain_request_state { struct winbindd_domain *domain; struct winbindd_request *request; struct winbindd_response *response; - void (*continuation)(void *private_data, BOOL success); - void *private_data; + void (*continuation)(void *private_data_data, BOOL success); + void *private_data_data; }; -static void domain_init_recv(void *private_data, BOOL success); +static void domain_init_recv(void *private_data_data, BOOL success); void async_domain_request(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct winbindd_request *request, struct winbindd_response *response, - void (*continuation)(void *private_data, BOOL success), - void *private_data) + void (*continuation)(void *private_data_data, BOOL success), + void *private_data_data) { struct domain_request_state *state; if (domain->initialized) { async_request(mem_ctx, &domain->child, request, response, - continuation, private_data); + continuation, private_data_data); return; } state = TALLOC_P(mem_ctx, struct domain_request_state); if (state == NULL) { DEBUG(0, ("talloc failed\n")); - continuation(private_data, False); + continuation(private_data_data, False); return; } @@ -238,15 +276,15 @@ void async_domain_request(TALLOC_CTX *mem_ctx, state->request = request; state->response = response; state->continuation = continuation; - state->private_data = private_data; + state->private_data_data = private_data_data; init_child_connection(domain, domain_init_recv, state); } -static void recvfrom_child(void *private_data, BOOL success) +static void recvfrom_child(void *private_data_data, BOOL success) { struct winbindd_cli_state *state = - talloc_get_type_abort(private_data, struct winbindd_cli_state); + talloc_get_type_abort(private_data_data, struct winbindd_cli_state); enum winbindd_result result = state->response.result; /* This is an optimization: The child has written directly to the @@ -278,20 +316,20 @@ void sendto_domain(struct winbindd_cli_state *state, recvfrom_child, state); } -static void domain_init_recv(void *private_data, BOOL success) +static void domain_init_recv(void *private_data_data, BOOL success) { struct domain_request_state *state = - talloc_get_type_abort(private_data, struct domain_request_state); + talloc_get_type_abort(private_data_data, struct domain_request_state); if (!success) { DEBUG(5, ("Domain init returned an error\n")); - state->continuation(state->private_data, False); + state->continuation(state->private_data_data, False); return; } async_request(state->mem_ctx, &state->domain->child, state->request, state->response, - state->continuation, state->private_data); + state->continuation, state->private_data_data); } struct winbindd_child_dispatch_table { @@ -466,39 +504,34 @@ static BOOL fork_domain_child(struct winbindd_child *child) main_loop_talloc_free(); /* fetch a request from the main daemon */ - dual_client_read(&state); + child_read_request(&state); if (state.finished) { /* we lost contact with our parent */ exit(0); } - /* process full rquests */ - if (state.read_buf_len == sizeof(state.request)) { - DEBUG(4,("child daemon request %d\n", - (int)state.request.cmd)); + DEBUG(4,("child daemon request %d\n", (int)state.request.cmd)); - ZERO_STRUCT(state.response); - state.request.null_term = '\0'; - child_process_request(child->domain, &state); + ZERO_STRUCT(state.response); + state.request.null_term = '\0'; + child_process_request(child->domain, &state); - cache_store_response(sys_getpid(), &state.response); + SAFE_FREE(state.request.extra_data); - SAFE_FREE(state.response.extra_data); + cache_store_response(sys_getpid(), &state.response); - /* We just send the result code back, the result - * structure needs to be fetched via the - * winbindd_cache. Hmm. That needs fixing... */ + SAFE_FREE(state.response.extra_data); - if (write_data(state.sock, - (void *)&state.response.result, - sizeof(state.response.result)) != - sizeof(state.response.result)) { - DEBUG(0, ("Could not write result\n")); - exit(1); - } + /* We just send the result code back, the result + * structure needs to be fetched via the + * winbindd_cache. Hmm. That needs fixing... */ - state.read_buf_len = 0; + if (write_data(state.sock, (void *)&state.response.result, + sizeof(state.response.result)) != + sizeof(state.response.result)) { + DEBUG(0, ("Could not write result\n")); + exit(1); } } } diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 6261dfb616..c52ee2d960 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -1150,10 +1150,10 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma DOM_SID user_sid; NTSTATUS status; - int i, num_groups; - size_t bufsize; - ssize_t len; + char *sidstring; + size_t len; DOM_SID *groups; + int num_groups; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -1176,22 +1176,15 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma return WINBINDD_OK; } - len=bufsize=0; - state->response.extra_data = NULL; - - for (i=0; i<num_groups; i++) { - sprintf_append(NULL, (char **)&state->response.extra_data, - &len, &bufsize, - "%s\n", sid_string_static(&groups[i])); - } - - if (state->response.extra_data == NULL) { - /* Hmmm. Allocation failed somewhere */ + if (!print_sidlist(NULL, groups, num_groups, &sidstring, &len)) { + DEBUG(0, ("malloc failed\n")); return WINBINDD_ERROR; } - state->response.data.num_entries = num_groups; + state->response.extra_data = sidstring; state->response.length += len+1; + state->response.data.num_entries = num_groups; return WINBINDD_OK; } + diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 6f72a0e2c6..83c4c0f6ee 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -58,12 +58,8 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do invalidate_cm_connection(&contact_domain->conn); { - struct rpc_pipe_client *cli; - unsigned char *session_key; - DOM_CRED *creds; - - result = cm_connect_netlogon(contact_domain, state->mem_ctx, - &cli, &session_key, &creds); + struct rpc_pipe_client *netlogon_pipe; + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); } if (!NT_STATUS_IS_OK(result)) { @@ -169,7 +165,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, { fstring dcname_slash; char *p; - struct rpc_pipe_client *cli; + struct rpc_pipe_client *netlogon_pipe; NTSTATUS result; state->request.domain_name @@ -178,21 +174,14 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid, state->request.domain_name)); - { - /* These var's can be ignored -- we're not requesting - anything in the credential chain here */ - unsigned char *session_key; - DOM_CRED *creds; - result = cm_connect_netlogon(domain, state->mem_ctx, &cli, - &session_key, &creds); - } + result = cm_connect_netlogon(domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(1, ("Can't contact our the NETLOGON pipe\n")); return WINBINDD_ERROR; } - result = rpccli_netlogon_getdcname(cli, state->mem_ctx, domain->dcname, + result = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, domain->dcname, state->request.domain_name, dcname_slash); @@ -202,11 +191,14 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, } p = dcname_slash; - if (*p == '\\') p+=1; - if (*p == '\\') p+=1; + if (*p == '\\') { + p+=1; + } + if (*p == '\\') { + p+=1; + } fstrcpy(state->response.data.dc_name, p); - return WINBINDD_OK; } diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index d012811d37..c1bb4b2600 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -175,6 +175,8 @@ typedef struct winbindd_gr { /* Flag to say this is a winbindd internal send - don't recurse. */ #define WBFLAG_RECURSE 0x0800 +#define WINBINDD_MAX_EXTRA_DATA (128*1024) + /* Winbind request structure */ struct winbindd_request { @@ -183,7 +185,6 @@ struct winbindd_request { pid_t pid; /* pid of calling process */ uint32 flags; /* flags relavant to a given request */ fstring domain_name; /* name of domain for which the request applies */ - int msgid; union { fstring winsreq; /* WINS request */ @@ -240,10 +241,9 @@ struct winbindd_request { gid_t gid; fstring sid; } dual_idmapset; - struct { - fstring cache_key; - } dual_sidaliases; } data; + char *extra_data; + size_t extra_len; char null_term; }; diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index a0712144ee..c2324291a6 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -37,7 +37,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { return NT_STATUS_NO_MEMORY; } - if (!net_io_user_info3("", info3, &ps, 1, 3)) { + if (!net_io_user_info3("", info3, &ps, 1, 3, False)) { prs_mem_free(&ps); return NT_STATUS_UNSUCCESSFUL; } @@ -227,15 +227,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, { NTSTATUS result; fstring name_domain, name_user; - const char *srv_name_slash; NET_USER_INFO_3 info3; - unsigned char *session_key; - struct rpc_pipe_client *pipe_cli; + struct rpc_pipe_client *netlogon_pipe; uchar chal[8]; DATA_BLOB lm_resp; DATA_BLOB nt_resp; - DOM_CRED ret_creds; - DOM_CRED *credentials; int attempts = 0; unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; @@ -311,7 +307,6 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, local_nt_response, sizeof(local_nt_response)); } - /* what domain should we contact? */ @@ -333,49 +328,30 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, contact_domain = find_our_domain(); } - srv_name_slash = talloc_asprintf(state->mem_ctx, "\\\\%s", - contact_domain->dcname); - if (srv_name_slash == NULL) { - DEBUG(0, ("talloc_asprintf failed\n")); - return WINBINDD_ERROR; - } - /* check authentication loop */ do { - DOM_CRED clnt_creds; ZERO_STRUCT(info3); - ZERO_STRUCT(ret_creds); retry = False; - result = cm_connect_netlogon(contact_domain, state->mem_ctx, - &pipe_cli, &session_key, - &credentials); + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); goto done; } - credentials->timestamp.time = time(NULL); - memcpy(&clnt_creds, credentials, sizeof(clnt_creds)); - - /* Calculate the new credentials. */ - cred_create(session_key, &credentials->challenge, - clnt_creds.timestamp, &(clnt_creds.challenge)); - - result = rpccli_netlogon_sam_network_logon(pipe_cli, - state->mem_ctx, - srv_name_slash, - &clnt_creds, - &ret_creds, - name_user, - name_domain, - global_myname(), - chal, lm_resp, - nt_resp, &info3, - session_key); + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, + state->mem_ctx, + contact_domain->dcname, /* server name */ + name_user, /* user name */ + name_domain, /* target domain */ + global_myname(), /* workstation */ + chal, + lm_resp, + nt_resp, + &info3); attempts += 1; /* We have to try a second time as cm_connect_netlogon @@ -404,21 +380,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, } while ( (attempts < 2) && retry ); - /* Only check creds if we got a connection. */ - if (contact_domain->conn.cli && - !(NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || - NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) { - if (!clnt_deal_with_creds(session_key, credentials, &ret_creds)) { - DEBUG(3, ("DC %s sent wrong credentials\n", - pipe_cli->cli->srv_name_slash)); - result = NT_STATUS_ACCESS_DENIED; - } - } - if (NT_STATUS_IS_OK(result)) { /* Check if the user is in the right group */ - if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, state->request.data.auth.require_membership_of_sid))) { + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + state->request.data.auth.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", state->request.data.auth.user, state->request.data.auth.require_membership_of_sid)); @@ -426,8 +392,10 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, } done: + /* give us a more useful (more correct?) error code */ - if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; } @@ -450,7 +418,9 @@ done: char *afsname = SMB_STRDUP(lp_afs_username_map()); char *cell; - if (afsname == NULL) goto no_token; + if (afsname == NULL) { + goto no_token; + } afsname = realloc_string_sub(afsname, "%D", name_domain); afsname = realloc_string_sub(afsname, "%u", name_user); @@ -466,7 +436,9 @@ done: afsname = realloc_string_sub(afsname, "%s", sidstr); } - if (afsname == NULL) goto no_token; + if (afsname == NULL) { + goto no_token; + } strlower_m(afsname); @@ -474,7 +446,9 @@ done: cell = strchr(afsname, '@'); - if (cell == NULL) goto no_token; + if (cell == NULL) { + goto no_token; + } *cell = '\0'; cell += 1; @@ -565,16 +539,12 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, struct winbindd_cli_state *state) { NTSTATUS result; - const char *srv_name_slash; NET_USER_INFO_3 info3; - unsigned char *session_key; - struct rpc_pipe_client *pipe_cli; - DOM_CRED *credentials; + struct rpc_pipe_client *netlogon_pipe; const char *name_user = NULL; const char *name_domain = NULL; const char *workstation; struct winbindd_domain *contact_domain; - DOM_CRED ret_creds; int attempts = 0; BOOL retry; @@ -618,9 +588,10 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len); - nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len); - + lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp, + state->request.data.auth_crap.lm_resp_len); + nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp, + state->request.data.auth_crap.nt_resp_len); /* what domain should we contact? */ @@ -631,33 +602,20 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, result = NT_STATUS_NO_SUCH_USER; goto done; } - } else { if (is_myname(name_domain)) { DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } - contact_domain = find_our_domain(); } - srv_name_slash = talloc_asprintf(state->mem_ctx, "\\\\%s", - contact_domain->dcname); - if (srv_name_slash == NULL) { - DEBUG(0, ("talloc_asprintf failed\n")); - return WINBINDD_ERROR; - } - do { - DOM_CRED clnt_creds; ZERO_STRUCT(info3); - ZERO_STRUCT(ret_creds); retry = False; - result = cm_connect_netlogon(contact_domain, state->mem_ctx, - &pipe_cli, &session_key, - &credentials); + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", @@ -665,25 +623,16 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - credentials->timestamp.time = time(NULL); - memcpy(&clnt_creds, credentials, sizeof(clnt_creds)); - - /* Calculate the new credentials. */ - cred_create(session_key, &credentials->challenge, - clnt_creds.timestamp, &(clnt_creds.challenge)); - - result = rpccli_netlogon_sam_network_logon(pipe_cli, - state->mem_ctx, - srv_name_slash, - &clnt_creds, - &ret_creds, - name_user, - name_domain, - global_myname(), - state->request.data.auth_crap.chal, - lm_resp, - nt_resp, &info3, - session_key); + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, + state->mem_ctx, + contact_domain->dcname, + name_user, + name_domain, + global_myname(), + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); attempts += 1; @@ -712,19 +661,9 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } while ( (attempts < 2) && retry ); - /* Only check creds if we got a connection. */ - if (contact_domain->conn.cli && - !(NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || - (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { - if (!clnt_deal_with_creds(session_key, credentials, &ret_creds)) { - DEBUG(3, ("DC %s sent wrong credentials\n", - pipe_cli->cli->srv_name_slash)); - result = NT_STATUS_ACCESS_DENIED; - } - } - if (NT_STATUS_IS_OK(result)) { - if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, state->request.data.auth_crap.require_membership_of_sid))) { + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", state->request.data.auth_crap.user, state->request.data.auth_crap.require_membership_of_sid)); @@ -736,14 +675,14 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } else if (state->request.flags & WBFLAG_PAM_UNIX_NAME) { /* ntlm_auth should return the unix username, per 'winbind use default domain' settings and the like */ - + fstring username_out; const char *nt_username, *nt_domain; if (!(nt_username = unistr2_tdup(state->mem_ctx, &(info3.uni_user_name)))) { /* If the server didn't give us one, just use the one we sent them */ nt_username = name_user; } - + if (!(nt_domain = unistr2_tdup(state->mem_ctx, &(info3.uni_logon_dom)))) { /* If the server didn't give us one, just use the one we sent them */ nt_domain = name_domain; @@ -762,29 +701,34 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } if (state->request.flags & WBFLAG_PAM_USER_SESSION_KEY) { - memcpy(state->response.data.auth.user_session_key, info3.user_sess_key, sizeof(state->response.data.auth.user_session_key) /* 16 */); + memcpy(state->response.data.auth.user_session_key, info3.user_sess_key, + sizeof(state->response.data.auth.user_session_key) /* 16 */); } if (state->request.flags & WBFLAG_PAM_LMKEY) { - memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); + memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key, + sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); } } done: + /* give us a more useful (more correct?) error code */ - if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; } if (state->request.flags & WBFLAG_PAM_NT_STATUS_SQUASH) { result = nt_status_squash(result); } - + state->response.data.auth.nt_status = NT_STATUS_V(result); fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - + /* we might have given a more useful error above */ - if (!*state->response.data.auth.error_string) + if (!*state->response.data.auth.error_string) { fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); + } state->response.data.auth.pam_error = nt_status_to_pam(result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, |