1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

This patch cleans up some of our ldap code, for better behaviour:

We now always read the Domain SID out of LDAP.  If the local secrets.tdb
is ever different to LDAP, it is overwritten out of LDAP.   We also
store the 'algorithmic rid base' into LDAP, and assert if it changes.
(This ensures cross-host synchronisation, and allows for possible
integration with idmap).  If we fail to read/add the domain entry, we just
fallback to the old behaviour.

We always use an existing DN when adding IDMAP entries to LDAP, unless
no suitable entry is available.  This means that a user's posixAccount
will have a SID added to it, or a user's sambaSamAccount will have a UID
added.  Where we cannot us an existing DN, we use
'sambaSid=S-x-y-z,....' as the DN.

The code now allows modifications to the ID mapping in many cases.

Likewise, we now check more carefully when adding new user entires to LDAP,
to not duplicate SIDs (for users, at this stage), and to add the sambaSamAccount
onto the idmap entry for that user, if it is already established (ensuring
we do not duplicate sambaSid entries in the directory).

The allocated UID code has been expanded to take into account the space
between '1000 - algorithmic rid base'.  This much better fits into what
an NT4 does - allocating in the bottom part of the RID range.

On the code cleanup side of things, we now share as much code as
possible between idmap_ldap and pdb_ldap.

We also no longer use the race-prone 'enumerate all users' method for
finding the next RID to allocate.  Instead, we just start at the bottom
of the range, and increment again if the user already exists.  The first
time this is run, it may well take a long time, but next time will just
be able to use the next Rid.

Thanks to metze and AB for double-checking parts of this.

Andrew Bartlett
This commit is contained in:
Andrew Bartlett 0001-01-01 00:00:00 +00:00
parent 5280c69531
commit 9c595c8c23
9 changed files with 756 additions and 1005 deletions

View File

@ -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 ) )

View File

@ -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

View File

@ -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;

View File

@ -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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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);

View File

@ -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);