summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/config.h.in2
-rw-r--r--source3/lib/util_unistr.c17
-rw-r--r--source3/nsswitch/winbindd.h24
-rw-r--r--source3/nsswitch/winbindd_cm.c2
-rw-r--r--source3/nsswitch/winbindd_proto.h4
-rw-r--r--source3/nsswitch/winbindd_user.c83
-rw-r--r--source3/nsswitch/winbindd_util.c47
7 files changed, 112 insertions, 67 deletions
diff --git a/source3/include/config.h.in b/source3/include/config.h.in
index 930eee6084..635c634e11 100644
--- a/source3/include/config.h.in
+++ b/source3/include/config.h.in
@@ -1,4 +1,4 @@
-/* include/config.h.in. Generated automatically from configure.in by autoheader. */
+/* include/config.h.in. Generated automatically from configure.in by autoheader 2.13. */
/* Define if on AIX 3.
System headers sometimes define this.
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c
index d2d23dafa5..fc29ca8dc2 100644
--- a/source3/lib/util_unistr.c
+++ b/source3/lib/util_unistr.c
@@ -165,6 +165,23 @@ void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
/*******************************************************************
+ duplicate a UNISTR2 string into a null terminated char*
+ using a talloc context
+********************************************************************/
+char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str)
+{
+ char *s;
+ int maxlen = (str->uni_str_len+1)*4;
+ if (!str->buffer) return NULL;
+ s = (char *)talloc(ctx, maxlen); /* convervative */
+ if (!s) return NULL;
+ pull_ucs2(NULL, s, str->buffer, maxlen, str->uni_str_len*2,
+ STR_NOALIGN);
+ return s;
+}
+
+
+/*******************************************************************
Return a number stored in a buffer
********************************************************************/
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 1380d5cc88..c4a7c82bc6 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -77,11 +77,33 @@ struct winbindd_state {
extern struct winbindd_state server_state; /* Server information */
-/* Structures to hold per domain information */
+typedef struct {
+ char *acct_name;
+ char *full_name;
+ uint32 user_rid;
+ uint32 group_rid; /* primary group */
+} WINBIND_DISPINFO;
+
+/* per-domain methods. This is how LDAP vs RPC is selected
+ This will eventually be the sole entry point to all the methods,
+ I'm just starting small
+ */
+struct winbindd_methods {
+ NTSTATUS (*query_dispinfo)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 *start_ndx, uint32 *num_entries,
+ WINBIND_DISPINFO **info);
+
+};
+
+/* Structures to hold per domain information */
struct winbindd_domain {
fstring name; /* Domain name */
DOM_SID sid; /* SID for this domain */
+ struct winbindd_methods *methods; /* lookup methods for
+ this domain (LDAP or
+ RPC) */
struct winbindd_domain *prev, *next; /* Linked list info */
};
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index f11d86d4c1..987b28e09c 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -73,7 +73,7 @@ struct winbindd_cm_conn {
POLICY_HND pol;
};
-struct winbindd_cm_conn *cm_conns = NULL;
+static struct winbindd_cm_conn *cm_conns = NULL;
/* Get a domain controller name. Cache positive and negative lookups so we
don't go to the network too often when something is badly broken. */
diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h
index 7c3326ce36..fc8377697a 100644
--- a/source3/nsswitch/winbindd_proto.h
+++ b/source3/nsswitch/winbindd_proto.h
@@ -152,8 +152,8 @@ void free_getent_state(struct getent_state *state);
BOOL winbindd_param_init(void);
NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32 *start_ndx, uint16 info_level,
- uint32 *num_entries, SAM_DISPINFO_CTR *ctr);
+ uint32 *start_ndx, uint32 *num_entries,
+ WINBIND_DISPINFO **info);
BOOL check_domain_env(char *domain_env, char *domain);
void parse_domain_user(char *domuser, fstring domain, fstring user);
#endif /* _PROTO_H_ */
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 853350fd19..2cc64cb565 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -377,12 +377,11 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
{
NTSTATUS status;
uint32 num_entries;
- SAM_DISPINFO_1 info1;
- SAM_DISPINFO_CTR ctr;
+ WINBIND_DISPINFO *info;
struct getpwent_user *name_list = NULL;
- uint32 group_rid;
BOOL result = False;
TALLOC_CTX *mem_ctx;
+ struct winbindd_methods *methods;
if (ent->got_all_sam_entries)
return False;
@@ -390,10 +389,7 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
if (!(mem_ctx = talloc_init()))
return False;
- ZERO_STRUCT(info1);
- ZERO_STRUCT(ctr);
-
- ctr.sam.info1 = &info1;
+ methods = ent->domain->methods;
#if 0
/* Look in cache for entries, else get them direct */
@@ -406,14 +402,6 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
}
#endif
- /* For the moment we set the primary group for every user to be the
- Domain Users group. There are serious problems with determining
- the actual primary group for large domains. This should really
- be made into a 'winbind force group' smb.conf parameter or
- something like that. */
-
- group_rid = DOMAIN_GROUP_RID_USERS;
-
/* Free any existing user info */
SAFE_FREE(ent->sam_entries);
@@ -426,9 +414,9 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
num_entries = 0;
- status = winbindd_query_dispinfo(ent->domain, mem_ctx,
- &ent->dispinfo_ndx, 1,
- &num_entries, &ctr);
+ status = methods->query_dispinfo(ent->domain, mem_ctx,
+ &ent->dispinfo_ndx,
+ &num_entries, &info);
if (num_entries) {
struct getpwent_user *tnl;
@@ -447,26 +435,23 @@ static BOOL get_sam_user_entries(struct getent_state *ent)
}
for (i = 0; i < num_entries; i++) {
-
/* Store account name and gecos */
-
- unistr2_to_ascii(
- name_list[ent->num_sam_entries + i].name,
- &info1.str[i].uni_acct_name,
- sizeof(fstring));
-
- unistr2_to_ascii(
- name_list[ent->num_sam_entries + i].gecos,
- &info1.str[i].uni_full_name,
- sizeof(fstring));
+ if (!info[i].acct_name) {
+ fstrcpy(name_list[ent->num_sam_entries + i].name, "");
+ } else {
+ fstrcpy(name_list[ent->num_sam_entries + i].name,
+ info[i].acct_name);
+ }
+ if (!info[i].full_name) {
+ fstrcpy(name_list[ent->num_sam_entries + i].gecos, "");
+ } else {
+ fstrcpy(name_list[ent->num_sam_entries + i].gecos,
+ info[i].full_name);
+ }
/* User and group ids */
-
- name_list[ent->num_sam_entries + i].user_rid =
- info1.sam[i].rid_user;
-
- name_list[ent->num_sam_entries + i].
- group_rid = group_rid;
+ name_list[ent->num_sam_entries+i].user_rid = info[i].user_rid;
+ name_list[ent->num_sam_entries+i].group_rid = info[i].group_rid;
}
ent->num_sam_entries += num_entries;
@@ -615,8 +600,7 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state)
enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state)
{
struct winbindd_domain *domain;
- SAM_DISPINFO_CTR ctr;
- SAM_DISPINFO_1 info1;
+ WINBIND_DISPINFO *info;
uint32 num_entries = 0, total_entries = 0;
char *ted, *extra_data = NULL;
int extra_data_len = 0;
@@ -630,14 +614,13 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state)
/* Enumerate over trusted domains */
- ctr.sam.info1 = &info1;
-
if (domain_list == NULL)
get_domain_info();
for (domain = domain_list; domain; domain = domain->next) {
NTSTATUS status;
uint32 start_ndx = 0;
+ struct winbindd_methods *methods;
/* Skip domains other than WINBINDD_DOMAIN environment
variable */
@@ -646,20 +629,20 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state)
!check_domain_env(state->request.domain, domain->name))
continue;
+ methods = domain->methods;
+
/* Query display info */
do {
int i;
- status = winbindd_query_dispinfo(
- domain, mem_ctx, &start_ndx,
- 1, &num_entries, &ctr);
+ status = methods->query_dispinfo(domain, mem_ctx, &start_ndx,
+ &num_entries, &info);
if (num_entries == 0)
continue;
/* Allocate some memory for extra data */
-
total_entries += num_entries;
ted = Realloc(extra_data, sizeof(fstring) *
@@ -675,26 +658,22 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state)
/* Pack user list into extra data fields */
for (i = 0; i < num_entries; i++) {
- UNISTR2 *uni_acct_name;
fstring acct_name, name;
- /* Convert unistring to ascii */
-
- uni_acct_name = &ctr.sam.info1->str[i].
- uni_acct_name;
- unistr2_to_ascii(acct_name, uni_acct_name,
- sizeof(acct_name) - 1);
+ if (!info[i].acct_name) {
+ fstrcpy(acct_name, "");
+ } else {
+ fstrcpy(acct_name, info[i].acct_name);
+ }
slprintf(name, sizeof(name) - 1, "%s%s%s",
domain->name, lp_winbind_separator(),
acct_name);
/* Append to extra data */
-
memcpy(&extra_data[extra_data_len], name,
strlen(name));
extra_data_len += strlen(name);
-
extra_data[extra_data_len++] = ',';
}
} while (NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES));
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 777b3cdac2..41eb8b9d28 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -40,9 +40,12 @@ static const fstring name_deadbeef = "<deadbeef>";
/* Globals for domain list stuff */
-
struct winbindd_domain *domain_list = NULL;
+static struct winbindd_methods msrpc_methods = {
+ winbindd_query_dispinfo
+};
+
/* Given a domain name, return the struct winbindd domain info for it
if it is actually working. */
@@ -89,7 +92,8 @@ struct winbindd_domain *find_domain_from_sid(DOM_SID *sid)
/* Add a trusted domain to our list of domains */
static struct winbindd_domain *add_trusted_domain(char *domain_name,
- DOM_SID *domain_sid)
+ DOM_SID *domain_sid,
+ struct winbindd_methods *methods)
{
struct winbindd_domain *domain, *tmp;
@@ -112,7 +116,8 @@ static struct winbindd_domain *add_trusted_domain(char *domain_name,
ZERO_STRUCTP(domain);
fstrcpy(domain->name, domain_name);
sid_copy(&domain->sid, domain_sid);
-
+ domain->methods = methods;
+
/* Link to domain list */
DLIST_ADD(domain_list, domain);
@@ -150,7 +155,7 @@ BOOL get_domain_info(void)
if (!NT_STATUS_IS_OK(result))
goto done;
- add_trusted_domain(lp_workgroup(), &domain_sid);
+ add_trusted_domain(lp_workgroup(), &domain_sid, &msrpc_methods);
/* Enumerate list of trusted domains */
@@ -166,7 +171,7 @@ BOOL get_domain_info(void)
/* Add each domain to the trusted domain list */
for(i = 0; i < num_doms; i++)
- add_trusted_domain(domains[i], &sids[i]);
+ add_trusted_domain(domains[i], &sids[i], &msrpc_methods);
rv = True;
@@ -790,14 +795,17 @@ BOOL winbindd_param_init(void)
NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32 *start_ndx, uint16 info_level,
- uint32 *num_entries, SAM_DISPINFO_CTR *ctr)
+ uint32 *start_ndx, uint32 *num_entries,
+ WINBIND_DISPINFO **info)
{
CLI_POLICY_HND *hnd;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
POLICY_HND dom_pol;
BOOL got_dom_pol = False;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+ SAM_DISPINFO_CTR ctr;
+ SAM_DISPINFO_1 info1;
+ int i;
/* Get sam handle */
@@ -814,11 +822,30 @@ NTSTATUS winbindd_query_dispinfo(struct winbindd_domain *domain,
got_dom_pol = True;
- /* Query display info */
+ ctr.sam.info1 = &info1;
+ /* Query display info level 1 */
result = cli_samr_query_dispinfo(hnd->cli, mem_ctx,
- &dom_pol, start_ndx, info_level,
- num_entries, 0xffff, ctr);
+ &dom_pol, start_ndx, 1,
+ num_entries, 0xffff, &ctr);
+
+ /* now map the result into the WINBIND_DISPINFO structure */
+ (*info) = (WINBIND_DISPINFO *)talloc(mem_ctx, (*num_entries)*sizeof(WINBIND_DISPINFO));
+ if (!(*info)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0;i<*num_entries;i++) {
+ (*info)[i].acct_name = unistr2_tdup(mem_ctx, &info1.str[i].uni_acct_name);
+ (*info)[i].full_name = unistr2_tdup(mem_ctx, &info1.str[i].uni_full_name);
+ (*info)[i].user_rid = info1.sam[i].rid_user;
+ /* For the moment we set the primary group for every user to be the
+ Domain Users group. There are serious problems with determining
+ the actual primary group for large domains. This should really
+ be made into a 'winbind force group' smb.conf parameter or
+ something like that. */
+ (*info)[i].group_rid = DOMAIN_GROUP_RID_USERS;
+ }
done: