mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
The beginnings of alternative backends for winbindd
This just splits off the dispinfo call behind a methods structure.
I'll split off a few more functions soon, then we will be ready for
LDAP replacement methods
(This used to be commit 0216b0fca1
)
This commit is contained in:
parent
c5f4a4b9ad
commit
de744cb970
@ -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.
|
||||
|
@ -164,6 +164,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
|
||||
********************************************************************/
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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_ */
|
||||
|
@ -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));
|
||||
|
@ -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:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user