summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/.cvsignore1
-rw-r--r--source3/nsswitch/hp_nss_common.h4
-rw-r--r--source3/nsswitch/nss.h2
-rw-r--r--source3/nsswitch/pam_winbind.c9
-rw-r--r--source3/nsswitch/wb_client.c5
-rw-r--r--source3/nsswitch/wb_common.c6
-rw-r--r--source3/nsswitch/wbinfo.c35
-rw-r--r--source3/nsswitch/winbind_nss.c26
-rw-r--r--source3/nsswitch/winbind_nss_config.h6
-rw-r--r--source3/nsswitch/winbindd.c145
-rw-r--r--source3/nsswitch/winbindd.h3
-rw-r--r--source3/nsswitch/winbindd_ads.c183
-rw-r--r--source3/nsswitch/winbindd_cache.c55
-rw-r--r--source3/nsswitch/winbindd_cm.c6
-rw-r--r--source3/nsswitch/winbindd_group.c42
-rw-r--r--source3/nsswitch/winbindd_idmap.c28
-rw-r--r--source3/nsswitch/winbindd_misc.c13
-rw-r--r--source3/nsswitch/winbindd_nss.h3
-rw-r--r--source3/nsswitch/winbindd_pam.c3
-rw-r--r--source3/nsswitch/winbindd_proto.h11
-rw-r--r--source3/nsswitch/winbindd_rpc.c34
-rw-r--r--source3/nsswitch/winbindd_sid.c4
-rw-r--r--source3/nsswitch/winbindd_user.c3
-rw-r--r--source3/nsswitch/winbindd_util.c7
-rw-r--r--source3/nsswitch/winbindd_wins.c28
-rw-r--r--source3/nsswitch/wins.c51
26 files changed, 494 insertions, 219 deletions
diff --git a/source3/nsswitch/.cvsignore b/source3/nsswitch/.cvsignore
index 090b859b37..658d50a680 100644
--- a/source3/nsswitch/.cvsignore
+++ b/source3/nsswitch/.cvsignore
@@ -1,3 +1,4 @@
*.po
*.po32
diffs
+winbindd_proto.h
diff --git a/source3/nsswitch/hp_nss_common.h b/source3/nsswitch/hp_nss_common.h
index 5f39e9abb0..5bd5374182 100644
--- a/source3/nsswitch/hp_nss_common.h
+++ b/source3/nsswitch/hp_nss_common.h
@@ -23,8 +23,12 @@
Boston, MA 02111-1307, USA.
*/
+#ifdef HAVE_SYNCH_H
#include <synch.h>
+#endif
+#ifdef HAVE_PTHREAD_H
#include <pthread.h>
+#endif
typedef enum {
NSS_SUCCESS,
diff --git a/source3/nsswitch/nss.h b/source3/nsswitch/nss.h
index e021b013b5..d83a5e237e 100644
--- a/source3/nsswitch/nss.h
+++ b/source3/nsswitch/nss.h
@@ -72,7 +72,7 @@ typedef enum
#define NSD_MEM_VOLATILE 1
#define NSD_MEM_DYNAMIC 2
-#elif defined(HPUX)
+#elif defined(HPUX) && defined(HAVE_NSSWITCH_H)
/* HP-UX 11 */
#include "nsswitch/hp_nss_common.h"
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
index b192a347f4..4739cfbf7a 100644
--- a/source3/nsswitch/pam_winbind.c
+++ b/source3/nsswitch/pam_winbind.c
@@ -155,6 +155,14 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
/* incorrect password */
_pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user);
return retval;
+ case PAM_ACCT_EXPIRED:
+ /* account expired */
+ _pam_log(LOG_WARNING, "user `%s' account expired", user);
+ return retval;
+ case PAM_AUTHTOK_EXPIRED:
+ /* password expired */
+ _pam_log(LOG_WARNING, "user `%s' password expired", user);
+ return retval;
case PAM_USER_UNKNOWN:
/* the user does not exist */
if (ctrl & WINBIND_DEBUG_ARG)
@@ -577,6 +585,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
retval = winbind_auth_request(user, pass_old, ctrl);
if (retval != PAM_ACCT_EXPIRED
+ && retval != PAM_AUTHTOK_EXPIRED
&& retval != PAM_NEW_AUTHTOK_REQD
&& retval != PAM_SUCCESS) {
pass_old = NULL;
diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c
index 53550ca353..bcb339864a 100644
--- a/source3/nsswitch/wb_client.c
+++ b/source3/nsswitch/wb_client.c
@@ -25,6 +25,11 @@
#include "includes.h"
#include "nsswitch/nss.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+extern DOM_SID global_sid_NULL; /* NULL sid */
+
NSS_STATUS winbindd_request(int req_type,
struct winbindd_request *request,
struct winbindd_response *response);
diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c
index 6a2143f8f0..89dd625241 100644
--- a/source3/nsswitch/wb_common.c
+++ b/source3/nsswitch/wb_common.c
@@ -86,7 +86,7 @@ void init_response(struct winbindd_response *response)
/* Close established socket */
-void close_sock(void)
+static void close_sock(void)
{
if (winbindd_fd != -1) {
close(winbindd_fd);
@@ -168,7 +168,7 @@ int winbind_open_pipe_sock(void)
return winbindd_fd;
}
-/* Write data to winbindd socket with timeout */
+/* Write data to winbindd socket */
int write_sock(void *buffer, int count)
{
@@ -234,7 +234,7 @@ int write_sock(void *buffer, int count)
return nwritten;
}
-/* Read data from winbindd socket with timeout */
+/* Read data from winbindd socket */
static int read_sock(void *buffer, int count)
{
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 3ddd1865c0..d0af10a0e6 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -25,6 +25,9 @@
#include "winbindd.h"
#include "debug.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* Prototypes from common.h */
NSS_STATUS winbindd_request(int req_type,
@@ -248,25 +251,22 @@ static BOOL wbinfo_show_sequence(void)
static BOOL wbinfo_check_secret(void)
{
struct winbindd_response response;
- BOOL result;
+ NSS_STATUS result;
ZERO_STRUCT(response);
result = winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response) ==
NSS_STATUS_SUCCESS;
+
+ d_printf("checking the trust secret via RPC calls %s\n",
+ (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
- if (result) {
-
- if (response.data.num_entries == 0)
- d_printf("Secret is good\n");
- else
- d_printf("Secret is bad\n0x%08x\n",
- response.data.num_entries);
-
- return True;
- }
-
- return False;
+ if (result != NSS_STATUS_SUCCESS)
+ d_printf("error code was %s (0x%x)\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.nt_status);
+
+ return result == NSS_STATUS_SUCCESS;
}
/* Convert uid to sid */
@@ -593,7 +593,7 @@ static BOOL wbinfo_set_auth_user(char *username)
/* Store in secrets.tdb */
- if (!secrets_store(SECRETS_AUTH_USER, username,
+ if (!secrets_store(SECRETS_AUTH_USER, user,
strlen(user) + 1) ||
!secrets_store(SECRETS_AUTH_DOMAIN, domain,
strlen(domain) + 1) ||
@@ -640,16 +640,17 @@ static void usage(void)
d_printf("\t-m\t\t\tlist trusted domains\n");
d_printf("\t-r user\t\t\tget user groups\n");
d_printf("\t-a user%%password\tauthenticate user\n");
- d_printf("\t-A user%%password\tstore user and password used by winbindd (root only)\n");
- d_printf("\t-p 'ping' winbindd to see if it is alive\n");
+ d_printf("\t-A user%%password\tstore user and password used by winbindd (root only)\n");
+ d_printf("\t-p\t\t\t'ping' winbindd to see if it is alive\n");
d_printf("\t--sequence\t\tshow sequence numbers of all domains\n");
+ d_printf("\t--set-auth-user DOMAIN\\user%%password\tset password for restrict anonymous\n");
}
/* Main program */
enum {
OPT_SET_AUTH_USER = 1000,
- OPT_SEQUENCE,
+ OPT_SEQUENCE
};
int main(int argc, char **argv)
diff --git a/source3/nsswitch/winbind_nss.c b/source3/nsswitch/winbind_nss.c
index a396e5551b..5dc3d32279 100644
--- a/source3/nsswitch/winbind_nss.c
+++ b/source3/nsswitch/winbind_nss.c
@@ -238,6 +238,7 @@ winbind_callback(nsd_file_t **rqp, int fd)
free_response(&response);
return(do_list(1,rq));
case WINBINDD_GETGRENT:
+ case WINBINDD_GETGRLST:
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) - %d GETGRENT responses\n",
response.data.num_entries);
@@ -1053,13 +1054,15 @@ _nss_winbind_endgrent(void)
/* Get next entry from ntdom group database */
-NSS_STATUS
-_nss_winbind_getgrent_r(struct group *result,
- char *buffer, size_t buflen, int *errnop)
+static NSS_STATUS
+winbind_getgrent(enum winbindd_cmd cmd,
+ struct group *result,
+ char *buffer, size_t buflen, int *errnop)
{
NSS_STATUS ret;
static struct winbindd_request request;
static int called_again;
+
#ifdef DEBUG_NSS
fprintf(stderr, "[%5d]: getgrent\n", getpid());
@@ -1083,7 +1086,7 @@ _nss_winbind_getgrent_r(struct group *result,
request.data.num_entries = MAX_GETGRENT_USERS;
- ret = winbindd_request(WINBINDD_GETGRENT, &request,
+ ret = winbindd_request(cmd, &request,
&getgrent_response);
if (ret == NSS_STATUS_SUCCESS) {
@@ -1141,6 +1144,21 @@ _nss_winbind_getgrent_r(struct group *result,
return ret;
}
+
+NSS_STATUS
+_nss_winbind_getgrent_r(struct group *result,
+ char *buffer, size_t buflen, int *errnop)
+{
+ return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop);
+}
+
+NSS_STATUS
+_nss_winbind_getgrlst_r(struct group *result,
+ char *buffer, size_t buflen, int *errnop)
+{
+ return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop);
+}
+
/* Return group struct from group name */
NSS_STATUS
diff --git a/source3/nsswitch/winbind_nss_config.h b/source3/nsswitch/winbind_nss_config.h
index 0de63878be..b9c738211e 100644
--- a/source3/nsswitch/winbind_nss_config.h
+++ b/source3/nsswitch/winbind_nss_config.h
@@ -129,11 +129,15 @@ typedef int BOOL;
#endif
/* zero a structure */
+#ifndef ZERO_STRUCT
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+#endif
/* zero a structure given a pointer to the structure */
+#ifndef ZERO_STRUCTP
#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); }
-
+#endif
+
/* Some systems (SCO) treat UNIX domain sockets as FIFOs */
#ifndef S_IFSOCK
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 4f64790236..358d9add3a 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -4,6 +4,7 @@
Winbind daemon for ntdom nss module
Copyright (C) by Tim Potter 2000, 2001
+ Copyright (C) Andrew Tridgell 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,7 +27,8 @@
struct winbindd_cli_state *client_list;
static int num_clients;
-BOOL opt_nocache;
+BOOL opt_nocache = False;
+BOOL opt_dual_daemon = False;
/* Reload configuration */
@@ -221,6 +223,7 @@ static struct dispatch_table dispatch_table[] = {
{ WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" },
{ WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" },
{ WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" },
+ { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" },
/* PAM auth functions */
@@ -365,9 +368,10 @@ static void remove_client(struct winbindd_cli_state *state)
}
}
+
/* Process a complete received packet from a client */
-static void process_packet(struct winbindd_cli_state *state)
+void winbind_process_packet(struct winbindd_cli_state *state)
{
/* Process request */
@@ -379,11 +383,16 @@ static void process_packet(struct winbindd_cli_state *state)
state->read_buf_len = 0;
state->write_buf_len = sizeof(struct winbindd_response);
+
+ /* we might need to send it to the dual daemon */
+ if (opt_dual_daemon) {
+ dual_send_request(state);
+ }
}
/* Read some data from a client connection */
-static void client_read(struct winbindd_cli_state *state)
+void winbind_client_read(struct winbindd_cli_state *state)
{
int n;
@@ -529,6 +538,10 @@ static void process_loop(int accept_sock)
timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
timeout.tv_usec = 0;
+ if (opt_dual_daemon) {
+ maxfd = dual_select_setup(&w_fds, maxfd);
+ }
+
/* Set up client readers and writers */
state = client_list;
@@ -583,6 +596,10 @@ static void process_loop(int accept_sock)
if (selret > 0) {
+ if (opt_dual_daemon) {
+ dual_select(&w_fds);
+ }
+
if (FD_ISSET(accept_sock, &r_fds))
new_connection(accept_sock);
@@ -596,7 +613,7 @@ static void process_loop(int accept_sock)
/* Read data */
- client_read(state);
+ winbind_client_read(state);
/*
* If we have the start of a
@@ -620,7 +637,7 @@ static void process_loop(int accept_sock)
if (state->read_buf_len ==
sizeof(state->request)) {
- process_packet(state);
+ winbind_process_packet(state);
}
}
@@ -656,6 +673,62 @@ static void process_loop(int accept_sock)
}
}
+
+/*
+ these are split out from the main winbindd for use by the background daemon
+ */
+int winbind_setup_common(void)
+{
+ load_interfaces();
+
+ if (!secrets_init()) {
+
+ DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
+ return 1;
+
+ }
+
+ /* Get list of domains we look up requests for. This includes the
+ domain which we are a member of as well as any trusted
+ domains. */
+
+ init_domain_list();
+
+ ZERO_STRUCT(server_state);
+
+ /* Winbind daemon initialisation */
+
+ if (!winbindd_param_init())
+ return 1;
+
+ if (!winbindd_idmap_init())
+ return 1;
+
+ /* Unblock all signals we are interested in as they may have been
+ blocked by the parent process. */
+
+ BlockSignals(False, SIGINT);
+ BlockSignals(False, SIGQUIT);
+ BlockSignals(False, SIGTERM);
+ BlockSignals(False, SIGUSR1);
+ BlockSignals(False, SIGUSR2);
+ BlockSignals(False, SIGHUP);
+
+ /* Setup signal handlers */
+
+ CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */
+ CatchSignal(SIGQUIT, termination_handler);
+ CatchSignal(SIGTERM, termination_handler);
+
+ CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
+
+ CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */
+ CatchSignal(SIGHUP, sighup_handler);
+
+ return 0;
+}
+
+
/* Main function */
struct winbindd_state server_state; /* Server state information */
@@ -665,13 +738,14 @@ static void usage(void)
{
printf("Usage: winbindd [options]\n");
printf("\t-i interactive mode\n");
+ printf("\t-B dual daemon mode\n");
printf("\t-n disable cacheing\n");
printf("\t-d level set debug level\n");
printf("\t-s configfile choose smb.conf location\n");
printf("\t-h show this help message\n");
}
-int main(int argc, char **argv)
+ int main(int argc, char **argv)
{
extern BOOL AllowDebugChange;
extern pstring global_myname;
@@ -709,7 +783,7 @@ int main(int argc, char **argv)
/* Initialise samba/rpc client stuff */
- while ((opt = getopt(argc, argv, "id:s:nh")) != EOF) {
+ while ((opt = getopt(argc, argv, "id:s:nhB")) != EOF) {
switch (opt) {
/* Don't become a daemon */
@@ -717,6 +791,11 @@ int main(int argc, char **argv)
interactive = True;
break;
+ /* dual daemon system */
+ case 'B':
+ opt_dual_daemon = True;
+ break;
+
/* disable cacheing */
case 'n':
opt_nocache = True;
@@ -756,8 +835,6 @@ int main(int argc, char **argv)
exit(1);
}
- pidfile_create("winbindd");
-
/* Setup names. */
if (!*global_myname) {
@@ -771,8 +848,10 @@ int main(int argc, char **argv)
fstrcpy(global_myworkgroup, lp_workgroup());
- if (!interactive)
+ if (!interactive) {
become_daemon();
+ pidfile_create("winbindd");
+ }
#if HAVE_SETPGID
/*
@@ -783,51 +862,13 @@ int main(int argc, char **argv)
setpgid( (pid_t)0, (pid_t)0);
#endif
- load_interfaces();
-
- if (!secrets_init()) {
-
- DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
- return 1;
-
+ if (opt_dual_daemon) {
+ do_dual_daemon();
}
- /* Get list of domains we look up requests for. This includes the
- domain which we are a member of as well as any trusted
- domains. */
-
- init_domain_list();
-
- ZERO_STRUCT(server_state);
-
- /* Winbind daemon initialisation */
-
- if (!winbindd_param_init())
- return 1;
-
- if (!winbindd_idmap_init())
+ if (winbind_setup_common() != 0) {
return 1;
-
- /* Unblock all signals we are interested in as they may have been
- blocked by the parent process. */
-
- BlockSignals(False, SIGINT);
- BlockSignals(False, SIGQUIT);
- BlockSignals(False, SIGTERM);
- BlockSignals(False, SIGUSR1);
- BlockSignals(False, SIGUSR2);
- BlockSignals(False, SIGHUP);
-
- /* Setup signal handlers */
-
- CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */
- CatchSignal(SIGQUIT, termination_handler);
- CatchSignal(SIGTERM, termination_handler);
-
- CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
-
- CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */
- CatchSignal(SIGHUP, sighup_handler);
+ }
/* Initialise messaging system */
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 4d35c27c21..11d399be49 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -29,6 +29,9 @@
#include "winbindd_nss.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* Client state structure */
struct winbindd_cli_state {
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 22bad667c3..b61348adfe 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -24,6 +24,9 @@
#ifdef HAVE_ADS
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* the realm of our primary LDAP server */
static char *primary_realm;
@@ -58,7 +61,7 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
if (*res) ads_msgfree(ads, *res);
*res = NULL;
- DEBUG(1,("Reopening ads connection to %s after error %s\n",
+ DEBUG(3,("Reopening ads connection to %s after error %s\n",
ads->ldap_server, ads_errstr(status)));
if (ads->ld) {
ldap_unbind(ads->ld);
@@ -119,6 +122,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
if (resolve_name(domain->name, &server_ip, 0x1b)) {
sname = inet_ntoa(server_ip);
+ } else if (resolve_name(domain->name, &server_ip, 0x1c)) {
+ sname = inet_ntoa(server_ip);
} else {
if (strcasecmp(domain->name, lp_workgroup()) != 0) {
DEBUG(1,("can't find domain controller for %s\n", domain->name));
@@ -127,7 +132,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
sname = NULL;
}
- ads = ads_init(primary_realm, sname, NULL, NULL);
+ ads = ads_init(primary_realm, domain->name, NULL, NULL, NULL);
if (!ads) {
DEBUG(1,("ads_init for domain %s failed\n", domain->name));
return NULL;
@@ -138,7 +143,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
ads->password = secrets_fetch_machine_password();
status = ads_connect(ads);
- if (!ADS_ERR_OK(status)) {
+ if (!ADS_ERR_OK(status) || !ads->realm) {
extern struct winbindd_methods msrpc_methods;
DEBUG(1,("ads_connect for domain %s failed: %s\n",
domain->name, ads_errstr(status)));
@@ -186,6 +191,24 @@ static enum SID_NAME_USE ads_atype_map(uint32 atype)
return SID_NAME_UNKNOWN;
}
+/*
+ in order to support usernames longer than 21 characters we need to
+ use both the sAMAccountName and the userPrincipalName attributes
+ It seems that not all users have the userPrincipalName attribute set
+*/
+static char *pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, void *msg)
+{
+ char *ret, *p;
+
+ ret = ads_pull_string(ads, mem_ctx, msg, "userPrincipalName");
+ if (ret && (p = strchr(ret, '@'))) {
+ *p = 0;
+ return ret;
+ }
+ return ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
+}
+
+
/* Query display info for a realm. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -193,7 +216,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
WINBIND_USERINFO **info)
{
ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"sAMAccountName", "name", "objectSid", "primaryGroupID",
+ const char *attrs[] = {"userPrincipalName",
+ "sAMAccountName",
+ "name", "objectSid", "primaryGroupID",
"sAMAccountType", NULL};
int i, count;
ADS_STATUS rc;
@@ -240,7 +265,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
continue;
}
- name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
+ name = pull_username(ads, mem_ctx, msg);
gecos = ads_pull_string(ads, mem_ctx, msg, "name");
if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
DEBUG(1,("No sid for %s !?\n", name));
@@ -251,7 +276,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
continue;
}
- if (!sid_peek_rid(&sid, &rid)) {
+ if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
DEBUG(1,("No rid for %s !?\n", name));
continue;
}
@@ -281,7 +306,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
struct acct_info **info)
{
ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"sAMAccountName", "name", "objectSid",
+ const char *attrs[] = {"userPrincipalName", "sAMAccountName",
+ "name", "objectSid",
"sAMAccountType", NULL};
int i, count;
ADS_STATUS rc;
@@ -298,13 +324,13 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs);
if (!ADS_ERR_OK(rc)) {
- DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
+ DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
goto done;
}
count = ads_count_replies(ads, res);
if (count == 0) {
- DEBUG(1,("query_user_list: No users found\n"));
+ DEBUG(1,("enum_dom_groups: No groups found\n"));
goto done;
}
@@ -326,14 +352,14 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
&account_type) ||
!(account_type & ATYPE_GROUP)) continue;
- name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
+ name = pull_username(ads, mem_ctx, msg);
gecos = ads_pull_string(ads, mem_ctx, msg, "name");
if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
DEBUG(1,("No sid for %s !?\n", name));
continue;
}
- if (!sid_peek_rid(&sid, &rid)) {
+ if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
DEBUG(1,("No rid for %s !?\n", name));
continue;
}
@@ -377,7 +403,9 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
ads = ads_cached_connection(domain);
if (!ads) goto done;
- asprintf(&exp, "(sAMAccountName=%s)", name);
+ /* accept either the win2000 or the pre-win2000 username */
+ asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
+ name, name, ads->realm);
rc = ads_search_retry(ads, &res, exp, attrs);
free(exp);
if (!ADS_ERR_OK(rc)) {
@@ -421,7 +449,9 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
enum SID_NAME_USE *type)
{
ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"sAMAccountName", "sAMAccountType", NULL};
+ const char *attrs[] = {"userPrincipalName",
+ "sAMAccountName",
+ "sAMAccountType", NULL};
ADS_STATUS rc;
void *msg = NULL;
char *exp;
@@ -448,7 +478,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
goto done;
}
- *name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
+ *name = pull_username(ads, mem_ctx, msg);
*type = ads_atype_map(atype);
status = NT_STATUS_OK;
@@ -462,6 +492,50 @@ done:
}
+/* convert a DN to a name, rid and name type
+ this might become a major speed bottleneck if groups have
+ lots of users, in which case we could cache the results
+*/
+static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ const char *dn,
+ char **name, uint32 *name_type, uint32 *rid)
+{
+ char *exp;
+ void *res = NULL;
+ const char *attrs[] = {"userPrincipalName", "sAMAccountName",
+ "objectSid", "sAMAccountType", NULL};
+ ADS_STATUS rc;
+ uint32 atype;
+ DOM_SID sid;
+
+ asprintf(&exp, "(distinguishedName=%s)", dn);
+ rc = ads_search_retry(ads, &res, exp, attrs);
+ free(exp);
+ if (!ADS_ERR_OK(rc)) {
+ goto failed;
+ }
+
+ (*name) = pull_username(ads, mem_ctx, res);
+
+ if (!ads_pull_uint32(ads, res, "sAMAccountType", &atype)) {
+ goto failed;
+ }
+ (*name_type) = ads_atype_map(atype);
+
+ if (!ads_pull_sid(ads, res, "objectSid", &sid) ||
+ !sid_peek_rid(&sid, rid)) {
+ goto failed;
+ }
+
+ if (res) ads_msgfree(ads, res);
+ return True;
+
+failed:
+ if (res) ads_msgfree(ads, res);
+ return False;
+}
+
+
/* convert a sid to a distnguished name */
static NTSTATUS sid_to_distinguished_name(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -511,7 +585,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
WINBIND_USERINFO *info)
{
ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"sAMAccountName", "name", "objectSid",
+ const char *attrs[] = {"userPrincipalName",
+ "sAMAccountName",
+ "name", "objectSid",
"primaryGroupID", NULL};
ADS_STATUS rc;
int count;
@@ -544,7 +620,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
goto done;
}
- info->acct_name = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
+ info->acct_name = pull_username(ads, mem_ctx, msg);
info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
DEBUG(1,("No sid for %d !?\n", user_rid));
@@ -555,7 +631,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
goto done;
}
- if (!sid_peek_rid(&sid, &info->user_rid)) {
+ if (!sid_peek_check_rid(&domain->sid,&sid, &info->user_rid)) {
DEBUG(1,("No rid for %d !?\n", user_rid));
goto done;
}
@@ -633,7 +709,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
for (i=1;i<count;i++) {
uint32 rid;
- if (!sid_peek_rid(&sids[i-1], &rid)) continue;
+ if (!sid_peek_check_rid(&domain->sid, &sids[i-1], &rid)) continue;
(*user_gids)[*num_groups] = rid;
(*num_groups)++;
}
@@ -646,7 +722,9 @@ done:
return status;
}
-
+/*
+ find the members of a group, given a group rid and domain
+ */
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 group_rid, uint32 *num_names,
@@ -654,13 +732,16 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
uint32 **name_types)
{
DOM_SID group_sid;
- const char *attrs[] = {"sAMAccountName", "objectSid", "sAMAccountType", NULL};
ADS_STATUS rc;
int count;
- void *res=NULL, *msg=NULL;
+ void *res=NULL;
ADS_STRUCT *ads = NULL;
- char *exp, *dn = NULL;
+ char *exp;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ char *sidstr;
+ const char *attrs[] = {"member", NULL};
+ char **members;
+ int i, num_members;
*num_names = 0;
@@ -668,17 +749,14 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
if (!ads) goto done;
sid_from_rid(domain, group_rid, &group_sid);
- status = sid_to_distinguished_name(domain, mem_ctx, &group_sid, &dn);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("Failed to find distinguishedName for %s\n", sid_string_static(&group_sid)));
- return status;
- }
+ sidstr = sid_binstring(&group_sid);
- /* search for all users who have that group sid as primary group or as member */
- asprintf(&exp, "(&(objectCategory=user)(|(primaryGroupID=%d)(memberOf=%s)))",
- group_rid, dn);
+ /* search for all members of the group */
+ asprintf(&exp, "(objectSid=%s)",sidstr);
rc = ads_search_retry(ads, &res, exp, attrs);
free(exp);
+ free(sidstr);
+
if (!ADS_ERR_OK(rc)) {
DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
goto done;
@@ -690,29 +768,33 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
goto done;
}
- (*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * count);
- (*name_types) = talloc_zero(mem_ctx, sizeof(uint32) * count);
- (*names) = talloc_zero(mem_ctx, sizeof(char *) * count);
+ members = ads_pull_strings(ads, mem_ctx, res, "member");
+ if (!members) {
+ /* no members? ok ... */
+ status = NT_STATUS_OK;
+ goto done;
+ }
- for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
- uint32 atype, rid;
- DOM_SID sid;
+ /* now we need to turn a list of members into rids, names and name types
+ the problem is that the members are in the form of distinguised names
+ */
+ for (i=0;members[i];i++) /* noop */ ;
+ num_members = i;
- (*names)[*num_names] = ads_pull_string(ads, mem_ctx, msg, "sAMAccountName");
- if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) {
- continue;
- }
- (*name_types)[*num_names] = ads_atype_map(atype);
- if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
- DEBUG(1,("No sid for %s !?\n", (*names)[*num_names]));
- continue;
- }
- if (!sid_peek_rid(&sid, &rid)) {
- DEBUG(1,("No rid for %s !?\n", (*names)[*num_names]));
- continue;
+ (*rid_mem) = talloc_zero(mem_ctx, sizeof(uint32) * num_members);
+ (*name_types) = talloc_zero(mem_ctx, sizeof(uint32) * num_members);
+ (*names) = talloc_zero(mem_ctx, sizeof(char *) * num_members);
+
+ for (i=0;i<num_members;i++) {
+ uint32 name_type, rid;
+ char *name;
+
+ if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &rid)) {
+ (*names)[*num_names] = name;
+ (*name_types)[*num_names] = name_type;
+ (*rid_mem)[*num_names] = rid;
+ (*num_names)++;
}
- (*rid_mem)[*num_names] = rid;
- (*num_names)++;
}
status = NT_STATUS_OK;
@@ -723,6 +805,7 @@ done:
return status;
}
+
/* find the sequence number for a domain */
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 9bd95fdd86..a607727867 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -22,6 +22,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
struct winbind_cache {
struct winbindd_methods *backend;
TDB_CONTEXT *tdb;
@@ -51,7 +54,7 @@ void wcache_flush_cache(void)
if (opt_nocache) return;
wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
- TDB_DEFAULT, O_RDWR | O_CREAT | O_TRUNC, 0600);
+ TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
if (!wcache->tdb) {
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
@@ -205,11 +208,17 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
{
NTSTATUS status;
unsigned time_diff;
+ unsigned cache_time = lp_winbind_cache_time();
+
+ /* trying to reconnect is expensive, don't do it too often */
+ if (domain->sequence_number == DOM_SEQUENCE_NONE) {
+ cache_time *= 8;
+ }
time_diff = time(NULL) - domain->last_seq_check;
/* see if we have to refetch the domain sequence number */
- if (!force && (time_diff < lp_winbind_cache_time())) {
+ if (!force && (time_diff < cache_time)) {
return;
}
@@ -289,8 +298,15 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
centry->sequence_number = centry_uint32(centry);
if (centry_expired(domain, centry)) {
- centry_free(centry);
- return NULL;
+ extern BOOL opt_dual_daemon;
+
+ if (opt_dual_daemon) {
+ extern BOOL backgroud_process;
+ backgroud_process = True;
+ } else {
+ centry_free(centry);
+ return NULL;
+ }
}
return centry;
@@ -410,6 +426,7 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain, NTSTATUS sta
{
struct cache_entry *centry;
uint32 len;
+ fstring uname;
centry = centry_start(domain, status);
if (!centry) return;
@@ -418,7 +435,9 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain, NTSTATUS sta
centry_put_uint32(centry, type);
sid_linearize(centry->data + centry->ofs, len, sid);
centry->ofs += len;
- centry_end(centry, "NS/%s/%s", domain->name, name);
+ fstrcpy(uname, name);
+ strupper(uname);
+ centry_end(centry, "NS/%s/%s", domain->name, uname);
centry_free(centry);
}
@@ -448,7 +467,7 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI
centry_put_string(centry, info->full_name);
centry_put_uint32(centry, info->user_rid);
centry_put_uint32(centry, info->group_rid);
- centry_end(centry, "U/%s/%x", domain->name, info->user_rid);
+ centry_end(centry, "U/%s/%d", domain->name, info->user_rid);
centry_free(centry);
}
@@ -597,10 +616,13 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
+ fstring uname;
if (!cache->tdb) goto do_query;
- centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, name);
+ fstrcpy(uname, name);
+ strupper(uname);
+ centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname);
if (!centry) goto do_query;
*type = centry_uint32(centry);
sid_parse(centry->data + centry->ofs, centry->len - centry->ofs, sid);
@@ -620,6 +642,9 @@ do_query:
/* and save it */
wcache_save_name_to_sid(domain, status, name, sid, *type);
+ /* We can't save the sid to name mapping as we don't know the
+ correct case of the name without looking it up */
+
return status;
}
@@ -636,7 +661,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
NTSTATUS status;
uint32 rid = 0;
- sid_peek_rid(sid, &rid);
+ if (!sid_peek_check_rid(&domain->sid, sid, &rid))
+ return NT_STATUS_INVALID_PARAMETER;
if (!cache->tdb) goto do_query;
@@ -661,6 +687,7 @@ do_query:
/* and save it */
refresh_sequence_number(domain, True);
wcache_save_sid_to_name(domain, status, sid, *name, *type, rid);
+ wcache_save_name_to_sid(domain, status, *name, sid, *type);
return status;
}
@@ -678,7 +705,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
if (!cache->tdb) goto do_query;
- centry = wcache_fetch(cache, domain, "U/%s/%x", domain->name, user_rid);
+ centry = wcache_fetch(cache, domain, "U/%s/%d", domain->name, user_rid);
if (!centry) goto do_query;
info->acct_name = centry_string(centry, mem_ctx);
@@ -719,7 +746,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
if (!cache->tdb) goto do_query;
- centry = wcache_fetch(cache, domain, "UG/%s/%x", domain->name, user_rid);
+ centry = wcache_fetch(cache, domain, "UG/%s/%d", domain->name, user_rid);
if (!centry) goto do_query;
*num_groups = centry_uint32(centry);
@@ -754,7 +781,7 @@ do_query:
for (i=0; i<(*num_groups); i++) {
centry_put_uint32(centry, (*user_gids)[i]);
}
- centry_end(centry, "UG/%s/%x", domain->name, user_rid);
+ centry_end(centry, "UG/%s/%d", domain->name, user_rid);
centry_free(centry);
skip_save:
@@ -775,7 +802,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
if (!cache->tdb) goto do_query;
- centry = wcache_fetch(cache, domain, "GM/%s/%x", domain->name, group_rid);
+ centry = wcache_fetch(cache, domain, "GM/%s/%d", domain->name, group_rid);
if (!centry) goto do_query;
*num_names = centry_uint32(centry);
@@ -824,7 +851,7 @@ do_query:
centry_put_string(centry, (*names)[i]);
centry_put_uint32(centry, (*name_types)[i]);
}
- centry_end(centry, "GM/%s/%x", domain->name, group_rid);
+ centry_end(centry, "GM/%s/%d", domain->name, group_rid);
centry_free(centry);
skip_save:
@@ -878,5 +905,3 @@ struct winbindd_methods cache_methods = {
trusted_domains,
domain_sid
};
-
-
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index ce484795f8..3ab97ed408 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -4,6 +4,7 @@
Winbind daemon connection manager
Copyright (C) Tim Potter 2001
+ Copyright (C) Andrew Bartlett 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -60,6 +61,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* Global list of connections. Initially a DLIST but can become a hash
table or whatever later. */
@@ -348,7 +352,7 @@ static NTSTATUS cm_open_connection(const char *domain,const char *pipe_name,
result = cli_full_connection(&(new_conn->cli), global_myname, new_conn->controller,
&dc_ip, 0, "IPC$",
"IPC", ipc_username, ipc_domain,
- ipc_password, strlen(ipc_password));
+ ipc_password, 0);
SAFE_FREE(ipc_username);
SAFE_FREE(ipc_domain);
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 4ef57513bb..20563ba7bd 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -23,6 +23,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/***************************************************************
Empty static struct for negative caching.
****************************************************************/
@@ -72,7 +75,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
*num_gr_mem = 0;
if (group_name_type != SID_NAME_DOM_GRP) {
- DEBUG(1, ("rid %d in domain %s isn't a " "domain group\n",
+ DEBUG(1, ("rid %d in domain %s isn't a domain group\n",
group_rid, domain->name));
goto done;
}
@@ -81,8 +84,8 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
status = domain->methods->lookup_groupmem(domain, mem_ctx, group_rid, &num_names,
&rid_mem, &names, &name_types);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("could not lookup membership for group rid %d in domain %s\n",
- group_rid, domain->name));
+ DEBUG(1, ("could not lookup membership for group rid %d in domain %s (error: %s)\n",
+ group_rid, domain->name, nt_errstr(status)));
goto done;
}
@@ -228,7 +231,8 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
}
/* Fill in group structure */
- sid_peek_rid(&group_sid, &group_rid);
+ if (!sid_peek_check_rid(&domain->sid, &group_sid, &group_rid))
+ return WINBINDD_ERROR;
if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) {
DEBUG(1, ("error converting unix gid to sid\n"));
@@ -359,8 +363,10 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
/* Create a state record for this domain */
if ((domain_state = (struct getent_state *)
- malloc(sizeof(struct getent_state))) == NULL)
+ malloc(sizeof(struct getent_state))) == NULL) {
+ DEBUG(1, ("winbindd_setgrent: malloc failed for domain_state!\n"));
return WINBINDD_ERROR;
+ }
ZERO_STRUCTP(domain_state);
@@ -407,8 +413,10 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
return False;
if (!(mem_ctx = talloc_init_named("get_sam_group_entries(%s)",
- ent->domain_name)))
+ ent->domain_name))) {
+ DEBUG(1, ("get_sam_group_entries: could not create talloc context!\n"));
return False;
+ }
/* Free any existing group info */
@@ -431,6 +439,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
&sam_grp_entries);
if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("get_sam_group_entries: could not enumerate domain groups! Error: %s", nt_errstr(status)));
result = False;
goto done;
}
@@ -571,14 +580,21 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state)
goto done;
}
- /* Get group membership */
+ group_list[group_list_ndx].num_gr_mem = 0;
+ gr_mem = NULL;
+ gr_mem_len = 0;
- result = fill_grent_mem(
- domain,
- name_list[ent->sam_entry_index].rid,
- SID_NAME_DOM_GRP,
- &group_list[group_list_ndx].num_gr_mem,
- &gr_mem, &gr_mem_len);
+ /* Get group membership */
+ if (state->request.cmd == WINBINDD_GETGRLST) {
+ result = True;
+ } else {
+ result = fill_grent_mem(
+ domain,
+ name_list[ent->sam_entry_index].rid,
+ SID_NAME_DOM_GRP,
+ &group_list[group_list_ndx].num_gr_mem,
+ &gr_mem, &gr_mem_len);
+ }
}
if (result) {
diff --git a/source3/nsswitch/winbindd_idmap.c b/source3/nsswitch/winbindd_idmap.c
index bae61449ee..6d184fec5f 100644
--- a/source3/nsswitch/winbindd_idmap.c
+++ b/source3/nsswitch/winbindd_idmap.c
@@ -22,6 +22,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* High water mark keys */
#define HWM_GROUP "GROUP HWM"
@@ -364,6 +367,7 @@ fail:
static BOOL idmap_convert(const char *idmap_name)
{
int32 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
+ BOOL bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False;
if (vers == IDMAP_VERSION)
return True;
@@ -374,28 +378,34 @@ static BOOL idmap_convert(const char *idmap_name)
return False;
#endif
- if (IREV(vers) == IDMAP_VERSION) {
- /* Arrggghh ! Bytereversed - make order independent ! */
+ if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) {
+ /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
+ /*
+ * high and low records were created on a
+ * big endian machine and will need byte-reversing.
+ */
+
int32 wm;
wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
- if (wm != -1)
+ if (wm != -1) {
wm = IREV(wm);
- else
+ } else
wm = server_state.uid_low;
- if (tdb_store_int32(idmap_tdb, HWM_USER, server_state.uid_low) == -1) {
+ if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
DEBUG(0, ("idmap_convert: Unable to byteswap user hwm in idmap database\n"));
return False;
}
wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
- if (wm != -1)
+ if (wm != -1) {
wm = IREV(wm);
- else
+ } else
wm = server_state.gid_low;
- if (tdb_store_int32(idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) {
+
+ if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n"));
return False;
}
@@ -404,7 +414,7 @@ static BOOL idmap_convert(const char *idmap_name)
/* the old format stored as DOMAIN/rid - now we store the SID direct */
tdb_traverse(idmap_tdb, convert_fn, NULL);
- if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
+ if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n"));
return False;
}
diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c
index 5678bdaa5a..45f2d42f98 100644
--- a/source3/nsswitch/winbindd_misc.c
+++ b/source3/nsswitch/winbindd_misc.c
@@ -23,6 +23,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
extern pstring global_myname;
/************************************************************************
@@ -88,9 +91,15 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
"good" : "bad"));
done:
- state->response.data.num_entries = NT_STATUS_V(result);
+ state->response.data.auth.nt_status = NT_STATUS_V(result);
+ fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
+ fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
+ state->response.data.auth.pam_error = nt_status_to_pam(result);
- return WINBINDD_OK;
+ DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n",
+ state->response.data.auth.nt_status_string));
+
+ return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index 023d72306b..0f0e40a2ec 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -99,6 +99,9 @@ enum winbindd_cmd {
WINBINDD_WINS_BYIP,
WINBINDD_WINS_BYNAME,
+ /* this is like GETGRENT but gives an empty group list */
+ WINBINDD_GETGRLST,
+
/* Placeholder for end of cmd list */
WINBINDD_NUM_CMDS
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index f7959c2feb..e608f826c9 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -24,6 +24,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* Return a password structure from a username. */
enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h
index f3830cd63c..ef44fb655e 100644
--- a/source3/nsswitch/winbindd_proto.h
+++ b/source3/nsswitch/winbindd_proto.h
@@ -6,7 +6,9 @@
/* The following definitions come from nsswitch/winbindd.c */
-int main(int argc, char **argv);
+void winbind_process_packet(struct winbindd_cli_state *state);
+void winbind_client_read(struct winbindd_cli_state *state);
+int winbind_setup_common(void);
/* The following definitions come from nsswitch/winbindd_ads.c */
@@ -39,6 +41,13 @@ NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
struct cli_state **cli);
void winbindd_cm_status(void);
+/* The following definitions come from nsswitch/winbindd_dual.c */
+
+int dual_select_setup(fd_set *fds, int maxfd);
+void dual_select(fd_set *fds);
+void dual_send_request(struct winbindd_cli_state *state);
+void do_dual_daemon(void);
+
/* The following definitions come from nsswitch/winbindd_group.c */
enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state);
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index d0d97cae49..2bb0e8c49f 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -23,6 +23,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* Query display info for a domain. This returns enough information plus a
bit extra to give an overview of domain users for the User Manager
application. */
@@ -38,6 +41,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
int i;
+ DEBUG(3,("rpc: query_user_list\n"));
+
*num_entries = 0;
*info = NULL;
@@ -130,6 +135,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
*num_entries = 0;
*info = NULL;
+ DEBUG(3,("rpc: enum_dom_groups\n"));
+
if (!(hnd = cm_get_sam_handle(domain->name))) {
return NT_STATUS_UNSUCCESSFUL;
}
@@ -189,6 +196,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
uint32 *types = NULL;
const char *full_name;
+ DEBUG(3,("rpc: name_to_sid name=%s\n", name));
+
if (!(mem_ctx = talloc_init_named("name_to_sid[rpc] for [%s]\\[%s]", domain->name, name))) {
DEBUG(0, ("talloc_init failed!\n"));
return NT_STATUS_NO_MEMORY;
@@ -210,7 +219,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1,
&full_name, &sids, &types);
- /* Return rid and type if lookup successful */
+ /* Return rid and type if lookup successful */
+
if (NT_STATUS_IS_OK(status)) {
sid_copy(sid, &sids[0]);
*type = types[0];
@@ -235,6 +245,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
uint32 *types;
NTSTATUS status;
+ DEBUG(3,("rpc: sid_to_name\n"));
+
if (!(hnd = cm_get_lsa_handle(domain->name)))
return NT_STATUS_UNSUCCESSFUL;
@@ -267,6 +279,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
BOOL got_dom_pol = False, got_user_pol = False;
SAM_USERINFO_CTR *ctr;
+ DEBUG(3,("rpc: query_user rid=%u\n", user_rid));
+
/* Get sam handle */
if (!(hnd = cm_get_sam_handle(domain->name)))
goto done;
@@ -295,6 +309,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol,
0x15, &ctr);
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
cli_samr_close(hnd->cli, mem_ctx, &user_pol);
got_user_pol = False;
@@ -329,6 +346,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
DOM_GID *user_groups;
int i;
+ DEBUG(3,("rpc: lookup_usergroups rid=%u\n", user_rid));
+
*num_groups = 0;
/* First try cached universal groups from logon */
@@ -400,6 +419,8 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
BOOL got_dom_pol = False, got_group_pol = False;
+ DEBUG(3,("rpc: lookup_groupmem rid=%u\n", group_rid));
+
*num_names = 0;
/* Get sam handle */
@@ -502,6 +523,8 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
BOOL got_dom_pol = False;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ DEBUG(3,("rpc: sequence_number\n"));
+
*seq = DOM_SEQUENCE_NONE;
if (!(mem_ctx = talloc_init_named("sequence_number[rpc]")))
@@ -557,6 +580,9 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
CLI_POLICY_HND *hnd;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
uint32 enum_ctx = 0;
+ uint32 pref_num_domains = 5;
+
+ DEBUG(3,("rpc: trusted_domains\n"));
*num_domains = 0;
@@ -564,8 +590,8 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
goto done;
result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
- &hnd->pol, &enum_ctx, num_domains,
- names, dom_sids);
+ &hnd->pol, &enum_ctx, &pref_num_domains,
+ num_domains, names, dom_sids);
done:
return result;
}
@@ -578,6 +604,8 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
CLI_POLICY_HND *hnd;
fstring level5_dom;
+ DEBUG(3,("rpc: domain_sid\n"));
+
if (!(mem_ctx = talloc_init_named("domain_sid[rpc]")))
return NT_STATUS_NO_MEMORY;
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
index a41bf75916..372898a08a 100644
--- a/source3/nsswitch/winbindd_sid.c
+++ b/source3/nsswitch/winbindd_sid.c
@@ -21,7 +21,9 @@
*/
#include "winbindd.h"
-#include "sids.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
/* Convert a string */
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index d89717ad47..55593d6ae5 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -23,6 +23,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* Fill a pwent structure with information we have obtained */
static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 06804b3b43..d5668a2bb6 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -22,7 +22,9 @@
*/
#include "winbindd.h"
-#include "sids.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
/**
* @file winbindd_util.c
@@ -164,9 +166,6 @@ BOOL init_domain_list(void)
DEBUG(1,("Added domain %s (%s)\n",
domain->name,
sid_string_static(&domain->sid)));
-
- /* this primes the connection */
- cache_methods.domain_sid(domain, &domain->sid);
}
}
diff --git a/source3/nsswitch/winbindd_wins.c b/source3/nsswitch/winbindd_wins.c
index af624170eb..8f9a7414bd 100644
--- a/source3/nsswitch/winbindd_wins.c
+++ b/source3/nsswitch/winbindd_wins.c
@@ -23,6 +23,9 @@
#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
/* Use our own create socket code so we don't recurse.... */
static int wins_lookup_open_socket_in(void)
@@ -84,25 +87,18 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count)
{
int fd;
struct in_addr *ret = NULL;
- struct in_addr p;
- int j;
+ int j, flags = 0;
*count = 0;
- fd = wins_lookup_open_socket_in();
- if (fd == -1)
- return NULL;
-
- p = wins_srv_ip();
- if( !is_zero_ip(p) ) {
- ret = name_query(fd,name,0x20,False,True, p, count);
- goto out;
+ /* always try with wins first */
+ if (resolve_wins(name,0x20,&ret,count)) {
+ return ret;
}
- if (lp_wins_support()) {
- /* we are our own WINS server */
- ret = name_query(fd,name,0x20,False,True, *interpret_addr2("127.0.0.1"), count);
- goto out;
+ fd = wins_lookup_open_socket_in();
+ if (fd == -1) {
+ return NULL;
}
/* uggh, we have to broadcast to each interface in turn */
@@ -110,12 +106,10 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count)
j >= 0;
j--) {
struct in_addr *bcast = iface_n_bcast(j);
- ret = name_query(fd,name,0x20,True,True,*bcast,count);
+ ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL);
if (ret) break;
}
- out:
-
close(fd);
return ret;
}
diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c
index 2133f817d1..9bb2d6755c 100644
--- a/source3/nsswitch/wins.c
+++ b/source3/nsswitch/wins.c
@@ -80,14 +80,10 @@ static void nss_wins_init(void)
DEBUGLEVEL = 0;
AllowDebugChange = False;
- /* needed for lp_xx() functions */
- charset_initialise();
-
TimeInit();
setup_logging("nss_wins",False);
lp_load(dyn_CONFIGFILE,True,False,False);
load_interfaces();
- codepage_initialise(lp_client_code_page());
}
static struct node_status *lookup_byaddr_backend(char *addr, int *count)
@@ -115,10 +111,10 @@ static struct node_status *lookup_byaddr_backend(char *addr, int *count)
static struct in_addr *lookup_byname_backend(const char *name, int *count)
{
- int fd;
+ int fd = -1;
struct in_addr *ret = NULL;
struct in_addr p;
- int j;
+ int j, flags = 0;
if (!initialised) {
nss_wins_init();
@@ -126,33 +122,24 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count)
*count = 0;
- fd = wins_lookup_open_socket_in();
- if (fd == -1)
- return NULL;
-
- p = wins_srv_ip();
- if( !is_zero_ip(p) ) {
- ret = name_query(fd,name,0x20,False,True, p, count);
- goto out;
+ /* always try with wins first */
+ if (resolve_wins(name,0x20,&ret,count)) {
+ return ret;
}
- if (lp_wins_support()) {
- /* we are our own WINS server */
- ret = name_query(fd,name,0x20,False,True, *interpret_addr2("127.0.0.1"), count);
- goto out;
+ fd = wins_lookup_open_socket_in();
+ if (fd == -1) {
+ return NULL;
}
/* uggh, we have to broadcast to each interface in turn */
- for (j=iface_count() - 1;
- j >= 0;
- j--) {
+ for (j=iface_count() - 1;j >= 0;j--) {
struct in_addr *bcast = iface_n_bcast(j);
- ret = name_query(fd,name,0x20,True,True,*bcast,count);
+ ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL);
if (ret) break;
}
- out:
-
+out:
close(fd);
return ret;
}
@@ -319,5 +306,19 @@ _nss_wins_gethostbyname_r(const char *name, struct hostent *he,
return NSS_STATUS_SUCCESS;
}
-#endif
+
+NSS_STATUS
+_nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he,
+ char *buffer, size_t buflen, int *errnop,
+ int *h_errnop)
+{
+ if(af!=AF_INET) {
+ *h_errnop = NO_DATA;
+ *errnop = EAFNOSUPPORT;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ return _nss_wins_gethostbyname_r(name,he,buffer,buflen,errnop,h_errnop);
+}
+#endif