summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-09-30 17:13:37 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:04:48 -0500
commit54abd2aa66069e6baf7769c496f46d9dba18db39 (patch)
tree9cf8e88168011797319ba9e9866749201b1eac1e /source3/nsswitch
parent4a2cc231d22a82ed21771a72508f15d21ed63227 (diff)
downloadsamba-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.c5
-rw-r--r--source3/nsswitch/wbinfo.c1
-rw-r--r--source3/nsswitch/winbindd.c67
-rw-r--r--source3/nsswitch/winbindd.h16
-rw-r--r--source3/nsswitch/winbindd_ads.c11
-rw-r--r--source3/nsswitch/winbindd_async.c97
-rw-r--r--source3/nsswitch/winbindd_cache.c86
-rw-r--r--source3/nsswitch/winbindd_cm.c513
-rw-r--r--source3/nsswitch/winbindd_dual.c151
-rw-r--r--source3/nsswitch/winbindd_group.c23
-rw-r--r--source3/nsswitch/winbindd_misc.c30
-rw-r--r--source3/nsswitch/winbindd_nss.h8
-rw-r--r--source3/nsswitch/winbindd_pam.c172
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,