working draft of the idmap_ldap code.
authorGerald Carter <jerry@samba.org>
Thu, 5 Jun 2003 02:34:30 +0000 (02:34 +0000)
committerGerald Carter <jerry@samba.org>
Thu, 5 Jun 2003 02:34:30 +0000 (02:34 +0000)
Includes sambaUnixIdPool objectclass

Still needs cleaning up wrt to name space.
More changes to come, but at least we now have a
a working distributed winbindd solution.
(This used to be commit 824175854421f7c27d31ad673a8790dd018ae350)

examples/LDAP/samba.schema
source3/Makefile.in
source3/configure.in
source3/include/includes.h
source3/include/smbldap.h [new file with mode: 0644]
source3/lib/smbldap.c [new file with mode: 0644]
source3/passdb/pdb_ldap.c
source3/sam/idmap_ldap.c

index 3db7094bf2507d4264371aa24c7b481d6a91139c..98879540451cf580d399b9d772e9484aa72ece85 100644 (file)
@@ -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 ))
+
index 945953fe48e3c7cacd657bcbf86bf3825551a909..df66f6a724325ada6a0b4300da4633cd428729af 100644 (file)
@@ -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)
index 79f01ba4219e3665e583dd78460629b9582b7264..53b4f1524f6295eea4a613fc79e5201b46fa4fe6 100644 (file)
@@ -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
index 4de81c46d28c49b87ee9ad2847f30686ad12cc5c..ac5c48d780f40374856762b20eb82eb6043db08a 100644 (file)
@@ -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 (file)
index 0000000..13451fa
--- /dev/null
@@ -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 (file)
index 0000000..5dbea06
--- /dev/null
@@ -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;
+}
+
index fb63e81d28be34ed7b082de1bfbbe4711e3370ba..e6fd12fd0e32231112979705774c68d5361bd484 100644 (file)
@@ -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 
@@ -286,52 +117,6 @@ static const char* get_userattr_key2string( int schema_ver, int key )
        return NULL;
 }
 
-/**********************************************************************
- 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;
index 22d9fd0666ad97c23d8d1c002b77f1bd3365d835..352b998cef32fee4d66abc3755fe2c6d394eaece 100644 (file)
@@ -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;
@@ -52,70 +56,6 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type);
 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.
 ******************************************************************/
@@ -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) {