summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/LDAP/samba.schema25
-rw-r--r--source3/include/smbldap.h6
-rw-r--r--source3/lib/smbldap.c38
-rw-r--r--source3/passdb/passdb.c2
-rw-r--r--source3/passdb/pdb_ldap.c780
-rw-r--r--source3/sam/idmap_ldap.c855
-rw-r--r--source3/sam/idmap_util.c7
-rw-r--r--source3/smbd/server.c20
-rw-r--r--source3/utils/pdbedit.c6
9 files changed, 745 insertions, 994 deletions
diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema
index 067f5a497d..6e8387f16e 100644
--- a/examples/LDAP/samba.schema
+++ b/examples/LDAP/samba.schema
@@ -276,6 +276,16 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.22 NAME 'sambaNextGroupRid'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+attributetype ( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid'
+ DESC 'Next NT rid to give out for anything'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase'
+ DESC 'Base at which the samba RID generation algorithm should operate'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
#######################################################################
## objectClasses used by Samba 3.0 schema ##
@@ -312,16 +322,23 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY
##
objectclass ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL
DESC 'Samba Domain Information'
- MUST ( sambaDomainName $ sambaNextGroupRid $ sambaNextUserRid $
- sambaSID ) )
+ MUST ( sambaDomainName $
+ sambaSID )
+ MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $
+ sambaAlgorithmicRidBase ) )
## used for idmap_ldap module
objectclass ( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' SUP top AUXILIARY
DESC 'Pool for allocating UNIX uids/gids'
MUST ( uidNumber $ gidNumber ) )
-objectclass ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top STRUCTURAL
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIARY
DESC 'Mapping from a SID to an ID'
MUST ( sambaSID )
- MAY ( uidNumber $ gidNumber ))
+ MAY ( uidNumber $ gidNumber ) )
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL
+ DESC 'Structural Class for a SID'
+ MUST ( sambaSID ) )
diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h
index 5f3606aa32..589d01aa6d 100644
--- a/source3/include/smbldap.h
+++ b/source3/include/smbldap.h
@@ -37,6 +37,7 @@
#define LDAP_OBJ_DOMINFO "sambaDomain"
#define LDAP_OBJ_IDPOOL "sambaUnixIdPool"
#define LDAP_OBJ_IDMAP_ENTRY "sambaIdmapEntry"
+#define LDAP_OBJ_SID_ENTRY "sambaSidEntry"
#define LDAP_OBJ_ACCOUNT "account"
#define LDAP_OBJ_POSIXACCOUNT "posixAccount"
@@ -85,7 +86,8 @@
#define LDAP_ATTR_GROUP_SID 30
#define LDAP_ATTR_GROUP_TYPE 31
#define LDAP_ATTR_SID 32
-
+#define LDAP_ATTR_ALGORITHMIC_RID_BASE 33
+#define LDAP_ATTR_NEXT_RID 34
typedef struct _attrib_map_entry {
int attrib;
@@ -113,6 +115,8 @@ void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, con
void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
LDAPMod ***mods,
const char *attribute, const char *newval);
+BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
+ const char *attribute, pstring value);
/**
* Struct to keep the state for all the ldap stuff
diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c
index 8401787317..f65860d1b8 100644
--- a/source3/lib/smbldap.c
+++ b/source3/lib/smbldap.c
@@ -102,9 +102,11 @@ ATTRIB_MAP_ENTRY attrib_map_v30[] = {
ATTRIB_MAP_ENTRY dominfo_attr_list[] = {
{ LDAP_ATTR_DOMAIN, "sambaDomainName" },
+ { LDAP_ATTR_NEXT_RID, "sambaNextRid" },
{ LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" },
{ LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" },
{ LDAP_ATTR_DOM_SID, LDAP_ATTRIBUTE_SID },
+ { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"},
{ LDAP_ATTR_LIST_END, NULL },
};
@@ -271,6 +273,40 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
return True;
}
+/*******************************************************************
+search an attribute and return the first value found.
+******************************************************************/
+ BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
+ const char *attribute, pstring value)
+{
+ char **values;
+
+ if ( !attribute )
+ return False;
+
+ value[0] = '\0';
+
+ if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
+ DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute));
+
+ return False;
+ }
+
+ if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1)
+ {
+ DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
+ attribute, values[0]));
+ ldap_value_free(values);
+ return False;
+ }
+
+ ldap_value_free(values);
+#ifdef DEBUG_PASSWORDS
+ DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));
+#endif
+ return True;
+}
+
/************************************************************************
Routine to manage the LDAPMod structure array
manage memory used by the array, by each struct, and values
@@ -819,7 +855,7 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
return NT_STATUS_OK;
}
-static int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts)
+int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts)
{
int rc;
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index ece4a1e057..54a852601a 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -581,7 +581,7 @@ BOOL pdb_gethexpwd(const char *p, unsigned char *pwd)
return (True);
}
-static int algorithmic_rid_base(void)
+int algorithmic_rid_base(void)
{
static int rid_offset = 0;
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index ec164a7e7b..6911cea369 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -216,8 +216,6 @@ static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
pstring filter;
int rc;
- /* check if the user rid exists, if not, try searching on the uid */
-
snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid,
get_objclass_filter(ldap_state->schema_ver));
@@ -237,8 +235,6 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
int rc;
fstring sid_string;
- /* check if the user rid exsists, if not, try searching on the uid */
-
snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)",
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
sid_to_string(sid_string, sid),
@@ -250,40 +246,6 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
}
/*******************************************************************
-search an attribute and return the first value found.
-******************************************************************/
-static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
- const char *attribute, pstring value)
-{
- char **values;
-
- if ( !attribute )
- return False;
-
- value[0] = '\0';
-
- if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
- DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
-
- return False;
- }
-
- if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1)
- {
- DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n",
- attribute, values[0]));
- ldap_value_free(values);
- return False;
- }
-
- ldap_value_free(values);
-#ifdef DEBUG_PASSWORDS
- DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
-#endif
- return True;
-}
-
-/*******************************************************************
Delete complete object or objectclass and attrs from
object found in search_result depending on lp_ldap_delete_dn
******************************************************************/
@@ -368,167 +330,6 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
}
/**********************************************************************
-Search for the domain info entry
-*********************************************************************/
-static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state,
- LDAPMessage ** result)
-{
- pstring filter;
- int rc;
- char **attr_list;
-
- snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
- LDAP_OBJ_DOMINFO,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- ldap_state->domain_name);
-
- DEBUG(2, ("Searching for:[%s]\n", filter));
-
-
- attr_list = get_attr_list( dominfo_attr_list );
- rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
- attr_list , result);
- free_attr_list( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
- DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
- }
-
- return rc;
-}
-
-/**********************************************************************
- If this entry is is the 'allocated' range, extract the RID and return
- it, so we can find the 'next' rid to allocate.
-
- Do this, no matter what type of object holds the RID - be it a user,
- group or somthing else.
-*********************************************************************/
-static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type)
-{
- pstring sid_string;
- DOM_SID dom_sid;
- uint32 rid;
-
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
- LDAP_ATTRIBUTE_SID, sid_string))
- {
- return 0;
- }
-
- if (!string_to_sid(&dom_sid, sid_string)) {
- return 0;
- }
-
- if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) {
- /* not our domain, so we don't care */
- return 0;
- }
-
- switch (rid_type) {
- case USER_RID_TYPE:
- if (rid >= ldap_state->low_allocated_user_rid &&
- rid <= ldap_state->high_allocated_user_rid) {
- return rid;
- }
- break;
- case GROUP_RID_TYPE:
- if (rid >= ldap_state->low_allocated_group_rid &&
- rid <= ldap_state->high_allocated_group_rid) {
- return rid;
- }
- break;
- }
- return 0;
-}
-
-
-/**********************************************************************
-Connect to LDAP server and find the next available 'allocated' RID.
-
-The search is done 'per type' as we allocate seperate pools for the
-EVEN and ODD (user and group) RIDs.
-
-This is only done once, so that we can fill out the sambaDomain.
-*********************************************************************/
-static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type)
-{
- int rc;
- LDAPMessage *result;
- LDAPMessage *entry;
- uint32 top_rid = 0;
- uint32 next_rid;
- uint32 count;
- uint32 rid;
- char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
- fstring filter;
-
- snprintf( filter, sizeof(filter)-1, "(%s=*)", LDAP_ATTRIBUTE_SID );
-
- DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter));
-
- rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
- sid_attr, &result);
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
- DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
-
- result = NULL;
- return 0;
- }
-
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
- DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count));
-
- if (count == 0) {
- DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc)));
- DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
- } else {
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,result);
-
- top_rid = entry_to_rid(ldap_state, entry, rid_type);
-
- while ((entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, entry))) {
-
- rid = entry_to_rid(ldap_state, entry, rid_type);
- if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) {
- top_rid = rid;
- }
- }
- }
-
- switch (rid_type) {
- case USER_RID_TYPE:
- if (top_rid < ldap_state->low_allocated_user_rid) {
- return ldap_state->low_allocated_user_rid;
- }
- break;
- case GROUP_RID_TYPE:
- if (top_rid < ldap_state->low_allocated_group_rid)
- return ldap_state->low_allocated_group_rid;
- break;
- }
-
- next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER;
-
- switch (rid_type) {
- case USER_RID_TYPE:
- if (next_rid > ldap_state->high_allocated_user_rid) {
- return 0;
- }
- break;
- case GROUP_RID_TYPE:
- if (next_rid > ldap_state->high_allocated_group_rid) {
- return 0;
- }
- break;
- }
- return next_rid;
-}
-
-/**********************************************************************
Add the sambaDomain to LDAP, so we don't have to search for this stuff
again. This is a once-add operation for now.
@@ -536,7 +337,8 @@ static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int
*********************************************************************/
static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
{
- pstring tmp;
+ fstring sid_string;
+ fstring algorithmic_rid_base_string;
pstring filter, dn;
LDAPMod **mods = NULL;
int rc;
@@ -545,22 +347,9 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
int num_result;
char **attr_list;
- uint32 next_allocated_user_rid;
- uint32 next_allocated_group_rid;
-
- next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE);
- if (!next_allocated_user_rid) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE);
- if (!next_allocated_group_rid) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- ldap_state->domain_name, LDAP_OBJ_DOMINFO);
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ ldap_state->domain_name, LDAP_OBJ_DOMINFO);
attr_list = get_attr_list( dominfo_attr_list );
rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
@@ -582,6 +371,7 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
/* Check if we need to add an entry */
DEBUG(3,("Adding new domain\n"));
ldap_op = LDAP_MOD_ADD;
+
snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
ldap_state->domain_name, lp_ldap_suffix());
@@ -592,15 +382,15 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
ldap_state->domain_name);
- sid_to_string(tmp, &ldap_state->domain_sid);
- smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), tmp);
-
- snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid);
- smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), tmp);
+ /* If we don't have an entry, then ask secrets.tdb for what it thinks.
+ It may choose to make it up */
- snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid);
- smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), tmp);
+ sid_to_string(sid_string, get_global_sam_sid());
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string);
+ slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base());
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ algorithmic_rid_base_string);
smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
switch(ldap_op)
@@ -637,7 +427,59 @@ static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state)
}
/**********************************************************************
- Even if the sambaAccount attribute in LDAP tells us that this RID is
+Search for the domain info entry
+*********************************************************************/
+static NTSTATUS ldapsam_search_domain_info(struct ldapsam_privates *ldap_state,
+ LDAPMessage ** result, BOOL try_add)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ pstring filter;
+ int rc;
+ char **attr_list;
+ int count;
+
+ snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
+ LDAP_OBJ_DOMINFO,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ ldap_state->domain_name);
+
+ DEBUG(2, ("Searching for:[%s]\n", filter));
+
+
+ attr_list = get_attr_list( dominfo_attr_list );
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+ attr_list , result);
+ free_attr_list( attr_list );
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
+ DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
+ } else if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, *result) < 1) {
+ DEBUG(3, ("Got no domain info entries for domain %s\n",
+ ldap_state->domain_name));
+ ldap_msgfree(*result);
+ *result = NULL;
+ if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) {
+ return ldapsam_search_domain_info(ldap_state, result, False);
+ } else {
+ DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret)));
+ return ret;
+ }
+ } else if ((count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, *result)) > 1) {
+ DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
+ count, ldap_state->domain_name));
+ ldap_msgfree(*result);
+ *result = NULL;
+ return ret;
+ } else {
+ return NT_STATUS_OK;
+ }
+
+ return ret;
+}
+
+/**********************************************************************
+ Even if the sambaDomain attribute in LDAP tells us that this RID is
safe to use, always check before use.
*********************************************************************/
static BOOL sid_in_use(struct ldapsam_privates *ldap_state,
@@ -689,15 +531,17 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
int rc;
- LDAPMessage *result = NULL;
+ LDAPMessage *domain_result = NULL;
LDAPMessage *entry = NULL;
char *dn;
LDAPMod **mods = NULL;
- int count;
fstring old_rid_string;
fstring next_rid_string;
+ fstring algorithmic_rid_base_string;
uint32 next_rid;
+ uint32 alg_rid_base;
int attempts = 0;
+ char *ld_error = NULL;
if ( ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT ) {
DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n",
@@ -707,100 +551,129 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri
while (attempts < 10)
{
- char *ld_error;
- if (ldapsam_search_domain_info(ldap_state, &result)) {
- return ret;
- }
-
- if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) < 1) {
- DEBUG(3, ("Got no domain info entries for domain %s\n",
- ldap_state->domain_name));
- ldap_msgfree(result);
- if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) {
- continue;
- } else {
- DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret)));
- return ret;
- }
- }
-
- if ((count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result)) > 1) {
- DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
- count, ldap_state->domain_name));
- ldap_msgfree(result);
+ if (!NT_STATUS_IS_OK(ret = ldapsam_search_domain_info(ldap_state, &domain_result, True))) {
return ret;
}
-
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, domain_result);
if (!entry) {
- ldap_msgfree(result);
+ DEBUG(0, ("Could not get domain info entry\n"));
+ ldap_msgfree(domain_result);
return ret;
}
if ((dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry)) == NULL) {
DEBUG(0, ("Could not get domain info DN\n"));
- ldap_msgfree(result);
+ ldap_msgfree(domain_result);
return ret;
}
- /* yes, we keep 2 seperate counters, to avoid stomping on the two
+ /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and
+ algorithmic_rid_base. The other two are to avoid stomping on the
different sets of algorithmic RIDs */
-
- switch (rid_type) {
- case USER_RID_TYPE:
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
- old_rid_string))
- {
- ldap_memfree(dn);
- ldap_msgfree(result);
- return ret;
- }
- break;
- case GROUP_RID_TYPE:
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
- old_rid_string))
- {
- ldap_memfree(dn);
- ldap_msgfree(result);
- return ret;
- }
- break;
+
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ algorithmic_rid_base_string))
+ {
+
+ alg_rid_base = (uint32)atol(algorithmic_rid_base_string);
+ } else {
+ alg_rid_base = algorithmic_rid_base();
+ /* Try to make the modification atomically by enforcing the
+ old value in the delete mod. */
+ slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ algorithmic_rid_base_string);
}
- /* This is the core of the whole routine. If we had
- scheme-style closures, there would be a *lot* less code
- duplication... */
- *rid = (uint32)atol(old_rid_string);
- next_rid = *rid+RID_MULTIPLIER;
+ next_rid = 0;
- slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
+ if (alg_rid_base > BASE_RID) {
+ /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we
+ can allocate to new users */
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
+ old_rid_string))
+ {
+ *rid = (uint32)atol(old_rid_string);
+ } else {
+ *rid = BASE_RID;
+ }
- switch (rid_type) {
- case USER_RID_TYPE:
- if (next_rid > ldap_state->high_allocated_user_rid) {
+ next_rid = *rid+1;
+ if (next_rid >= alg_rid_base) {
return NT_STATUS_UNSUCCESSFUL;
}
-
+
+ slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
+
/* Try to make the modification atomically by enforcing the
old value in the delete mod. */
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
- next_rid_string);
- break;
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
+ next_rid_string);
+ }
- case GROUP_RID_TYPE:
- if (next_rid > ldap_state->high_allocated_group_rid) {
- return NT_STATUS_UNSUCCESSFUL;
+ if (!next_rid) { /* not got one already */
+ switch (rid_type) {
+ case USER_RID_TYPE:
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
+ old_rid_string))
+ {
+
+ *rid = (uint32)atol(old_rid_string);
+
+ } else {
+ *rid = ldap_state->low_allocated_user_rid;
+ }
+ break;
+ case GROUP_RID_TYPE:
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
+ old_rid_string))
+ {
+ *rid = (uint32)atol(old_rid_string);
+ } else {
+ *rid = ldap_state->low_allocated_group_rid;
+ }
+ break;
}
+
+ /* This is the core of the whole routine. If we had
+ scheme-style closures, there would be a *lot* less code
+ duplication... */
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
- next_rid_string);
- break;
+ next_rid = *rid+RID_MULTIPLIER;
+ slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
+
+ switch (rid_type) {
+ case USER_RID_TYPE:
+ if (next_rid > ldap_state->high_allocated_user_rid) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Try to make the modification atomically by enforcing the
+ old value in the delete mod. */
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
+ next_rid_string);
+ break;
+
+ case GROUP_RID_TYPE:
+ if (next_rid > ldap_state->high_allocated_group_rid) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Try to make the modification atomically by enforcing the
+ old value in the delete mod. */
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
+ next_rid_string);
+ break;
+ }
}
if ((rc = ldap_modify_s(ldap_state->smbldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
@@ -809,27 +682,27 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri
pstring domain_sid_string;
int error = 0;
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, result,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, domain_result,
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
domain_sid_string))
{
ldap_mods_free(mods, True);
ldap_memfree(dn);
- ldap_msgfree(result);
+ ldap_msgfree(domain_result);
return ret;
}
if (!string_to_sid(&dom_sid, domain_sid_string)) {
ldap_mods_free(mods, True);
ldap_memfree(dn);
- ldap_msgfree(result);
+ ldap_msgfree(domain_result);
return ret;
}
ldap_mods_free(mods, True);
mods = NULL;
ldap_memfree(dn);
- ldap_msgfree(result);
+ ldap_msgfree(domain_result);
sid_copy(&sid, &dom_sid);
sid_append_rid(&sid, *rid);
@@ -845,8 +718,9 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri
return NT_STATUS_OK;
}
+ ld_error = NULL;
ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(2, ("Failed to modify rid: %s\n", ld_error));
+ DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL"));
SAFE_FREE(ld_error);
ldap_mods_free(mods, True);
@@ -855,8 +729,8 @@ static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *ri
ldap_memfree(dn);
dn = NULL;
- ldap_msgfree(result);
- result = NULL;
+ ldap_msgfree(domain_result);
+ domain_result = NULL;
{
/* Sleep for a random timeout */
@@ -905,13 +779,13 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
}
ldap_value_free(ldap_values);
- if ( !get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) )
{
return False;
}
- if ( !get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
{
return False;
@@ -989,7 +863,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
return False;
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
DEBUG(1, ("No uid attribute found for this user!\n"));
return False;
}
@@ -1009,13 +883,13 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT )
{
- if (get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp))
{
pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
}
- if (get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp))
{
pdb_set_group_sid_from_string(sampass, temp, PDB_SET);
@@ -1029,14 +903,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
}
else
{
- if (get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp))
{
user_rid = (uint32)atol(temp);
pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp))
{
pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
@@ -1083,7 +957,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
}
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp))
{
/* leave as default */
@@ -1092,7 +966,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp))
{
/* leave as default */
@@ -1101,7 +975,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_logon_time(sampass, logon_time, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp))
{
/* leave as default */
@@ -1110,7 +984,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp))
{
/* leave as default */
@@ -1119,7 +993,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp))
{
/* leave as default */
@@ -1128,7 +1002,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp))
{
/* leave as default */
@@ -1143,10 +1017,10 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
* that fits your needs; using cn then displayName rather than 'userFullName'
*/
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname))
{
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname))
{
/* leave as default */
@@ -1157,7 +1031,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_fullname(sampass, fullname, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive))
{
pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
@@ -1169,7 +1043,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir))
{
pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
@@ -1181,7 +1055,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_homedir(sampass, homedir, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script))
{
pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
@@ -1193,7 +1067,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_logon_script(sampass, logon_script, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path))
{
pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
@@ -1205,7 +1079,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_profile_path(sampass, profile_path, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc))
{
/* leave as default */
@@ -1213,7 +1087,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations))
{
/* leave as default */;
@@ -1227,7 +1101,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
hours_len = 21;
memset(hours, 0xff, hours_len);
- if (!get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp))
{
/* leave as default */
@@ -1239,7 +1113,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
ZERO_STRUCT(smblmpwd);
}
- if (!get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp))
{
/* leave as default */
@@ -1251,7 +1125,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
ZERO_STRUCT(smbntpwd);
}
- if (!get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp))
{
acct_ctrl |= ACB_NORMAL;
@@ -1346,10 +1220,10 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
switch ( ldap_state->schema_ver )
{
case SCHEMAVER_SAMBAACCOUNT:
- if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) {
+ if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
sid_to_string(sid_string, user_sid),
- sid_to_string(dom_sid_string, get_global_sam_sid())));
+ sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
return False;
}
slprintf(temp, sizeof(temp) - 1, "%i", rid);
@@ -1382,10 +1256,10 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
switch ( ldap_state->schema_ver )
{
case SCHEMAVER_SAMBAACCOUNT:
- if (!sid_peek_check_rid(get_global_sam_sid(), group_sid, &rid)) {
+ if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
sid_to_string(sid_string, group_sid),
- sid_to_string(dom_sid_string, get_global_sam_sid())));
+ sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
return False;
}
@@ -1637,48 +1511,59 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
return ret;
}
-/**********************************************************************
-Get SAM_ACCOUNT entry from LDAP by SID
-*********************************************************************/
-static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
+static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
+ const DOM_SID *sid, LDAPMessage **result)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
- LDAPMessage *result;
- LDAPMessage *entry;
- fstring sid_string;
- int count;
- int rc;
+ int rc = -1;
char ** attr_list;
-
switch ( ldap_state->schema_ver )
{
case SCHEMAVER_SAMBASAMACCOUNT:
attr_list = get_userattr_list(ldap_state->schema_ver);
- rc = ldapsam_search_suffix_by_sid(ldap_state, sid, &result, attr_list);
+ rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
free_attr_list( attr_list );
if ( rc != LDAP_SUCCESS )
- return NT_STATUS_NO_SUCH_USER;
+ return rc;
break;
case SCHEMAVER_SAMBAACCOUNT:
{
uint32 rid;
- if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
- return NT_STATUS_NO_SUCH_USER;
+ if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
+ return rc;
}
attr_list = get_userattr_list(ldap_state->schema_ver);
- rc = ldapsam_search_suffix_by_rid(ldap_state, rid, &result, attr_list );
+ rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
free_attr_list( attr_list );
if ( rc != LDAP_SUCCESS )
- return NT_STATUS_NO_SUCH_USER;
+ return rc;
}
break;
}
-
+ return rc;
+}
+
+/**********************************************************************
+Get SAM_ACCOUNT entry from LDAP by SID
+*********************************************************************/
+static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *result;
+ LDAPMessage *entry;
+ int count;
+ int rc;
+ fstring sid_string;
+
+ rc = ldapsam_get_ldap_user_by_sid(ldap_state,
+ sid, &result);
+ if (rc != LDAP_SUCCESS)
+ return NT_STATUS_NO_SUCH_USER;
+
count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
if (count < 1)
@@ -1737,7 +1622,9 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
switch(ldap_op)
{
case LDAP_MOD_ADD:
- smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_ACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ "objectclass",
+ LDAP_OBJ_ACCOUNT);
rc = smbldap_add(ldap_state->smbldap_state,
dn, mods);
break;
@@ -1746,7 +1633,8 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
dn ,mods);
break;
default:
- DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
+ DEBUG(0,("Wrong LDAP operation type: %d!\n",
+ ldap_op));
return NT_STATUS_INVALID_PARAMETER;
}
@@ -1979,7 +1867,9 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
char **attr_list;
char *escape_user;
const char *username = pdb_get_username(newpwd);
+ const DOM_SID *sid = pdb_get_user_sid(newpwd);
pstring filter;
+ fstring sid_string;
if (!username || !*username) {
DEBUG(0, ("Cannot add user without a username!\n"));
@@ -1987,8 +1877,8 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
}
/* free this list after the second search or in case we exit on failure */
-
attr_list = get_userattr_list(ldap_state->schema_ver);
+
rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
if (rc != LDAP_SUCCESS) {
@@ -2004,9 +1894,24 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
return NT_STATUS_UNSUCCESSFUL;
}
ldap_msgfree(result);
+ result = NULL;
+
+ if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
+ rc = ldapsam_get_ldap_user_by_sid(ldap_state,
+ sid, &result);
+ if (rc == LDAP_SUCCESS) {
+ if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
+ DEBUG(0,("SID '%s' already in the base, with samba attributes\n",
+ sid_to_string(sid_string, sid)));
+ free_attr_list( attr_list );
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ ldap_msgfree(result);
+ }
+ }
/* does the entry already exist but without a samba rttibutes?
- we don't really care what attributes are returned here */
+ we need to return the samba attributes here */
escape_user = escape_ldap_string_alloc( username );
pstrcpy( filter, lp_ldap_filter() );
@@ -2015,15 +1920,16 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
rc = smbldap_search_suffix(ldap_state->smbldap_state,
filter, attr_list, &result);
- free_attr_list( attr_list );
-
- if ( rc != LDAP_SUCCESS )
+ if ( rc != LDAP_SUCCESS ) {
+ free_attr_list( attr_list );
return NT_STATUS_UNSUCCESSFUL;
+ }
num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
if (num_result > 1) {
DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
+ free_attr_list( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2038,15 +1944,57 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
slprintf (dn, sizeof (dn) - 1, "%s", tmp);
ldap_memfree (tmp);
- } else {
+
+ } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
+
+ /* There might be a SID for this account already - say an idmap entry */
+
+ snprintf(filter, sizeof(filter)-1, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))",
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
+ sid_to_string(sid_string, sid),
+ LDAP_OBJ_IDMAP_ENTRY,
+ LDAP_OBJ_SID_ENTRY);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state,
+ filter, attr_list, &result);
+ free_attr_list( attr_list );
+
+ if ( rc != LDAP_SUCCESS ) {
+ free_attr_list( attr_list );
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+
+ if (num_result > 1) {
+ DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
+ free_attr_list( attr_list );
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Check if we need to update an existing entry */
+ if (num_result == 1) {
+ char *tmp;
+
+ DEBUG(3,("User exists without samba attributes: adding them\n"));
+ ldap_op = LDAP_MOD_REPLACE;
+ entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
+ tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
+ slprintf (dn, sizeof (dn) - 1, "%s", tmp);
+ ldap_memfree (tmp);
+ }
+ }
+
+ if (num_result == 0) {
/* Check if we need to add an entry */
DEBUG(3,("Adding new user\n"));
ldap_op = LDAP_MOD_ADD;
if (username[strlen(username)-1] == '$') {
- slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
- } else {
- slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
- }
+ slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
+ } else {
+ slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
+ }
}
if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
@@ -2090,21 +2038,6 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
}
/**********************************************************************
- Housekeeping
- *********************************************************************/
-
-static void free_private_data(void **vp)
-{
- struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
-
- smbldap_free_struct(&(*ldap_state)->smbldap_state);
-
- *ldap_state = NULL;
-
- /* No need to free any further, as it is talloc()ed */
-}
-
-/**********************************************************************
*********************************************************************/
static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
@@ -2154,7 +2087,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
return False;
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp))
{
DEBUG(0, ("Mandatory attribute %s not found\n",
@@ -2165,7 +2098,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
map->gid = (gid_t)atol(temp);
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp))
{
DEBUG(0, ("Mandatory attribute %s not found\n",
@@ -2174,7 +2107,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
}
string_to_sid(&map->sid, temp);
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp))
{
DEBUG(0, ("Mandatory attribute %s not found\n",
@@ -2189,11 +2122,11 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
return False;
}
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp))
{
temp[0] = '\0';
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp))
{
DEBUG(0, ("Attributes cn not found either "
@@ -2203,7 +2136,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
}
fstrcpy(map->nt_name, temp);
- if (!get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp))
{
temp[0] = '\0';
@@ -2333,13 +2266,18 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
const char *name)
{
pstring filter;
+ char *escape_name = escape_ldap_string_alloc(name);
- /* TODO: Escaping of name? */
+ if (!escape_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
LDAP_OBJ_GROUPMAP,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), name,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), name);
+ get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
+ get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name);
+
+ SAFE_FREE(escape_name);
return ldapsam_getgroup(methods, filter, map);
}
@@ -2651,6 +2589,21 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
}
/**********************************************************************
+ Housekeeping
+ *********************************************************************/
+
+static void free_private_data(void **vp)
+{
+ struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
+
+ smbldap_free_struct(&(*ldap_state)->smbldap_state);
+
+ *ldap_state = NULL;
+
+ /* No need to free any further, as it is talloc()ed */
+}
+
+/**********************************************************************
Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
*********************************************************************/
@@ -2700,8 +2653,6 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
return NT_STATUS_NO_MEMORY;
}
- sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
-
(*pdb_method)->private_data = ldap_state;
(*pdb_method)->free_private_data = free_private_data;
@@ -2743,6 +2694,8 @@ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **
ldap_state = (*pdb_method)->private_data;
ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
+ sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
+
return NT_STATUS_OK;
}
@@ -2754,8 +2707,15 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
+ uint32 alg_rid_base;
+ pstring alg_rid_base_string;
uint32 low_idmap_uid, high_idmap_uid;
uint32 low_idmap_gid, high_idmap_gid;
+ LDAPMessage *result;
+ LDAPMessage *entry;
+ DOM_SID ldap_domain_sid;
+ DOM_SID secrets_domain_sid;
+ pstring domain_sid_string;
if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
return nt_status;
@@ -2767,6 +2727,52 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
ldap_state->permit_non_unix_accounts = False;
+ /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
+
+ if (!NT_STATUS_IS_OK(nt_status = ldapsam_search_domain_info(ldap_state, &result, True))) {
+ DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n"));
+ DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, and will risk BDCs having inconsistant SIDs\n"));
+ sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
+ return NT_STATUS_OK;
+ }
+
+ /* Given that the above might fail, everything below this must be optional */
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ if (!entry) {
+ DEBUG(0, ("Could not get domain info entry\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
+ domain_sid_string))
+ {
+ BOOL found_sid;
+ string_to_sid(&ldap_domain_sid, domain_sid_string);
+ found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
+ if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
+ /* reset secrets.tdb sid */
+ secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
+ }
+ sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
+ }
+
+ if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ alg_rid_base_string))
+ {
+ alg_rid_base = (uint32)atol(alg_rid_base_string);
+ if (alg_rid_base != algorithmic_rid_base()) {
+ DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
+ "database was initialised. Aborting. \n"));
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ ldap_msgfree(result);
+
/* check for non-unix account ranges */
if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid)
diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c
index b31ce18925..2dccaf04f7 100644
--- a/source3/sam/idmap_ldap.c
+++ b/source3/sam/idmap_ldap.c
@@ -39,463 +39,23 @@
struct ldap_idmap_state {
- LDAP *ldap_struct;
- time_t last_ping;
- char *uri;
- char *bind_dn;
- char *bind_secret;
- unsigned int num_failures;
- struct ldap_idmap_state *prev, *next;
+ struct smbldap_state *smbldap_state;
+ TALLOC_CTX *mem_ctx;
+
+ /* struct ldap_idmap_state *prev, *next; */
};
-#define LDAP_IDMAP_DONT_PING_TIME 10 /* ping only all 10 seconds */
#define LDAP_MAX_ALLOC_ID 128 /* number tries while allocating
new id */
static struct ldap_idmap_state ldap_state;
-static int ldap_idmap_connect_system(struct ldap_idmap_state *state);
static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type);
+static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, int id_type,
+ const char *ldap_dn, LDAPMessage *entry);
static NTSTATUS ldap_idmap_close(void);
-/*******************************************************************
- open a connection to the ldap server.
-******************************************************************/
-static int ldap_idmap_open_connection(struct ldap_idmap_state *state)
-{
- int rc = LDAP_SUCCESS;
- int version;
- BOOL ldap_v3 = False;
-
-#ifdef HAVE_LDAP_INITIALIZE
- DEBUG(10, ("ldap_idmap_open_connection: %s\n", state->uri));
-
- if ((rc = ldap_initialize(&state->ldap_struct, state->uri))
- != LDAP_SUCCESS) {
- DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
- return rc;
- }
-#else
- /* Parse the string manually */
- {
- int port = 0;
- fstring protocol;
- fstring host;
- const char *p = state->uri;
- SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
-
- /* skip leading "URL:" (if any) */
- if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
- p += 4;
- }
-
- sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
-
- if (port == 0) {
- if (strequal(protocol, "ldap")) {
- port = LDAP_PORT;
- } else if (strequal(protocol, "ldaps")) {
- port = LDAPS_PORT;
- } else {
- DEBUG(0, ("unrecognised protocol (%s)!\n",
- protocol));
- }
- }
-
- if ((state->ldap_struct = ldap_init(host, port)) == NULL) {
- DEBUG(0, ("ldap_init failed !\n"));
- return LDAP_OPERATIONS_ERROR;
- }
-
- if (strequal(protocol, "ldaps")) {
-#ifdef LDAP_OPT_X_TLS
- int tls = LDAP_OPT_X_TLS_HARD;
- if (ldap_set_option (state->ldap_struct,
- LDAP_OPT_X_TLS, &tls) !=
- LDAP_SUCCESS)
- {
- DEBUG(0, ("Failed to setup a TLS session\n"));
- }
-
- DEBUG(3,("LDAPS option set...!\n"));
-#else
- DEBUG(0,("ldap_idmap_open_connection: Secure "
- "connection not supported by LDAP client "
- "libraries!\n"));
- return LDAP_OPERATIONS_ERROR;
-#endif
- }
- }
-#endif
-
- if (ldap_get_option(state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
- &version) == LDAP_OPT_SUCCESS) {
- if (version != LDAP_VERSION3) {
- version = LDAP_VERSION3;
- if (ldap_set_option(state->ldap_struct,
- LDAP_OPT_PROTOCOL_VERSION,
- &version) == LDAP_OPT_SUCCESS) {
- ldap_v3 = True;
- }
- } else {
- ldap_v3 = True;
- }
- }
-
- if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
-#ifdef LDAP_OPT_X_TLS
- if (ldap_v3) {
- if ((rc = ldap_start_tls_s(state->ldap_struct, NULL,
- NULL)) != LDAP_SUCCESS) {
- DEBUG(0,("Failed to issue the StartTLS "
- "instruction: %s\n",
- ldap_err2string(rc)));
- return rc;
- }
- DEBUG (3, ("StartTLS issued: using a TLS "
- "connection\n"));
- } else {
-
- DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
- return LDAP_OPERATIONS_ERROR;
- }
-#else
- DEBUG(0,("ldap_idmap_open_connection: StartTLS not supported by "
- "LDAP client libraries!\n"));
- return LDAP_OPERATIONS_ERROR;
-#endif
- }
-
- DEBUG(2, ("ldap_idmap_open_connection: connection opened\n"));
- return rc;
-}
-
-/**********************************************************************
-Connect to LDAP server
-*********************************************************************/
-static int ldap_idmap_open(struct ldap_idmap_state *state)
-{
- int rc;
- SMB_ASSERT(state);
-
-#ifndef NO_LDAP_SECURITY
- if (geteuid() != 0) {
- DEBUG(0,
- ("ldap_idmap_open: cannot access LDAP when not root\n"));
- return LDAP_INSUFFICIENT_ACCESS;
- }
-#endif
-
- if ((state->ldap_struct != NULL) &&
- ((state->last_ping + LDAP_IDMAP_DONT_PING_TIME)<time(NULL))) {
- struct sockaddr_un addr;
- socklen_t len = sizeof(addr);
- int sd;
-
- if (!ldap_get_option(state->ldap_struct, LDAP_OPT_DESC, &sd)&&
- getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
- /* the other end has died. reopen. */
- ldap_unbind_ext(state->ldap_struct, NULL, NULL);
- state->ldap_struct = NULL;
- state->last_ping = (time_t)0;
- } else {
- state->last_ping = time(NULL);
- }
- }
-
- if (state->ldap_struct != NULL) {
- DEBUG(5,("ldap_idmap_open: already connected to the LDAP "
- "server\n"));
- return LDAP_SUCCESS;
- }
-
- if ((rc = ldap_idmap_open_connection(state))) {
- return rc;
- }
-
- if ((rc = ldap_idmap_connect_system(state))) {
- ldap_unbind_ext(state->ldap_struct, NULL, NULL);
- state->ldap_struct = NULL;
- return rc;
- }
-
-
- state->last_ping = time(NULL);
- DEBUG(4,("The LDAP server is succesful connected\n"));
-
- return LDAP_SUCCESS;
-}
-
-/*******************************************************************
-******************************************************************/
-
-static int ldap_idmap_retry_open(struct ldap_idmap_state *state, int *attempts)
-{
- int rc;
-
- SMB_ASSERT(state && attempts);
-
- if (*attempts != 0) {
- unsigned int sleep_time;
- uint8 rand_byte = 128; /* a reasonable place to start */
-
- generate_random_buffer(&rand_byte, 1, False);
-
- sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2;
- /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
- on average.
- */
- DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
- sleep_time));
- msleep(sleep_time);
- }
- (*attempts)++;
-
- if ((rc = ldap_idmap_open(state))) {
- DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",
- *attempts));
- return rc;
- }
-
- return LDAP_SUCCESS;
-}
-
-/*******************************************************************
- a rebind function for authenticated referrals
- This version takes a void* that we can shove useful stuff in :-)
-******************************************************************/
-
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-#else
-static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
- int *methodp, int freeit, void *arg)
-{
- struct ldap_idmap_state *state = arg;
-
- /** @TODO Should we be doing something to check what servers we rebind
- to? Could we get a referral to a machine that we don't want to
- give our username and password to? */
-
- if (freeit) {
- SAFE_FREE(*whop);
- memset(*credp, '\0', strlen(*credp));
- SAFE_FREE(*credp);
- } else {
- DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
- state->bind_dn));
-
- *whop = strdup(state->bind_dn);
- if (!*whop) {
- return LDAP_NO_MEMORY;
- }
- *credp = strdup(state->bind_secret);
- if (!*credp) {
- SAFE_FREE(*whop);
- return LDAP_NO_MEMORY;
- }
- *methodp = LDAP_AUTH_SIMPLE;
- }
- return 0;
-}
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- a rebind function for authenticated referrals
- This version takes a void* that we can shove useful stuff in :-)
- and actually does the connection.
-******************************************************************/
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-static int rebindproc_connect_with_state (LDAP *ldap_struct,
- LDAP_CONST char *url,
- ber_tag_t request,
- ber_int_t msgid, void *arg)
-{
- struct ldap_idmap_state *state = arg;
- int rc;
- DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
- state->bind_dn));
-
- /** @TODO Should we be doing something to check what servers we rebind
- to? Could we get a referral to a machine that we don't want to
- give our username and password to? */
-
- rc = ldap_simple_bind_s(ldap_struct, state->bind_dn,
- state->bind_secret);
-
- return rc;
-}
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- Add a rebind function for authenticated referrals
-******************************************************************/
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-#else
-# if LDAP_SET_REBIND_PROC_ARGS == 2
-static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
- int *method, int freeit )
-{
- return rebindproc_with_state(ldap_struct, whop, credp,
- method, freeit, &ldap_state);
-
-}
-# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- a rebind function for authenticated referrals
- this also does the connection, but no void*.
-******************************************************************/
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-# if LDAP_SET_REBIND_PROC_ARGS == 2
-static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
- ber_int_t msgid)
-{
- return rebindproc_connect_with_state(ld, url, (ber_tag_t)request,
- msgid, &ldap_state);
-}
-# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
-/*******************************************************************
- connect to the ldap server under system privilege.
-******************************************************************/
-static int ldap_idmap_connect_system(struct ldap_idmap_state *state)
-{
- int rc;
- char *ldap_dn;
- char *ldap_secret;
-
- /* get the password */
- if (!fetch_ldap_pw(&ldap_dn, &ldap_secret))
- {
- DEBUG(0, ("ldap_idmap_connect_system: Failed to retrieve "
- "password from secrets.tdb\n"));
- return LDAP_INVALID_CREDENTIALS;
- }
-
- state->bind_dn = ldap_dn;
- state->bind_secret = ldap_secret;
-
- /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
- (OpenLDAP) doesnt' seem to support it */
-
- DEBUG(10,("ldap_idmap_connect_system: Binding to ldap server %s as "
- "\"%s\"\n", state->uri, ldap_dn));
-
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-# if LDAP_SET_REBIND_PROC_ARGS == 2
- ldap_set_rebind_proc(state->ldap_struct, &rebindproc_connect);
-# endif
-# if LDAP_SET_REBIND_PROC_ARGS == 3
- ldap_set_rebind_proc(state->ldap_struct,
- &rebindproc_connect_with_state, (void *)state);
-# endif
-#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-# if LDAP_SET_REBIND_PROC_ARGS == 2
- ldap_set_rebind_proc(state->ldap_struct, &rebindproc);
-# endif
-# if LDAP_SET_REBIND_PROC_ARGS == 3
- ldap_set_rebind_proc(state->ldap_struct, &rebindproc_with_state,
- (void *)state);
-# endif
-#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
-
- rc = ldap_simple_bind_s(state->ldap_struct, ldap_dn, ldap_secret);
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(state->num_failures ? 2 : 0,
- ("failed to bind to server with dn= %s Error: "
- "%s\n\t%s\n",
- ldap_dn ? ld_error : "(unknown)",
- ldap_err2string(rc), ld_error));
- SAFE_FREE(ld_error);
- state->num_failures++;
- return rc;
- }
-
- state->num_failures = 0;
-
- DEBUG(3, ("ldap_idmap_connect_system: succesful connection to the "
- "LDAP server\n"));
- return rc;
-}
-
-/*****************************************************************************
- wrapper around ldap_search()
-*****************************************************************************/
-
-static int ldap_idmap_search(struct ldap_idmap_state *state,
- const char *base, int scope, const char *filter,
- char *attrs[], int attrsonly,
- LDAPMessage **res)
-{
- int rc = LDAP_SERVER_DOWN;
- int attempts = 0;
- char *utf8_filter;
-
- SMB_ASSERT(state);
-
- if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
- return LDAP_NO_MEMORY;
- }
-
- while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
- if ((rc = ldap_idmap_retry_open(state, &attempts)) !=
- LDAP_SUCCESS) continue;
-
- rc = ldap_search_s(state->ldap_struct, base, scope,
- utf8_filter, (char**)attrs, attrsonly, res);
- }
-
- if (rc == LDAP_SERVER_DOWN) {
- DEBUG(0,("ldap_idmap_search: LDAP server is down!\n"));
- ldap_idmap_close();
- }
-
- SAFE_FREE(utf8_filter);
- return rc;
-}
-
-/***********************************************************************
- search an attribute and return the first value found.
-***********************************************************************/
-
-static BOOL ldap_idmap_attribute (struct ldap_idmap_state *state,
- LDAPMessage * entry,
- const char *attribute, pstring value)
-{
- char **values;
- value[0] = '\0';
-
- if ( !entry )
- return False;
-
- if ((values = ldap_get_values (state->ldap_struct, entry, attribute)) == NULL)
- {
- DEBUG(10,("get_single_attribute: [%s] = [<does not exist>]\n",
- attribute));
- return False;
- }
-
- if (convert_string(CH_UTF8, CH_UNIX,
- values[0], -1,
- value, sizeof(pstring)) == (size_t)-1)
- {
- DEBUG(1, ("ldap_idmap_attribute: string conversion of [%s] = "
- "[%s] failed!\n", attribute, values[0]));
- ldap_value_free(values);
- return False;
- }
- ldap_value_free(values);
-
- return True;
-}
-
/*****************************************************************************
Allocate a new uid or gid
*****************************************************************************/
@@ -505,8 +65,8 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
int rc = LDAP_SERVER_DOWN;
int count = 0;
- LDAPMessage *result = 0;
- LDAPMessage *entry = 0;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
pstring id_str, new_id_str;
LDAPMod **mods = NULL;
const char *type;
@@ -525,7 +85,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
attr_list = get_attr_list( idpool_attr_list );
- rc = ldap_idmap_search(&ldap_state, lp_ldap_idmap_suffix(),
+ rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
LDAP_SCOPE_SUBTREE, filter,
attr_list, 0, &result);
free_attr_list( attr_list );
@@ -535,16 +95,16 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
goto out;
}
- count = ldap_count_entries(ldap_state.ldap_struct, result);
+ count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
if (count != 1) {
DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL));
goto out;
}
- dn = ldap_get_dn(ldap_state.ldap_struct, result);
- entry = ldap_first_entry(ldap_state.ldap_struct, result);
+ dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
- if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) {
+ if (!smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) {
DEBUG(0,("ldap_allocate_id: %s attribute not found\n",
type));
goto out;
@@ -578,7 +138,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str );
smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str );
- rc = ldap_modify_s(ldap_state.ldap_struct, dn, mods);
+ rc = ldap_modify_s(ldap_state.smbldap_state->ldap_struct, dn, mods);
ldap_memfree(dn);
ldap_mods_free( mods, True );
@@ -600,12 +160,14 @@ out:
static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
{
- LDAPMessage *result = 0;
- LDAPMessage *entry = 0;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ fstring id_str;
pstring sid_str;
pstring filter;
pstring suffix;
const char *type;
+ const char *obj_class;
int rc;
int count;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
@@ -615,49 +177,48 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
if ( id_type & ID_USERID ) {
type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
- snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))",
- LDAP_OBJ_SAMBASAMACCOUNT, type, id.uid );
+ obj_class = LDAP_OBJ_SAMBASAMACCOUNT;
+ snprintf(id_str, sizeof(id_str), "%u", id.uid );
pstrcpy( suffix, lp_ldap_suffix());
}
else {
type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
- snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))",
- LDAP_OBJ_GROUPMAP, type, id.gid );
+ obj_class = LDAP_OBJ_GROUPMAP;
+ snprintf(id_str, sizeof(id_str), "%u", id.gid );
pstrcpy( suffix, lp_ldap_group_suffix() );
}
attr_list = get_attr_list( sidmap_attr_list );
- rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE,
- filter, attr_list, 0, &result);
+ snprintf(filter, sizeof(filter), "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))",
+ LDAP_OBJ_IDMAP_ENTRY, obj_class, type, id_str);
+
+ rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
+ filter, attr_list, 0, &result);
if (rc != LDAP_SUCCESS)
goto out;
- count = ldap_count_entries(ldap_state.ldap_struct, result);
+ count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
/* fall back to looking up an idmap entry if we didn't find and
actual user or group */
if (count == 0) {
+ ldap_msgfree(result);
+ result = NULL;
+
snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))",
LDAP_OBJ_IDMAP_ENTRY, type, ((id_type & ID_USERID) ? id.uid : id.gid));
-#if 0 /* commented out for now -- jerry */
- if ( id_type & ID_USERID )
- snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_USER_SUFFIX, lp_ldap_idmap_suffix() );
- else
- snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_GROUP_SUFFIX, lp_ldap_idmap_suffix() );
-#else
pstrcpy( suffix, lp_ldap_idmap_suffix() );
-#endif
- rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE,
+ rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
filter, attr_list, 0, &result);
if (rc != LDAP_SUCCESS)
goto out;
- count = ldap_count_entries(ldap_state.ldap_struct, result);
+ count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
}
if (count != 1) {
@@ -666,9 +227,9 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
goto out;
}
- entry = ldap_first_entry(ldap_state.ldap_struct, result);
+ entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
- if ( !ldap_idmap_attribute(&ldap_state, entry, LDAP_ATTRIBUTE_SID, sid_str) )
+ if ( !smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) )
goto out;
if (!string_to_sid(sid, sid_str))
@@ -678,6 +239,9 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
out:
free_attr_list( attr_list );
+ if (result)
+ ldap_msgfree(result);
+
return ret;
}
@@ -687,68 +251,74 @@ out:
static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
{
- LDAPMessage *result = 0;
- LDAPMessage *entry = 0;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
pstring sid_str;
pstring filter;
pstring id_str;
- pstring suffix;
+ const char *suffix;
const char *type;
const char *obj_class;
+ const char *posix_obj_class;
int rc;
int count;
char **attr_list;
+ char *dn = NULL;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
/* first try getting the mapping from a samba user or group */
+ sid_to_string(sid_str, sid);
if ( *id_type & ID_USERID ) {
- type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
+ type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER );
obj_class = LDAP_OBJ_SAMBASAMACCOUNT;
- pstrcpy( suffix, lp_ldap_suffix() );
+ posix_obj_class = LDAP_OBJ_POSIXACCOUNT;
+ suffix = lp_ldap_suffix();
+ snprintf(filter, sizeof(filter),
+ "(&(|(&(objectClass=%s)(objectClass=%s))(objectClass=%s))(%s=%s))",
+ obj_class, posix_obj_class, LDAP_OBJ_IDMAP_ENTRY,
+ get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ),
+ sid_str);
}
else {
- type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
+ type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER );
obj_class = LDAP_OBJ_GROUPMAP;
- pstrcpy( suffix, lp_ldap_group_suffix() );
- }
+ posix_obj_class = LDAP_OBJ_POSIXGROUP;
+ suffix = lp_ldap_group_suffix();
+ snprintf(filter, sizeof(filter),
+ "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))",
+ obj_class, LDAP_OBJ_IDMAP_ENTRY,
+ get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ),
+ sid_str);
+ }
- sid_to_string(sid_str, sid);
- snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%s))", obj_class,
- LDAP_ATTRIBUTE_SID, sid_str);
-
attr_list = get_attr_list( sidmap_attr_list );
- rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE,
+ rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
filter, attr_list, 0, &result);
if (rc != LDAP_SUCCESS)
goto out;
- count = ldap_count_entries(ldap_state.ldap_struct, result);
+ count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
- /* fall back to looking up an idmap entry if we didn't find and
- actual user or group */
+ /* fall back to looking up an idmap entry if we didn't find anything under the idmap
+ user or group suffix */
if (count == 0) {
+ ldap_msgfree(result);
+
snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%s))",
LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str);
-#if 0 /* commented out for now -- jerry */
- if ( *id_type & ID_USERID )
- snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_USER_SUFFIX, lp_ldap_idmap_suffix() );
- else
- snprintf( suffix, sizeof(suffix), "%s,%s", IDMAP_GROUP_SUFFIX, lp_ldap_idmap_suffix() );
-#else
- pstrcpy( suffix, lp_ldap_idmap_suffix() );
-#endif
+ suffix = lp_ldap_idmap_suffix();
- rc = ldap_idmap_search(&ldap_state, suffix, LDAP_SCOPE_SUBTREE,
+ rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
filter, attr_list, 0, &result);
if (rc != LDAP_SUCCESS)
goto out;
- count = ldap_count_entries(ldap_state.ldap_struct, result);
+ count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
}
if ( count > 1 ) {
@@ -759,15 +329,28 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
/* we might have an existing entry to work with so pull out the requested information */
- if ( count )
- entry = ldap_first_entry(ldap_state.ldap_struct, result);
+ if ( count ) {
+ entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
- /* if entry == NULL, then we will default to allocating a new id */
+ dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
+ DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type));
+
+ if ( smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) )
+ {
+ if ( (*id_type & ID_USERID) )
+ id->uid = strtoul(id_str, NULL, 10);
+ else
+ id->gid = strtoul(id_str, NULL, 10);
+
+ ret = NT_STATUS_OK;
+ goto out;
+ }
+ }
- if ( !ldap_idmap_attribute(&ldap_state, entry, type, id_str) )
- {
+ if (!(*id_type & ID_QUERY_ONLY)) {
+ /* if entry == NULL, and we are asked to - allocate a new id */
int i;
-
+
for (i = 0; i < LDAP_MAX_ALLOC_ID; i++)
{
ret = ldap_allocate_id(id, *id_type);
@@ -781,115 +364,236 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
}
ret = ldap_set_mapping(sid, *id, *id_type);
-
- }
- else
- {
- if ( (*id_type & ID_USERID) )
- id->uid = strtoul(id_str, NULL, 10);
- else
- id->gid = strtoul(id_str, NULL, 10);
-
- ret = NT_STATUS_OK;
+ } else {
+ /* no match, and not adding one */
+ ret = NT_STATUS_UNSUCCESSFUL;
}
+
out:
free_attr_list( attr_list );
+ if (result)
+ ldap_msgfree(result);
+ if (dn)
+ ldap_memfree(dn);
return ret;
}
/***********************************************************************
This function cannot be called to modify a mapping, only set a new one
+
+ This takes a possible pointer to the existing entry for the UID or SID
+ involved.
***********************************************************************/
-static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id,
+ int id_type, const char *ldap_dn,
+ LDAPMessage *entry)
{
- pstring dn, sid_str, id_str;
+ char *dn = NULL;
+ pstring id_str;
fstring type;
LDAPMod **mods = NULL;
- int rc;
- int attempts = 0;
+ int rc = -1;
+ int ldap_op;
+ fstring sid_string;
+
+ sid_to_string( sid_string, sid );
+
+ if (ldap_dn) {
+ DEBUG(10, ("Adding new IDMAP mapping on DN: %s", ldap_dn));
+ ldap_op = LDAP_MOD_REPLACE;
+ dn = strdup(ldap_dn);
+ } else {
+ ldap_op = LDAP_MOD_ADD;
+ asprintf(&dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID),
+ sid_string, lp_ldap_idmap_suffix());
+ }
+
+ if (!dn) {
+ DEBUG(0, ("ldap_set_mapping_internals: out of memory allocating DN!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
if ( id_type & ID_USERID )
- fstrcpy( type, get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) );
+ fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) );
else
- fstrcpy( type, get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ) );
-
-#if 0
- snprintf(dn, sizeof(dn), "%s=%u,%s,%s", type,
- ((id_type & ID_USERID) ? id.uid : id.gid),
- ((id_type & ID_USERID) ? IDMAP_USER_SUFFIX : IDMAP_GROUP_SUFFIX ),
- lp_ldap_idmap_suffix());
-#else
- snprintf(dn, sizeof(dn), "%s=%u,%s", type,
- ((id_type & ID_USERID) ? id.uid : id.gid),
- lp_ldap_idmap_suffix());
-#endif
+ fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) );
snprintf(id_str, sizeof(id_str), "%u", ((id_type & ID_USERID) ? id.uid : id.gid));
- sid_to_string( sid_str, sid );
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY );
- smbldap_set_mod( &mods, LDAP_MOD_ADD, type, id_str );
smbldap_set_mod( &mods, LDAP_MOD_ADD,
- get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), sid_str );
+ "objectClass", LDAP_OBJ_IDMAP_ENTRY );
+
+ smbldap_make_mod( ldap_state.smbldap_state->ldap_struct,
+ entry, &mods, type, id_str );
- do {
- if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) != LDAP_SUCCESS)
- continue;
-
- rc = ldap_add_s(ldap_state.ldap_struct, dn, mods);
- } while ((rc == LDAP_SERVER_DOWN) && (attempts <= 8));
+ smbldap_make_mod( ldap_state.smbldap_state->ldap_struct,
+ entry, &mods,
+ get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID),
+ sid_string );
+
+ switch(ldap_op)
+ {
+ case LDAP_MOD_ADD:
+ smbldap_set_mod( &mods, LDAP_MOD_ADD,
+ "objectClass", LDAP_OBJ_SID_ENTRY );
+ rc = smbldap_add(ldap_state.smbldap_state, dn, mods);
+ break;
+ case LDAP_MOD_REPLACE:
+ rc = smbldap_modify(ldap_state.smbldap_state, dn, mods);
+ break;
+ }
ldap_mods_free( mods, True );
if (rc != LDAP_SUCCESS) {
- DEBUG(0,("ldap_set_mapping: Failed to create mapping from %s to %d [%s]\n",
- sid_str, ((id_type & ID_USERID) ? id.uid : id.gid), type));
+ char *ld_error = NULL;
+ ldap_get_option(ldap_state.smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
+ &ld_error);
+ DEBUG(0,("ldap_set_mapping_internals: Failed to create mapping from %s to %u [%s]\n",
+ sid_string, (unsigned int)((id_type & ID_USERID) ? id.uid : id.gid), type));
+ DEBUG(0, ("ldap_set_mapping_internals: Error was: %s\n", ld_error ? ld_error : "(NULL)"));
return NT_STATUS_UNSUCCESSFUL;
}
DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %d [%s]\n",
- sid_str, ((id_type & ID_USERID) ? id.uid : id.gid), type));
+ sid_string, ((id_type & ID_USERID) ? id.uid : id.gid), type));
return NT_STATUS_OK;
}
+/***********************************************************************
+ This function cannot be called to modify a mapping, only set a new one
+***********************************************************************/
+
+static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ char *dn = NULL;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ const char *type;
+ const char *obj_class;
+ const char *posix_obj_class;
+ const char *suffix;
+ fstring sid_str;
+ fstring id_str;
+ pstring filter;
+ char **attr_list;
+ int rc;
+ int count;
+
+ /* try for a samba user or group mapping (looking for an entry with a SID) */
+ if ( id_type & ID_USERID ) {
+ obj_class = LDAP_OBJ_SAMBASAMACCOUNT;
+ suffix = lp_ldap_suffix();
+ type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
+ posix_obj_class = LDAP_OBJ_POSIXACCOUNT;
+ snprintf(id_str, sizeof(id_str), "%u", id.uid );
+ }
+ else {
+ obj_class = LDAP_OBJ_GROUPMAP;
+ suffix = lp_ldap_group_suffix();
+ type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
+ posix_obj_class = LDAP_OBJ_POSIXGROUP;
+ snprintf(id_str, sizeof(id_str), "%u", id.gid );
+ }
+
+ sid_to_string(sid_str, sid);
+ snprintf(filter, sizeof(filter),
+ "(|"
+ "(&(|(objectClass=%s)(|(objectClass=%s)(objectClass=%s)))(%s=%s))"
+ "(&(objectClass=%s)(%s=%s))"
+ ")",
+ /* objectClasses that might contain a SID */
+ LDAP_OBJ_SID_ENTRY, LDAP_OBJ_IDMAP_ENTRY, obj_class,
+ get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ),
+ sid_str,
+
+ /* objectClasses that might contain a Unix UID/GID */
+ posix_obj_class,
+ /* Unix UID/GID specifier*/
+ type,
+ /* actual ID */
+ id_str);
+
+ attr_list = get_attr_list( sidmap_attr_list );
+ rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
+ filter, attr_list, 0, &result);
+ free_attr_list( attr_list );
+
+ if (rc != LDAP_SUCCESS)
+ goto out;
+
+ count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
+
+ /* fall back to looking up an idmap entry if we didn't find anything under the idmap
+ user or group suffix */
+
+ if (count == 1) {
+ entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
+
+ dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result);
+ DEBUG(10, ("Found partial mapping entry at dn=%s, looking for %s\n", dn, type));
+
+ ret = ldap_set_mapping_internals(sid, id, id_type, dn, entry);
+
+ goto out;
+ } else if (count > 1) {
+ DEBUG(0, ("Too many entries trying to find DN to attach ldap \n"));
+ goto out;
+ }
+
+ ret = ldap_set_mapping_internals(sid, id, id_type, NULL, NULL);
+
+out:
+ if (result)
+ ldap_msgfree(result);
+ if (dn)
+ ldap_memfree(dn);
+
+ return ret;
+}
/*****************************************************************************
Initialise idmap database.
*****************************************************************************/
static NTSTATUS ldap_idmap_init( char *params )
{
fstring filter;
-#if 0
- pstring dn;
-#endif
int rc;
char **attr_list;
LDAPMessage *result = NULL;
LDAPMod **mods = NULL;
int count;
+ NTSTATUS nt_status;
- /* parse out the server (assuming only parameter is a URI) */
+ ldap_state.mem_ctx = talloc_init("idmap_ldap");
+ if (!ldap_state.mem_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* assume location is the only parameter */
+ if (!NT_STATUS_IS_OK(nt_status =
+ smbldap_init(ldap_state.mem_ctx, params,
+ &ldap_state.smbldap_state))) {
+ talloc_destroy(ldap_state.mem_ctx);
+ return nt_status;
+ }
- if ( params )
- ldap_state.uri = smb_xstrdup( params );
- else
- ldap_state.uri = smb_xstrdup( "ldap://localhost/" );
-
/* see if the idmap suffix and sub entries exists */
snprintf( filter, sizeof(filter), "(objectclass=%s)", LDAP_OBJ_IDPOOL );
attr_list = get_attr_list( idpool_attr_list );
- rc = ldap_idmap_search(&ldap_state, lp_ldap_idmap_suffix(),
+ rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result);
free_attr_list ( attr_list );
if (rc != LDAP_SUCCESS)
return NT_STATUS_UNSUCCESSFUL;
- count = ldap_count_entries(ldap_state.ldap_struct, result);
+ count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
if ( count > 1 ) {
DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n",
@@ -900,7 +604,6 @@ static NTSTATUS ldap_idmap_init( char *params )
uid_t luid, huid;
gid_t lgid, hgid;
fstring uid_str, gid_str;
- int attempts = 0;
if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) {
DEBUG(0,("ldap_idmap_init: idmap uid/gid parameters not specified\n"));
@@ -916,34 +619,9 @@ static NTSTATUS ldap_idmap_init( char *params )
smbldap_set_mod( &mods, LDAP_MOD_ADD,
get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str );
- do {
- if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) != LDAP_SUCCESS)
- continue;
-
- rc = ldap_modify_s(ldap_state.ldap_struct, lp_ldap_idmap_suffix(), mods);
- } while ((rc == LDAP_SERVER_DOWN) && (attempts <= 8));
+ rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods);
}
- /* we have the initial entry now; let's create the sub entries */
- /* if they already exist then this will fail, but we don't care */
-
-#if 0 /* commenting out for now, but I will come back to this --jerry */
-
- mods = NULL;
- snprintf( dn, sizeof(dn), "%s,%s", IDMAP_USER_SUFFIX, lp_ldap_idmap_suffix() );
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_OU );
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "ou", "idmap people" );
- ldap_add_s(ldap_state.ldap_struct, dn, mods);
- ldap_mods_free( mods, True );
-
- mods = NULL;
- snprintf( dn, sizeof(dn), "%s,%s", IDMAP_GROUP_SUFFIX, lp_ldap_idmap_suffix() );
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_OU );
- smbldap_set_mod( &mods, LDAP_MOD_ADD, "ou", "idmap group" );
- ldap_add_s(ldap_state.ldap_struct, dn, mods);
- ldap_mods_free( mods, True );
-#endif
-
return NT_STATUS_OK;
}
@@ -953,14 +631,9 @@ static NTSTATUS ldap_idmap_init( char *params )
static NTSTATUS ldap_idmap_close(void)
{
- if (ldap_state.ldap_struct != NULL) {
- ldap_unbind_ext(ldap_state.ldap_struct, NULL, NULL);
- ldap_state.ldap_struct = NULL;
- }
- SAFE_FREE( ldap_state.uri );
- SAFE_FREE( ldap_state.bind_dn );
- SAFE_FREE( ldap_state.bind_secret );
+ smbldap_free_struct(&(ldap_state).smbldap_state);
+ talloc_destroy(ldap_state.mem_ctx);
DEBUG(5,("The connection to the LDAP server was closed\n"));
/* maybe free the results here --metze */
diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c
index 095f5f0874..ffc3db2a0a 100644
--- a/source3/sam/idmap_util.c
+++ b/source3/sam/idmap_util.c
@@ -132,7 +132,6 @@ BOOL idmap_get_free_ugid_range(uint32 *low, uint32 *high)
*THE CANONICAL* convert uid_t to SID function.
check idmap if uid is in idmap range, otherwise falls back to
the legacy algorithmic mapping.
- A special cache is used for uids that maps to Wellknown SIDs
Returns SID pointer.
*****************************************************************/
@@ -204,7 +203,6 @@ NTSTATUS gid_to_sid(DOM_SID *sid, gid_t gid)
*THE CANONICAL* convert SID to uid function.
if it is a foreign sid or it is in idmap rid range check idmap,
otherwise falls back to the legacy algorithmic mapping.
- A special cache is used for uids that maps to Wellknown SIDs
Returns True if this name is a user sid and the conversion
was done correctly, False if not.
*****************************************************************/
@@ -351,6 +349,7 @@ BOOL idmap_init_wellknown_sids(void)
int num_entries=0;
DOM_SID sid;
unid_t id;
+ fstring sid_string;
if (!(guest_account && *guest_account)) {
DEBUG(1, ("NULL guest account!?!?\n"));
@@ -368,6 +367,8 @@ BOOL idmap_init_wellknown_sids(void)
sid_append_rid(&sid, DOMAIN_USER_RID_GUEST);
if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_USERID))) {
+ DEBUG(0, ("Failed to setup UID mapping for GUEST (%s) to (%u)\n",
+ sid_to_string(sid_string, &sid), (unsigned int)id.uid));
passwd_free(&pass);
return False;
}
@@ -378,6 +379,8 @@ BOOL idmap_init_wellknown_sids(void)
sid_copy(&sid, get_global_sam_sid());
sid_append_rid(&sid, DOMAIN_GROUP_RID_GUESTS);
if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_GROUPID))) {
+ DEBUG(0, ("Failed to setup GID mapping for Group DOMAIN GUESTS (%s) to (%u)\n",
+ sid_to_string(sid_string, &sid), (unsigned int)id.gid));
passwd_free(&pass);
return False;
}
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index e2fe2ac819..6f549aab1c 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -842,9 +842,19 @@ void build_options(BOOL screen);
if (!init_registry())
exit(1);
+ /* Initialise the password backed before idmap and the global_sam_sid
+ to ensure that we fetch from ldap before we make a domain sid up */
+
if(!initialize_password_db(False))
exit(1);
+ if(!get_global_sam_sid()) {
+ DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
+ exit(1);
+ }
+
+ static_init_auth;
+
{
const char *idmap_back = lp_idmap_backend();
@@ -852,8 +862,10 @@ void build_options(BOOL screen);
exit(1);
}
- if (!idmap_init_wellknown_sids())
+ if (!idmap_init_wellknown_sids()) {
+ DEBUG(0,("ERROR: Samba failed to initialize it's 'well known' SID -> ID mapping tables.\n"));
exit(1);
+ }
static_init_rpc;
@@ -862,12 +874,6 @@ void build_options(BOOL screen);
/* possibly reload the services file. */
reload_services(True);
- if(!get_global_sam_sid()) {
- DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
- exit(1);
- }
-
-
if (!init_account_policy()) {
DEBUG(0,("Could not open account policy tdb.\n"));
exit(1);
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index 3fa2751347..5b702f7591 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -606,6 +606,12 @@ int main (int argc, char **argv)
exit(1);
}
+ /* Initialise the password backed before idmap and the global_sam_sid
+ to ensure that we fetch from ldap before we make a domain sid up */
+
+ if(!initialize_password_db(False))
+ exit(1);
+
if (!init_names())
exit(1);