diff options
-rw-r--r-- | examples/LDAP/samba.schema | 10 | ||||
-rw-r--r-- | source3/Makefile.in | 12 | ||||
-rw-r--r-- | source3/configure.in | 12 | ||||
-rw-r--r-- | source3/include/includes.h | 4 | ||||
-rw-r--r-- | source3/include/smbldap.h | 101 | ||||
-rw-r--r-- | source3/lib/smbldap.c | 259 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 285 | ||||
-rw-r--r-- | source3/sam/idmap_ldap.c | 446 |
8 files changed, 646 insertions, 483 deletions
diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema index 3db7094bf2..9887954045 100644 --- a/examples/LDAP/samba.schema +++ b/examples/LDAP/samba.schema @@ -315,3 +315,13 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL MUST ( sambaDomainName $ sambaNextGroupRid $ sambaNextUserRid $ sambaSID ) ) +## 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 + DESC 'Mapping from a SID to an ID' + MUST ( sambaSID ) + MAY ( uidNumber $ gidNumber )) + diff --git a/source3/Makefile.in b/source3/Makefile.in index 945953fe48..df66f6a724 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -158,6 +158,8 @@ MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSE TDBBASE_OBJ = tdb/tdb.o tdb/spinlock.o TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o +SMBLDAP_OBJ = @SMBLDAP@ + LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \ lib/getsmbpass.o lib/interface.o lib/md4.o \ lib/interfaces.o lib/pidfile.o lib/replace.o \ @@ -178,7 +180,7 @@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \ lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \ lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ -LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o +LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o READLINE_OBJ = lib/readline.o @@ -277,13 +279,13 @@ PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ passdb/machine_sid.o passdb/util_sam_sid.o passdb/pdb_compat.o \ - passdb/privileges.o @PDB_STATIC@ + passdb/privileges.o @PDB_STATIC@ $(SMBLDAP__OBJ) XML_OBJ = passdb/pdb_xml.o MYSQL_OBJ = passdb/pdb_mysql.o DEVEL_HELP_OBJ = modules/weird.o -IDMAP_OBJ = sam/idmap.o sam/idmap_util.o @IDMAP_STATIC@ +IDMAP_OBJ = sam/idmap.o sam/idmap_util.o @IDMAP_STATIC@ $(SMBLDAP_OBJ) GROUPDB_OBJ = groupdb/mapping.o @@ -387,7 +389,7 @@ SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(LIBSMB_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \ $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \ - $(POPT_LIB_OBJ) $(IDMAP_OBJ) + $(POPT_LIB_OBJ) $(IDMAP_OBJ) SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) @@ -597,7 +599,7 @@ WINBINDD_OBJ = \ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \ $(PROFILE_OBJ) $(UNIGRP_OBJ) $(IDMAP_OBJ) \ - $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) + $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ $(UBIQX_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) diff --git a/source3/configure.in b/source3/configure.in index 79f01ba421..53b4f1524f 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -2302,8 +2302,8 @@ AC_ARG_WITH(ldap, AC_MSG_RESULT($with_ldap_support) if test x"$with_ldap_support" = x"yes"; then -ac_save_LIBS="$LIBS" -LIBS="" + ac_save_LIBS="$LIBS" + LIBS="" ################################################################## # we might need the lber lib on some systems. To avoid link errors @@ -2322,6 +2322,9 @@ LIBS="" ]) ]) + ## we have ldap so build the list of files for the generic samba ldap library + SMBLDAP="lib/smbldap.o" + ######################################################## # If we have LDAP, does it's rebind procedure take 2 or 3 arguments? # Check found in pam_ldap 145. @@ -2334,8 +2337,9 @@ LIBS="" AC_CHECK_FUNCS(ldap_initialize) fi -LDAP_LIBS="$LIBS"; -LIBS="$ac_save_LIBS"; + AC_SUBST(SMBLDAP) + LDAP_LIBS="$LIBS"; + LIBS="$ac_save_LIBS"; else # Can't have ADS support without LDAP if test x"$with_ads_support" = x"yes"; then diff --git a/source3/include/includes.h b/source3/include/includes.h index 4de81c46d2..ac5c48d780 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -869,6 +869,10 @@ struct printjob; struct smb_ldap_privates; +/* forward declarations from smbldap.c */ + +#include "smbldap.h" + /***** automatically generated prototypes *****/ #ifndef NO_PROTO_H #include "proto.h" diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h new file mode 100644 index 0000000000..13451fa24f --- /dev/null +++ b/source3/include/smbldap.h @@ -0,0 +1,101 @@ +/* + Unix SMB/CIFS mplementation. + LDAP protocol helper functions for SAMBA + Copyright (C) Gerald Carter 2001-2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef _SMBLDAP_H +#define _SMBLDAP_H + +/* specify schema versions between 2.2. and 3.0 */ + +#define SCHEMAVER_SAMBAACCOUNT 1 +#define SCHEMAVER_SAMBASAMACCOUNT 2 + +/* objectclass names */ + +#define LDAP_OBJ_SAMBASAMACCOUNT "sambaSamAccount" +#define LDAP_OBJ_SAMBAACCOUNT "sambaAccount" +#define LDAP_OBJ_GROUPMAP "sambaGroupMapping" +#define LDAP_OBJ_DOMINFO "sambaDomain" +#define LDAP_OBJ_IDPOOL "sambaUnixIdPool" +#define LDAP_OBJ_IDMAP_ENTRY "sambaIdmapEntry" + +#define LDAP_OBJ_ACCOUNT "account" +#define LDAP_OBJ_POSIXACCOUNT "posixAccount" +#define LDAP_OBJ_POSIXGROUP "posixGroup" + +/* some generic attributes that get reused a lot */ + +#define LDAP_ATTRIBUTE_SID "sambaSID" +#define LDAP_ATTRIBUTE_UIDNUMBER "uidNumber" +#define LDAP_ATTRIBUTE_GIDNUMBER "gidNumber" + +/* attribute map table indexes */ + +#define LDAP_ATTR_LIST_END 0 +#define LDAP_ATTR_UID 1 +#define LDAP_ATTR_UIDNUMBER 2 +#define LDAP_ATTR_GIDNUMBER 3 +#define LDAP_ATTR_UNIX_HOME 4 +#define LDAP_ATTR_PWD_LAST_SET 5 +#define LDAP_ATTR_PWD_CAN_CHANGE 6 +#define LDAP_ATTR_PWD_MUST_CHANGE 7 +#define LDAP_ATTR_LOGON_TIME 8 +#define LDAP_ATTR_LOGOFF_TIME 9 +#define LDAP_ATTR_KICKOFF_TIME 10 +#define LDAP_ATTR_CN 11 +#define LDAP_ATTR_DISPLAY_NAME 12 +#define LDAP_ATTR_HOME_PATH 13 +#define LDAP_ATTR_LOGON_SCRIPT 14 +#define LDAP_ATTR_PROFILE_PATH 15 +#define LDAP_ATTR_DESC 16 +#define LDAP_ATTR_USER_WKS 17 +#define LDAP_ATTR_USER_SID 18 +#define LDAP_ATTR_USER_RID 18 +#define LDAP_ATTR_PRIMARY_GROUP_SID 19 +#define LDAP_ATTR_PRIMARY_GROUP_RID 20 +#define LDAP_ATTR_LMPW 21 +#define LDAP_ATTR_NTPW 22 +#define LDAP_ATTR_DOMAIN 23 +#define LDAP_ATTR_OBJCLASS 24 +#define LDAP_ATTR_ACB_INFO 25 +#define LDAP_ATTR_NEXT_USERRID 26 +#define LDAP_ATTR_NEXT_GROUPRID 27 +#define LDAP_ATTR_DOM_SID 28 +#define LDAP_ATTR_HOME_DRIVE 29 +#define LDAP_ATTR_GROUP_SID 30 +#define LDAP_ATTR_GROUP_TYPE 31 + + +typedef struct _attrib_map_entry { + int attrib; + const char *name; +} ATTRIB_MAP_ENTRY; + +/* structures */ + +extern ATTRIB_MAP_ENTRY attrib_map_v22[]; +extern ATTRIB_MAP_ENTRY attrib_map_v30[]; +extern ATTRIB_MAP_ENTRY dominfo_attr_list[]; +extern ATTRIB_MAP_ENTRY groupmap_attr_list[]; +extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[]; +extern ATTRIB_MAP_ENTRY idpool_attr_list[]; +extern ATTRIB_MAP_ENTRY sidmap_attr_list[]; + +#endif /* _SMBLDAP_H */ diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c new file mode 100644 index 0000000000..5dbea0669f --- /dev/null +++ b/source3/lib/smbldap.c @@ -0,0 +1,259 @@ +/* + Unix SMB/CIFS mplementation. + LDAP protocol helper functions for SAMBA + Copyright (C) Gerald Carter 2001-2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" +#include "smbldap.h" + +/* attributes used by Samba 2.2 */ + +ATTRIB_MAP_ENTRY attrib_map_v22[] = { + { LDAP_ATTR_UID, "uid" }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, + { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" }, + { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" }, + { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" }, + { LDAP_ATTR_LOGON_TIME, "logonTime" }, + { LDAP_ATTR_LOGOFF_TIME, "logoffTime" }, + { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_HOME_PATH, "smbHome" }, + { LDAP_ATTR_HOME_DRIVE, "homeDrives" }, + { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" }, + { LDAP_ATTR_PROFILE_PATH, "profilePath" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_USER_WKS, "userWorkstations"}, + { LDAP_ATTR_USER_RID, "rid" }, + { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"}, + { LDAP_ATTR_LMPW, "lmPassword" }, + { LDAP_ATTR_NTPW, "ntPassword" }, + { LDAP_ATTR_DOMAIN, "domain" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_ACB_INFO, "acctFlags" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* attributes used by Samba 3.0's sambaSamAccount */ + +ATTRIB_MAP_ENTRY attrib_map_v30[] = { + { LDAP_ATTR_UID, "uid" }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, + { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" }, + { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" }, + { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" }, + { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" }, + { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" }, + { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" }, + { LDAP_ATTR_HOME_PATH, "sambaHomePath" }, + { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" }, + { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" }, + { LDAP_ATTR_USER_SID, "sambaSID" }, + { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" }, + { LDAP_ATTR_LMPW, "sambaLMPassword" }, + { LDAP_ATTR_NTPW, "sambaNTPassword" }, + { LDAP_ATTR_DOMAIN, "sambaDomainName" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* attributes used for alalocating RIDs */ + +ATTRIB_MAP_ENTRY dominfo_attr_list[] = { + { LDAP_ATTR_DOMAIN, "sambaDomainName" }, + { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, + { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, + { LDAP_ATTR_DOM_SID, "sambaSID" }, + { LDAP_ATTR_LIST_END, NULL }, +}; + +/* Samba 3.0 group mapping attributes */ + +ATTRIB_MAP_ENTRY groupmap_attr_list[] = { + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_GROUP_SID, "sambaSID" }, + { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { + { LDAP_ATTR_GROUP_SID, "sambaSID" }, + { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* idmap_ldap samba[U|G]idPool */ + +ATTRIB_MAP_ENTRY idpool_attr_list[] = { + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_LIST_END, NULL } +}; + +ATTRIB_MAP_ENTRY sidmap_attr_list[] = { + { LDAP_ATTR_GROUP_SID, "sambaSID" }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_LIST_END, NULL } +}; + +/********************************************************************** + perform a simple table lookup and return the attribute name + **********************************************************************/ + +const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ) +{ + int i = 0; + + while ( table[i].attrib != LDAP_ATTR_LIST_END ) { + if ( table[i].attrib == key ) + return table[i].name; + i++; + } + + return NULL; +} + + +/********************************************************************** + Return the list of attribute names from a mapping table + **********************************************************************/ + +char** get_attr_list( ATTRIB_MAP_ENTRY table[] ) +{ + char **names; + int i = 0; + + while ( table[i].attrib != LDAP_ATTR_LIST_END ) + i++; + i++; + + names = (char**)malloc( sizeof(char*)*i ); + if ( !names ) { + DEBUG(0,("get_attr_list: out of memory\n")); + return NULL; + } + + i = 0; + while ( table[i].attrib != LDAP_ATTR_LIST_END ) { + names[i] = strdup( table[i].name ); + i++; + } + names[i] = NULL; + + return names; +} + +/********************************************************************* + Cleanup + ********************************************************************/ + +void free_attr_list( char **list ) +{ + int i = 0; + + if ( !list ) + return; + + while ( list[i] ) + SAFE_FREE( list[i] ); + + SAFE_FREE( list ); +} + +/******************************************************************* + find the ldap password +******************************************************************/ +BOOL fetch_ldap_pw(char **dn, char** pw) +{ + char *key = NULL; + size_t size; + + *dn = smb_xstrdup(lp_ldap_admin_dn()); + + if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { + SAFE_FREE(*dn); + DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); + } + + *pw=secrets_fetch(key, &size); + SAFE_FREE(key); + + if (!size) { + /* Upgrade 2.2 style entry */ + char *p; + char* old_style_key = strdup(*dn); + char *data; + fstring old_style_pw; + + if (!old_style_key) { + DEBUG(0, ("fetch_ldap_pw: strdup failed!\n")); + return False; + } + + for (p=old_style_key; *p; p++) + if (*p == ',') *p = '/'; + + data=secrets_fetch(old_style_key, &size); + if (!size && size < sizeof(old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + + strncpy(old_style_pw, data, size); + old_style_pw[size] = 0; + + SAFE_FREE(data); + + if (!secrets_store_ldap_pw(*dn, old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + if (!secrets_delete(old_style_key)) { + DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); + } + + SAFE_FREE(old_style_key); + + *pw = smb_xstrdup(old_style_pw); + } + + return True; +} + diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index fb63e81d28..e6fd12fd0e 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -59,6 +59,8 @@ #define SAM_ACCOUNT struct sam_passwd #endif +#include "smbldap.h" + struct ldapsam_privates { /* Former statics */ LDAP *ldap_struct; @@ -93,177 +95,6 @@ struct ldapsam_privates { static struct ldapsam_privates *static_ldap_state; -/* specify schema versions between 2.2. and 3.0 */ - -#define SCHEMAVER_SAMBAACCOUNT 1 -#define SCHEMAVER_SAMBASAMACCOUNT 2 - -/* objectclass names */ - -#define LDAP_OBJ_SAMBASAMACCOUNT "sambaSamAccount" -#define LDAP_OBJ_SAMBAACCOUNT "sambaAccount" -#define LDAP_OBJ_GROUPMAP "sambaGroupMapping" -#define LDAP_OBJ_DOMINFO "sambaDomain" - -#define LDAP_OBJ_ACCOUNT "account" -#define LDAP_OBJ_POSIXACCOUNT "posixAccount" -#define LDAP_OBJ_POSIXGROUP "posixGroup" - -/* some generic attributes that get reused a lot */ - -#define LDAP_ATTRIBUTE_SID "sambaSID" - -/* attribute map table indexes */ - -#define LDAP_ATTR_LIST_END 0 -#define LDAP_ATTR_UID 1 -#define LDAP_ATTR_UIDNUMBER 2 -#define LDAP_ATTR_GIDNUMBER 3 -#define LDAP_ATTR_UNIX_HOME 4 -#define LDAP_ATTR_PWD_LAST_SET 5 -#define LDAP_ATTR_PWD_CAN_CHANGE 6 -#define LDAP_ATTR_PWD_MUST_CHANGE 7 -#define LDAP_ATTR_LOGON_TIME 8 -#define LDAP_ATTR_LOGOFF_TIME 9 -#define LDAP_ATTR_KICKOFF_TIME 10 -#define LDAP_ATTR_CN 11 -#define LDAP_ATTR_DISPLAY_NAME 12 -#define LDAP_ATTR_HOME_PATH 13 -#define LDAP_ATTR_LOGON_SCRIPT 14 -#define LDAP_ATTR_PROFILE_PATH 15 -#define LDAP_ATTR_DESC 16 -#define LDAP_ATTR_USER_WKS 17 -#define LDAP_ATTR_USER_SID 18 -#define LDAP_ATTR_USER_RID 18 -#define LDAP_ATTR_PRIMARY_GROUP_SID 19 -#define LDAP_ATTR_PRIMARY_GROUP_RID 20 -#define LDAP_ATTR_LMPW 21 -#define LDAP_ATTR_NTPW 22 -#define LDAP_ATTR_DOMAIN 23 -#define LDAP_ATTR_OBJCLASS 24 -#define LDAP_ATTR_ACB_INFO 25 -#define LDAP_ATTR_NEXT_USERRID 26 -#define LDAP_ATTR_NEXT_GROUPRID 27 -#define LDAP_ATTR_DOM_SID 28 -#define LDAP_ATTR_HOME_DRIVE 29 -#define LDAP_ATTR_GROUP_SID 30 -#define LDAP_ATTR_GROUP_TYPE 31 - - -typedef struct _attrib_map_entry { - int attrib; - const char *name; -} ATTRIB_MAP_ENTRY; - - -/* attributes used by Samba 2.2 */ - -static ATTRIB_MAP_ENTRY attrib_map_v22[] = { - { LDAP_ATTR_UID, "uid" }, - { LDAP_ATTR_UIDNUMBER, "uidNumber" }, - { LDAP_ATTR_GIDNUMBER, "gidNumber" }, - { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, - { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" }, - { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" }, - { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" }, - { LDAP_ATTR_LOGON_TIME, "logonTime" }, - { LDAP_ATTR_LOGOFF_TIME, "logoffTime" }, - { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" }, - { LDAP_ATTR_CN, "cn" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_HOME_PATH, "smbHome" }, - { LDAP_ATTR_HOME_DRIVE, "homeDrives" }, - { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" }, - { LDAP_ATTR_PROFILE_PATH, "profilePath" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_USER_WKS, "userWorkstations"}, - { LDAP_ATTR_USER_RID, "rid" }, - { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"}, - { LDAP_ATTR_LMPW, "lmPassword" }, - { LDAP_ATTR_NTPW, "ntPassword" }, - { LDAP_ATTR_DOMAIN, "domain" }, - { LDAP_ATTR_OBJCLASS, "objectClass" }, - { LDAP_ATTR_ACB_INFO, "acctFlags" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -/* attributes used by Samba 3.0's sambaSamAccount */ - -static ATTRIB_MAP_ENTRY attrib_map_v30[] = { - { LDAP_ATTR_UID, "uid" }, - { LDAP_ATTR_UIDNUMBER, "uidNumber" }, - { LDAP_ATTR_GIDNUMBER, "gidNumber" }, - { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, - { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" }, - { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" }, - { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" }, - { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" }, - { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" }, - { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" }, - { LDAP_ATTR_CN, "cn" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" }, - { LDAP_ATTR_HOME_PATH, "sambaHomePath" }, - { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" }, - { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" }, - { LDAP_ATTR_USER_SID, "sambaSID" }, - { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" }, - { LDAP_ATTR_LMPW, "sambaLMPassword" }, - { LDAP_ATTR_NTPW, "sambaNTPassword" }, - { LDAP_ATTR_DOMAIN, "sambaDomainName" }, - { LDAP_ATTR_OBJCLASS, "objectClass" }, - { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -/* attributes used for alalocating RIDs */ - -static ATTRIB_MAP_ENTRY dominfo_attr_list[] = { - { LDAP_ATTR_DOMAIN, "sambaDomainName" }, - { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, - { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, - { LDAP_ATTR_DOM_SID, "sambaSID" }, - { LDAP_ATTR_LIST_END, NULL }, -}; - -/* Samba 3.0 group mapping attributes */ - -static ATTRIB_MAP_ENTRY groupmap_attr_list[] = { - { LDAP_ATTR_GIDNUMBER, "gidNumber" }, - { LDAP_ATTR_GROUP_SID, "sambaSID" }, - { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_CN, "cn" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -static ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { - { LDAP_ATTR_GROUP_SID, "sambaSID" }, - { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -/********************************************************************** - perform a simple table lookup and return the attribute name - **********************************************************************/ - -static const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ) -{ - int i = 0; - - while ( table[i].attrib != LDAP_ATTR_LIST_END ) { - if ( table[i].attrib == key ) - return table[i].name; - i++; - } - - return NULL; -} /********************************************************************** get the attribute name given a user schame version @@ -287,52 +118,6 @@ static const char* get_userattr_key2string( int schema_ver, int key ) } /********************************************************************** - Return the list of attribute names from a mapping table - **********************************************************************/ - -static char** get_attr_list( ATTRIB_MAP_ENTRY table[] ) -{ - char **names; - int i = 0; - - while ( table[i].attrib != LDAP_ATTR_LIST_END ) - i++; - i++; - - names = (char**)malloc( sizeof(char*)*i ); - if ( !names ) { - DEBUG(0,("get_attr_list: out of memory\n")); - return NULL; - } - - i = 0; - while ( table[i].attrib != LDAP_ATTR_LIST_END ) { - names[i] = strdup( table[i].name ); - i++; - } - names[i] = NULL; - - return names; -} - -/********************************************************************* - Cleanup - ********************************************************************/ - -static void free_attr_list( char **list ) -{ - int i = 0; - - if ( !list ) - return; - - while ( list[i] ) - SAFE_FREE( list[i] ); - - SAFE_FREE( list ); -} - -/********************************************************************** return the list of attribute names given a user schema version **********************************************************************/ @@ -352,70 +137,6 @@ static char** get_userattr_list( int schema_ver ) return NULL; } - -/******************************************************************* - find the ldap password -******************************************************************/ -static BOOL fetch_ldapsam_pw(char **dn, char** pw) -{ - char *key = NULL; - size_t size; - - *dn = smb_xstrdup(lp_ldap_admin_dn()); - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { - SAFE_FREE(*dn); - DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n")); - } - - *pw=secrets_fetch(key, &size); - SAFE_FREE(key); - - if (!size) { - /* Upgrade 2.2 style entry */ - char *p; - char* old_style_key = strdup(*dn); - char *data; - fstring old_style_pw; - - if (!old_style_key) { - DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n")); - return False; - } - - for (p=old_style_key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(old_style_key, &size); - if (!size && size < sizeof(old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - - strncpy(old_style_pw, data, size); - old_style_pw[size] = 0; - - SAFE_FREE(data); - - if (!secrets_store_ldap_pw(*dn, old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - if (!secrets_delete(old_style_key)) { - DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); - } - - SAFE_FREE(old_style_key); - - *pw = smb_xstrdup(old_style_pw); - } - - return True; -} /******************************************************************* open a connection to the ldap server. @@ -632,7 +353,7 @@ static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ld static_ldap_state = ldap_state; /* get the password */ - if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) + if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) { DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); return LDAP_INVALID_CREDENTIALS; diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c index 22d9fd0666..352b998cef 100644 --- a/source3/sam/idmap_ldap.c +++ b/source3/sam/idmap_ldap.c @@ -3,9 +3,10 @@ idmap LDAP backend - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 - Copyright (C) Simo Sorce 2003 + Copyright (C) Tim Potter 2000 + Copyright (C) Anthony Liguori 2003 + Copyright (C) Simo Sorce 2003 + Copyright (C) Gerald Carter 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +32,9 @@ #include <lber.h> #include <ldap.h> +#include "smbldap.h" + + struct ldap_idmap_state { LDAP *ldap_struct; time_t last_ping; @@ -53,70 +57,6 @@ static NTSTATUS ldap_idmap_close(void); /******************************************************************* - find the ldap password -******************************************************************/ -static BOOL fetch_ldapsam_pw(char **dn, char** pw) -{ - char *key = NULL; - size_t size; - - *dn = smb_xstrdup(lp_ldap_admin_dn()); - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { - SAFE_FREE(*dn); - DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n")); - } - - *pw=secrets_fetch(key, &size); - SAFE_FREE(key); - - if (!size) { - /* Upgrade 2.2 style entry */ - char *p; - char* old_style_key = strdup(*dn); - char *data; - fstring old_style_pw; - - if (!old_style_key) { - DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n")); - return False; - } - - for (p=old_style_key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(old_style_key, &size); - if (!size && size < sizeof(old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - - strncpy(old_style_pw, data, size); - old_style_pw[size] = 0; - - SAFE_FREE(data); - - if (!secrets_store_ldap_pw(*dn, old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - if (!secrets_delete(old_style_key)) { - DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); - } - - SAFE_FREE(old_style_key); - - *pw = smb_xstrdup(old_style_pw); - } - - return True; -} - -/******************************************************************* open a connection to the ldap server. ******************************************************************/ static int ldap_idmap_open_connection(struct ldap_idmap_state *state) @@ -284,6 +224,9 @@ static int ldap_idmap_open(struct ldap_idmap_state *state) return LDAP_SUCCESS; } +/******************************************************************* +******************************************************************/ + static int ldap_idmap_retry_open(struct ldap_idmap_state *state, int *attempts) { int rc; @@ -319,6 +262,7 @@ static int ldap_idmap_retry_open(struct ldap_idmap_state *state, int *attempts) 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, @@ -421,7 +365,7 @@ static int ldap_idmap_connect_system(struct ldap_idmap_state *state) char *ldap_secret; /* get the password */ - if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) + if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) { DEBUG(0, ("ldap_idmap_connect_system: Failed to retrieve " "password from secrets.tdb\n")); @@ -478,9 +422,13 @@ static int ldap_idmap_connect_system(struct ldap_idmap_state *state) return rc; } +/***************************************************************************** + wrapper around ldap_search() +*****************************************************************************/ + static int ldap_idmap_search(struct ldap_idmap_state *state, const char *base, int scope, const char *filter, - const char *attrs[], int attrsonly, + char *attrs[], int attrsonly, LDAPMessage **res) { int rc = LDAP_SERVER_DOWN; @@ -510,9 +458,10 @@ static int ldap_idmap_search(struct ldap_idmap_state *state, return rc; } -/******************************************************************* -search an attribute and return the first value found. -******************************************************************/ +/*********************************************************************** + 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) @@ -520,12 +469,16 @@ static BOOL ldap_idmap_attribute (struct ldap_idmap_state *state, char **values; value[0] = '\0'; - if ((values = ldap_get_values (state->ldap_struct, entry, attribute)) - == NULL) { + 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) @@ -540,9 +493,9 @@ static BOOL ldap_idmap_attribute (struct ldap_idmap_state *state, return True; } -static const char *attrs[] = {"objectClass", "uidNumber", "gidNumber", - "ntSid", NULL}; -static const char *pool_attr[] = {"uidNumber", "gidNumber", NULL}; +/***************************************************************************** + Allocate a new uid or gid +*****************************************************************************/ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) { @@ -554,21 +507,34 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) pstring id_str, new_id_str; LDAPMod mod[2]; LDAPMod *mods[3]; - const char *type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; + const char *type; char *val[4]; char *dn; + char **attr_list; + pstring filter; + + type = (id_type & ID_USERID) ? + get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) : + get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); + + snprintf(filter, sizeof(filter)-1, "(objectClass=%s)", LDAP_OBJ_IDPOOL); + + attr_list = get_attr_list( idpool_attr_list ); + rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, "(objectClass=unixIdPool)", - pool_attr, 0, &result); + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &result); + free_attr_list( attr_list ); + if (rc != LDAP_SUCCESS) { - DEBUG(0,("ldap_allocate_id: unixIdPool object not found\n")); + DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL)); goto out; } count = ldap_count_entries(ldap_state.ldap_struct, result); if (count != 1) { - DEBUG(0,("ldap_allocate_id: single unixIdPool not found\n")); + DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL)); goto out; } @@ -580,210 +546,303 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) type)); goto out; } - if (id_type & ID_USERID) { + + if (id_type & ID_USERID) id->uid = strtoul(id_str, NULL, 10); - } else { + else id->gid = strtoul(id_str, NULL, 10); - } + mod[0].mod_op = LDAP_MOD_DELETE; mod[0].mod_type = strdup(type); - val[0] = id_str; val[1] = NULL; + val[0] = id_str; + val[1] = NULL; mod[0].mod_values = val; - pstr_sprintf(new_id_str, "%ud", + snprintf(new_id_str, sizeof(new_id_str), "%u", ((id_type & ID_USERID) ? id->uid : id->gid) + 1); mod[1].mod_op = LDAP_MOD_ADD; mod[1].mod_type = strdup(type); - val[3] = new_id_str; val[4] = NULL; + val[2] = new_id_str; + val[3] = NULL; mod[1].mod_values = val + 2; - mods[0] = mod; mods[1] = mod + 1; mods[2] = NULL; + mods[0] = mod; \ + mods[1] = mod + 1; + mods[2] = NULL; + rc = ldap_modify_s(ldap_state.ldap_struct, dn, mods); + ldap_memfree(dn); + + SAFE_FREE( mod[0].mod_type ); + SAFE_FREE( mod[1].mod_type ); - if (rc == LDAP_SUCCESS) ret = NT_STATUS_OK; + if (rc != LDAP_SUCCESS) { + DEBUG(0,("ldap_allocate_id: Failed to allocate new %s. ldap_modify() failed.\n", + type)); + goto out; + } + + ret = NT_STATUS_OK; out: return ret; } -/* Get a sid from an id */ +/***************************************************************************** + get a sid from an id +*****************************************************************************/ + static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) { LDAPMessage *result = 0; LDAPMessage *entry = 0; pstring sid_str; pstring filter; - char type = (id_type & ID_USERID) ? 'u' : 'g'; + const char *type; int rc; int count; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - pstr_sprintf(filter, "(&(%cidNumber=%ud)(objectClass=sambaAccount))", - type, ((id_type & ID_USERID) ? id.uid : id.gid)); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, attrs, 0, - &result); - if (rc != LDAP_SUCCESS) { - goto out; - } + char **attr_list; + + type = (id_type & ID_USERID) ? + get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) : + get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); + + /* first we try for a samba user or group mapping */ + + if ( id_type & ID_USERID ) { + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", + LDAP_OBJ_SAMBASAMACCOUNT, type, id.uid ); + } + else { + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", + LDAP_OBJ_GROUPMAP, type, id.gid ); + } + + attr_list = get_attr_list( sidmap_attr_list ); + rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + if (rc != LDAP_SUCCESS) + goto out; + count = ldap_count_entries(ldap_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) { - pstr_sprintf(filter, - "(&(objectClass=idmapEntry)(%cidNumber=%ud))", - type, ((id_type & ID_USERID) ? id.uid : id.gid)); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, - attrs, 0, &result); - if (rc != LDAP_SUCCESS) { + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", + LDAP_OBJ_IDMAP_ENTRY, type, ((id_type & ID_USERID) ? id.uid : id.gid)); + + rc = ldap_idmap_search(&ldap_state, lp_ldap_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.ldap_struct, result); } if (count != 1) { - DEBUG(0,("ldap_get_sid_from_id: mapping not found for " - "%cid: %ud\n", (id_type&ID_USERID)?'u':'g', - ((id_type & ID_USERID) ? id.uid : id.gid))); + DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %u\n", + type, ((id_type & ID_USERID) ? id.uid : id.gid))); goto out; } entry = ldap_first_entry(ldap_state.ldap_struct, result); - if (!ldap_idmap_attribute(&ldap_state, entry, "ntSid", sid_str)) { + if ( !ldap_idmap_attribute(&ldap_state, entry, LDAP_ATTRIBUTE_SID, sid_str) ) goto out; - } - if (!string_to_sid(sid, sid_str)) { + if (!string_to_sid(sid, sid_str)) goto out; - } ret = NT_STATUS_OK; out: + free_attr_list( attr_list ); + return ret; } -/* Get an id from a sid */ -static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, - const DOM_SID *sid) +/*********************************************************************** + Get an id from a sid +***********************************************************************/ + +static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) { LDAPMessage *result = 0; LDAPMessage *entry = 0; pstring sid_str; pstring filter; pstring id_str; - const char *type = (*id_type & ID_USERID) ? "uidNumber" : "gidNumber"; - const char *class = - (*id_type & ID_USERID) ? "sambaAccount" : "sambaGroupMapping"; + const char *type; + const char *obj_class; int rc; int count; + char **attr_list; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + /* first try getting the mapping from a samba user or group */ + + if ( *id_type & ID_USERID ) { + type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); + obj_class = LDAP_OBJ_SAMBASAMACCOUNT; + } + else { + type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); + obj_class = LDAP_OBJ_GROUPMAP; + } sid_to_string(sid_str, sid); - pstr_sprintf(filter, "(&(objectClass=%s)(ntSid=%s)", class, sid_str); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); - if (rc != LDAP_SUCCESS) { + 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, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) goto out; - } + count = ldap_count_entries(ldap_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) { - pstr_sprintf(filter, - "(&(objectClass=idmapEntry)(ntSid=%s))", sid_str); + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%s))", + LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, - attrs, 0, &result); - if (rc != LDAP_SUCCESS) { - goto out; - } - count = ldap_count_entries(ldap_state.ldap_struct, result); + rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), + LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) + goto out; + + count = ldap_count_entries(ldap_state.ldap_struct, result); } - - /* our search filters may 2 objects in the case that a user and group - rid are the same */ - if (count != 1 && count != 2) { - DEBUG(0, - ("ldap_get_id_from_sid: incorrect number of objects\n")); + + if ( count > 1 ) { + DEBUG(0, ("ldap_get_id_from_sid: search %s returned more than on entry!\n", + filter)); goto out; } - entry = ldap_first_entry(ldap_state.ldap_struct, result); - if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) { - entry = ldap_next_entry(ldap_state.ldap_struct, entry); - - if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) { - int i; + /* 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 entry == NULL, then we will default to allocating a new id */ + + if ( !ldap_idmap_attribute(&ldap_state, entry, type, id_str) ) + { + int i; - for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) { - ret = ldap_allocate_id(id, *id_type); - if (NT_STATUS_IS_OK(ret)) { - break; - } - } - if (NT_STATUS_IS_OK(ret)) { - ret = ldap_set_mapping(sid, *id, *id_type); - } else { - DEBUG(0,("ldap_allocate_id: cannot acquire id" - " lock\n")); - } - } 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; + for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) + { + ret = ldap_allocate_id(id, *id_type); + if ( NT_STATUS_IS_OK(ret) ) + break; } - } else { - if ((*id_type & ID_USERID)) { + + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n")); + goto out; + } + + ret = ldap_set_mapping(sid, *id, *id_type); + + } + else + { + if ( (*id_type & ID_USERID) ) id->uid = strtoul(id_str, NULL, 10); - } else { + else id->gid = strtoul(id_str, NULL, 10); - } + ret = NT_STATUS_OK; } out: + free_attr_list( attr_list ); + return ret; } -/* This function cannot be called to modify a mapping, only set a new one */ +/*********************************************************************** + 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) { pstring dn, sid_str, id_str; - const char *type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; - LDAPMod *mods[3]; - LDAPMod mod[2]; - char *val[4]; + fstring type, obj_str, obj_str_val, attr_sid; + LDAPMod *mods[4]; + LDAPMod mod[3]; + char *val[6]; int rc; int attempts = 0; - pstr_sprintf(id_str, "%ud", ((id_type & ID_USERID) ? id.uid : id.gid)); - sid_to_string(sid_str, sid); - pstr_sprintf(dn, "%s=%ud,%s", type, ((id_type & ID_USERID) ? id.uid : id.gid), lp_ldap_suffix()); - mod[0].mod_op = LDAP_MOD_REPLACE; - mod[0].mod_type = strdup(type); - val[0] = id_str; val[1] = NULL; + if ( id_type & ID_USERID ) + fstrcpy( type, get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) ); + else + fstrcpy( type, get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ) ); + + snprintf(dn, sizeof(dn), "%s=%u,%s", type, ((id_type & ID_USERID) ? id.uid : id.gid), + lp_ldap_suffix()); + + fstrcpy( obj_str, "objectClass" ); + fstrcpy( obj_str_val, LDAP_OBJ_IDMAP_ENTRY ); + fstrcpy( attr_sid, LDAP_ATTRIBUTE_SID ); + + /* objectClass */ + + mod[0].mod_op = LDAP_MOD_ADD; + mod[0].mod_type = obj_str; + val[0] = obj_str_val; + val[1] = NULL; mod[0].mod_values = val; - mod[1].mod_op = LDAP_MOD_REPLACE; - mod[1].mod_type = strdup("ntSid"); - val[2] = sid_str; val[3] = NULL; - mod[1].mod_values = val + 2; + /* uid or gid */ + + snprintf(id_str, sizeof(id_str), "%u", ((id_type & ID_USERID) ? id.uid : id.gid)); + mod[1].mod_op = LDAP_MOD_ADD; + mod[1].mod_type = type; + val[2] = id_str; + val[3] = NULL; + mod[1].mod_values = val+2; - mods[0] = mod; mods[1] = mod + 1; mods[2] = NULL; + /* SID */ + + sid_to_string(sid_str, sid); + mod[2].mod_op = LDAP_MOD_ADD; + mod[2].mod_type = attr_sid; + val[4] = sid_str; + val[5] = NULL; + mod[2].mod_values = val+4; + + mods[0] = mod; + mods[1] = mod + 1; + mods[2] = mod + 2; + mods[3] = NULL; do { - if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) != - LDAP_SUCCESS) continue; + if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) != LDAP_SUCCESS) + continue; - rc = ldap_modify_s(ldap_state.ldap_struct, dn, mods); + rc = ldap_add_s(ldap_state.ldap_struct, dn, mods); } while ((rc == LDAP_SERVER_DOWN) && (attempts <= 8)); + 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)); 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)); return NT_STATUS_OK; } @@ -799,7 +858,10 @@ static NTSTATUS ldap_idmap_init(void) return NT_STATUS_OK; } -/* End the LDAP session */ +/***************************************************************************** + End the LDAP session +*****************************************************************************/ + static NTSTATUS ldap_idmap_close(void) { if (ldap_state.ldap_struct != NULL) { |