Split smbldap in a core file and a utility file
authorSimo Sorce <idra@samba.org>
Sat, 15 Nov 2003 00:47:29 +0000 (00:47 +0000)
committerSimo Sorce <idra@samba.org>
Sat, 15 Nov 2003 00:47:29 +0000 (00:47 +0000)
Add module support for configuration loading

Add a first implementation of config_ldap module to put samba configuration
on ldap

It worked on my test machine, please try it out and send bugfixes :-)

have fun,
Simo.

INSTRUCTIONS:

Just add something like  this to your smb.conf file:
        config backend = config_ldap:ldap://localhost
        config_ldap:basedn = dc=samba,dc=org

the config tree must follow this scheme:
   ou=foo, dc=samba, dc=org <- global section
   |- sambaOptionName=log level, ou=foo, ...  <- options
   |- ...
   |- sambaShareName=testlc, ou=foo, ...  == [testlc]
      |- sambaOptionName=path, sambaShareName=testlc, ou=foo, ... <- option

here is a sample ldif:
# foo, samba, org
dn: ou=foo, dc=samba, dc=org
objectClass: organizationalUnit
objectClass: sambaConfig
ou: foo
description: Test Foo

# log level, foo, samba, org
dn: sambaOptionName=log level, ou=foo, dc=samba, dc=org
objectClass: sambaConfigOption
sambaOptionName: log level
sambaIntegerOption: 10
description: log level 10 is suitable for good debugging

# testlc, foo, samba, org
dn: sambaShareName=testlc, ou=foo, dc=samba, dc=org
objectClass: sambaShare
sambaShareName: testlc
description: share to test ldap config module actually works

# path, testlc, foo, samba, org
dn: sambaOptionName=path, sambaShareName=testlc, ou=foo, dc=samba, dc=org
objectClass: sambaConfigOption
sambaOptionName: path
sambaStringOption: /tmp
description: Path for share testlc

# read only, testlc, foo, samba, org
dn: sambaOptionName=read only, sambaShareName=testlc, ou=foo, dc=samba,
dc=org
objectClass: sambaConfigOption
sambaOptionName: read only
sambaBoolOption: TRUE
description: Share testlc is read only

# guest ok, testlc, foo, samba, org
dn: sambaOptionName=guest ok, sambaShareName=testlc, ou=foo, dc=samba,
dc=org
objectClass: sambaConfigOption
sambaOptionName: guest ok
sambaBoolOption: TRUE
description: Guest users are allowed to connect to testlc share

source/Makefile.in
source/configure.in
source/include/includes.h
source/include/modconf.h [new file with mode: 0644]
source/lib/smbldap.c
source/lib/smbldap_util.c [new file with mode: 0644]
source/param/config_ldap.c [new file with mode: 0644]
source/param/loadparm.c
source/param/modconf.c [new file with mode: 0644]

index f7e13220c49ba07657ba295f0eb895176207c8aa..6141fd500be79ca3900cb8340cf05f9c6259fb9e 100644 (file)
@@ -66,6 +66,7 @@ RPCLIBDIR = $(LIBDIR)/rpc
 IDMAPLIBDIR = $(LIBDIR)/idmap
 CHARSETLIBDIR = $(LIBDIR)/charset
 AUTHLIBDIR = $(LIBDIR)/auth
+CONFIGLIBDIR = $(LIBDIR)/config
 CONFIGDIR = @configdir@
 VARDIR = @localstatedir@
 MANDIR = @mandir@
@@ -154,7 +155,8 @@ RPC_MODULES = @RPC_MODULES@
 IDMAP_MODULES = @IDMAP_MODULES@
 CHARSET_MODULES = @CHARSET_MODULES@
 AUTH_MODULES = @AUTH_MODULES@
-MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSET_MODULES) $(AUTH_MODULES)
+CONFIG_MODULES = @CONFIG_MODULES@
+MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSET_MODULES) $(AUTH_MODULES) $(CONFIG_MODULES)
 
 ######################################################################
 # object file lists
@@ -163,7 +165,7 @@ 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 tdb/tdbback.o
 
-SMBLDAP_OBJ = @SMBLDAP@
+SMBLDAP_OBJ = @SMBLDAP@ @SMBLDAPUTIL@
 
 LIB_OBJ = lib/version.o lib/charcnv.o lib/debug.o lib/fault.o \
           lib/getsmbpass.o lib/interface.o lib/md4.o \
@@ -198,7 +200,7 @@ POPT_LIB_OBJ = lib/popt_common.o
 UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
             ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o 
 
-PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o
+PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o param/modconf.o
 
 KRBCLIENT_OBJ = libads/kerberos.o
 
@@ -340,6 +342,8 @@ AUTH_OBJ = auth/auth.o @AUTH_STATIC@ auth/auth_util.o auth/auth_compat.o \
 
 MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_map.o smbd/mangle_hash2.o
 
+CONFIG_LDAP_OBJ = param/config_ldap.o
+
 SMBD_OBJ_MAIN = smbd/server.o
 
 BUILDOPT_OBJ = smbd/build_options.o
@@ -1155,6 +1159,11 @@ bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ:.o=.@PICSUFFIX@)
        @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ:.o=.@PICSUFFIX@) \
                @SONAMEFLAG@`basename $@`
 
+bin/config_ldap.@SHLIBEXT@: $(CONFIG_LDAP_OBJ:.o=.@PICSUFFIX@)
+       @echo "Building plugin $@"
+        @$(SHLD) $(LDSHFLAGS) -o $@ $(CONFIG_LDAP_OBJ:.o=.@PICSUFFIX@) \
+               @SMBLDAP@ @LDAP_LIBS@ @SONAMEFLAG@`basename $@`
+
 bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@
@@ -1223,6 +1232,7 @@ installmodules: modules installdirs
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(IDMAPLIBDIR) $(IDMAP_MODULES)
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(CHARSETLIBDIR) $(CHARSET_MODULES)
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(AUTHLIBDIR) $(AUTH_MODULES)
+       @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(CONFIGLIBDIR) $(CONFIG_MODULES)
        @# These symlinks are required for the 'probing' of modules. 
        @# This mechanism should go at some point..
        @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ ldapsam_compat.@SHLIBEXT@
index 8093e341aea3ba7f7a2c18428edca2fdd777aa0e..b8c8eeaaa02e8a767cce5c5dfcf36c620f21dc48 100644 (file)
@@ -162,6 +162,7 @@ AC_SUBST(SMBWRAPPER)
 AC_SUBST(EXTRA_BIN_PROGS)
 AC_SUBST(EXTRA_SBIN_PROGS)
 AC_SUBST(EXTRA_ALL_TARGETS)
+AC_SUBST(CONFIG_LIBS)
 
 AC_ARG_ENABLE(debug, 
 [  --enable-debug          Turn on compiler debugging information (default=no)],
@@ -299,7 +300,7 @@ dnl These have to be built static:
 default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss rpc_epmapper auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin pdb_gums gums_tdbsam2"
 
 dnl These are preferably build shared, and static if dlopen() is not available
-default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap charset_CP850 charset_CP437"
+default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap charset_CP850 charset_CP437 config_ldap"
 
 if test "x$developer" = xyes; then
    default_static_modules="$default_static_modules rpc_echo"
@@ -2288,6 +2289,8 @@ AC_MSG_RESULT($with_ldap_support)
 
 SMBLDAP=""
 AC_SUBST(SMBLDAP)
+SMBLDAPUTIL=""
+AC_SUBST(SMBLDAPUTIL)
 if test x"$with_ldap_support" != x"no"; then
 
   ##################################################################
@@ -2343,7 +2346,9 @@ if test x"$with_ldap_support" != x"no"; then
   if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes" -a x"$ac_cv_func_ext_ldap_domain2hostlist" = x"yes"; then
     AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
     default_static_modules="$default_static_modules pdb_ldap idmap_ldap";
+    default_shared_modules="$default_shared_modules config_ldap";
     SMBLDAP="lib/smbldap.o"
+    SMBLDAPUTIL="lib/smbldap_util.o"
     with_ldap_support=yes
     AC_MSG_CHECKING(whether LDAP support is used)
     AC_MSG_RESULT(yes)
@@ -4194,6 +4199,9 @@ SMB_MODULE(vfs_readonly, \$(VFS_READONLY_OBJ), "bin/readonly.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS)
 SMB_SUBSYSTEM(VFS,smbd/vfs.o)
 
+SMB_MODULE(config_ldap, param/config_ldap.o, "bin/config_ldap.$SHLIBEXT", CONFIG, [ CONFIG_LIBS="$CONFIG_LIBS $LDAP_LIBS" "$SMBLDAP" ])
+SMB_SUBSYSTEM(CONFIG, param/modconf.o)
+
 AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules])
 
 #################################################
index c463f99a90d71649958b3c6de6d3ba5bf5fbd3c5..92c5f847ddbed0194ffb772280f80fc04a475282 100644 (file)
@@ -890,6 +890,7 @@ struct smb_ldap_privates;
 /* forward declarations from smbldap.c */
 
 #include "smbldap.h"
+#include "modconf.h"
 
 /***** automatically generated prototypes *****/
 #ifndef NO_PROTO_H
diff --git a/source/include/modconf.h b/source/include/modconf.h
new file mode 100644 (file)
index 0000000..f5cc5ef
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _MODCONF_H_
+#define _MODCONF_H_
+/* 
+   Unix SMB/CIFS implementation.
+
+   ModConf headers
+
+   Copyright (C) Simo Sorce 2003
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library 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
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#define SAMBA_CONFIG_INTERFACE_VERSION 1
+
+/* Filled out by config backends */
+struct config_functions {
+       NTSTATUS (*init)(char *params);
+       NTSTATUS (*load)(BOOL (*sfunc)(const char *),BOOL (*pfunc)(const char *, const char *));
+       NTSTATUS (*close)(void);
+};
+#endif /* _MODCONF_H_ */
index fe34cfb852e136767e79e0203df0e191160b0a6e..ac35ed2a033aae71b958985b256f244bdb8e52e9 100644 (file)
@@ -1153,181 +1153,6 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_
        return NT_STATUS_OK;
 }
 
-/**********************************************************************
- Add the sambaDomain to LDAP, so we don't have to search for this stuff
- again.  This is a once-add operation for now.
-
- TODO:  Add other attributes, and allow modification.
-*********************************************************************/
-static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, 
-                                    const char *domain_name) 
-{
-       fstring sid_string;
-       fstring algorithmic_rid_base_string;
-       pstring filter, dn;
-       LDAPMod **mods = NULL;
-       int rc;
-       int ldap_op;
-       LDAPMessage *result = NULL;
-       int num_result;
-       char **attr_list;
-       uid_t u_low, u_high;
-       gid_t g_low, g_high;
-       uint32 rid_low, rid_high;
-
-       slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", 
-                 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
-                 domain_name, LDAP_OBJ_DOMINFO);
-
-       attr_list = get_attr_list( dominfo_attr_list );
-       rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
-       free_attr_list( attr_list );
-
-       if (rc != LDAP_SUCCESS) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       num_result = ldap_count_entries(ldap_state->ldap_struct, result);
-       
-       if (num_result > 1) {
-               DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       
-       /* Check if we need to add an entry */
-       DEBUG(3,("Adding new domain\n"));
-       ldap_op = LDAP_MOD_ADD;
-
-       pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
-               domain_name, lp_ldap_suffix());
-
-       /* Free original search */
-       ldap_msgfree(result);
-
-       /* make the changes - the entry *must* not already have samba attributes */
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
-               domain_name);
-
-       /* If we don't have an entry, then ask secrets.tdb for what it thinks.  
-          It may choose to make it up */
-
-       sid_to_string(sid_string, get_global_sam_sid());
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string);
-
-       slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base());
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), 
-                       algorithmic_rid_base_string);
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
-       
-       /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set.
-          TODO: fix all the places where the line between idmap and normal operations
-          needed by smbd gets fuzzy   --jerry 2003-08-11                              */
-       
-       if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high)
-               && get_free_rid_range(&rid_low, &rid_high) ) 
-       {
-               fstring rid_str;
-               
-               fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE );
-               DEBUG(10,("setting next available user rid [%s]\n", rid_str));
-               smbldap_set_mod(&mods, LDAP_MOD_ADD, 
-                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), 
-                       rid_str);
-                       
-               fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE );
-               DEBUG(10,("setting next available group rid [%s]\n", rid_str));
-               smbldap_set_mod(&mods, LDAP_MOD_ADD, 
-                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), 
-                       rid_str);
-               
-        }
-
-
-       switch(ldap_op)
-       {
-       case LDAP_MOD_ADD: 
-               rc = smbldap_add(ldap_state, dn, mods);
-               break;
-       case LDAP_MOD_REPLACE: 
-               rc = smbldap_modify(ldap_state, dn, mods);
-               break;
-       default:        
-               DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-       
-       if (rc!=LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
-               DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n",
-                      ldap_op == LDAP_MOD_ADD ? "add" : "modify",
-                      dn, ldap_err2string(rc),
-                      ld_error?ld_error:"unknown"));
-               SAFE_FREE(ld_error);
-
-               ldap_mods_free(mods, True);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name));
-       ldap_mods_free(mods, True);
-       return NT_STATUS_OK;
-}
-
-/**********************************************************************
-Search for the domain info entry
-*********************************************************************/
-NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
-                                    LDAPMessage ** result, const char *domain_name,
-                                    BOOL try_add)
-{
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       pstring filter;
-       int rc;
-       char **attr_list;
-       int count;
-
-       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
-               LDAP_OBJ_DOMINFO,
-               get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
-               domain_name);
-
-       DEBUG(2, ("Searching for:[%s]\n", filter));
-
-
-       attr_list = get_attr_list( dominfo_attr_list );
-       rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
-       free_attr_list( attr_list );
-
-       if (rc != LDAP_SUCCESS) {
-               DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
-               DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
-       } else if (ldap_count_entries(ldap_state->ldap_struct, *result) < 1) {
-               DEBUG(3, ("Got no domain info entries for domain\n"));
-               ldap_msgfree(*result);
-               *result = NULL;
-               if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name))) {
-                       return smbldap_search_domain_info(ldap_state, result, domain_name, False);
-               } 
-               else {
-                       DEBUG(0, ("Adding domain info for %s failed with %s\n", 
-                               domain_name, nt_errstr(ret)));
-                       return ret;
-               }
-       } else if ((count = ldap_count_entries(ldap_state->ldap_struct, *result)) > 1) {
-               DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
-                         count, domain_name));
-               ldap_msgfree(*result);
-               *result = NULL;
-               return ret;
-       } else {
-               return NT_STATUS_OK;
-       }
-       
-       return ret;
-}
-
 /*******************************************************************
  Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX.
 ********************************************************************/
diff --git a/source/lib/smbldap_util.c b/source/lib/smbldap_util.c
new file mode 100644 (file)
index 0000000..f609759
--- /dev/null
@@ -0,0 +1,203 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   LDAP protocol helper functions for SAMBA
+   Copyright (C) Jean François Micouleau       1998
+   Copyright (C) Gerald Carter                 2001-2003
+   Copyright (C) Shahms King                   2001
+   Copyright (C) Andrew Bartlett               2002-2003
+   Copyright (C) Stefan (metze) Metzmacher     2002-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"
+
+/**********************************************************************
+ Add the sambaDomain to LDAP, so we don't have to search for this stuff
+ again.  This is a once-add operation for now.
+
+ TODO:  Add other attributes, and allow modification.
+*********************************************************************/
+static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, 
+                                    const char *domain_name) 
+{
+       fstring sid_string;
+       fstring algorithmic_rid_base_string;
+       pstring filter, dn;
+       LDAPMod **mods = NULL;
+       int rc;
+       int ldap_op;
+       LDAPMessage *result = NULL;
+       int num_result;
+       char **attr_list;
+       uid_t u_low, u_high;
+       gid_t g_low, g_high;
+       uint32 rid_low, rid_high;
+
+       slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", 
+                 get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
+                 domain_name, LDAP_OBJ_DOMINFO);
+
+       attr_list = get_attr_list( dominfo_attr_list );
+       rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
+       free_attr_list( attr_list );
+
+       if (rc != LDAP_SUCCESS) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       num_result = ldap_count_entries(ldap_state->ldap_struct, result);
+       
+       if (num_result > 1) {
+               DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
+               ldap_msgfree(result);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+       
+       /* Check if we need to add an entry */
+       DEBUG(3,("Adding new domain\n"));
+       ldap_op = LDAP_MOD_ADD;
+
+       pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+               domain_name, lp_ldap_suffix());
+
+       /* Free original search */
+       ldap_msgfree(result);
+
+       /* make the changes - the entry *must* not already have samba attributes */
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
+               domain_name);
+
+       /* If we don't have an entry, then ask secrets.tdb for what it thinks.  
+          It may choose to make it up */
+
+       sid_to_string(sid_string, get_global_sam_sid());
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string);
+
+       slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base());
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), 
+                       algorithmic_rid_base_string);
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
+       
+       /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set.
+          TODO: fix all the places where the line between idmap and normal operations
+          needed by smbd gets fuzzy   --jerry 2003-08-11                              */
+       
+       if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high)
+               && get_free_rid_range(&rid_low, &rid_high) ) 
+       {
+               fstring rid_str;
+               
+               fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE );
+               DEBUG(10,("setting next available user rid [%s]\n", rid_str));
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, 
+                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), 
+                       rid_str);
+                       
+               fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE );
+               DEBUG(10,("setting next available group rid [%s]\n", rid_str));
+               smbldap_set_mod(&mods, LDAP_MOD_ADD, 
+                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), 
+                       rid_str);
+               
+        }
+
+
+       switch(ldap_op)
+       {
+       case LDAP_MOD_ADD: 
+               rc = smbldap_add(ldap_state, dn, mods);
+               break;
+       case LDAP_MOD_REPLACE: 
+               rc = smbldap_modify(ldap_state, dn, mods);
+               break;
+       default:        
+               DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       
+       if (rc!=LDAP_SUCCESS) {
+               char *ld_error = NULL;
+               ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+               DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n",
+                      ldap_op == LDAP_MOD_ADD ? "add" : "modify",
+                      dn, ldap_err2string(rc),
+                      ld_error?ld_error:"unknown"));
+               SAFE_FREE(ld_error);
+
+               ldap_mods_free(mods, True);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name));
+       ldap_mods_free(mods, True);
+       return NT_STATUS_OK;
+}
+
+/**********************************************************************
+Search for the domain info entry
+*********************************************************************/
+NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
+                                    LDAPMessage ** result, const char *domain_name,
+                                    BOOL try_add)
+{
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       pstring filter;
+       int rc;
+       char **attr_list;
+       int count;
+
+       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
+               LDAP_OBJ_DOMINFO,
+               get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
+               domain_name);
+
+       DEBUG(2, ("Searching for:[%s]\n", filter));
+
+
+       attr_list = get_attr_list( dominfo_attr_list );
+       rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
+       free_attr_list( attr_list );
+
+       if (rc != LDAP_SUCCESS) {
+               DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
+               DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
+       } else if (ldap_count_entries(ldap_state->ldap_struct, *result) < 1) {
+               DEBUG(3, ("Got no domain info entries for domain\n"));
+               ldap_msgfree(*result);
+               *result = NULL;
+               if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name))) {
+                       return smbldap_search_domain_info(ldap_state, result, domain_name, False);
+               } 
+               else {
+                       DEBUG(0, ("Adding domain info for %s failed with %s\n", 
+                               domain_name, nt_errstr(ret)));
+                       return ret;
+               }
+       } else if ((count = ldap_count_entries(ldap_state->ldap_struct, *result)) > 1) {
+               DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
+                         count, domain_name));
+               ldap_msgfree(*result);
+               *result = NULL;
+               return ret;
+       } else {
+               return NT_STATUS_OK;
+       }
+       
+       return ret;
+}
+
diff --git a/source/param/config_ldap.c b/source/param/config_ldap.c
new file mode 100644 (file)
index 0000000..ad9b515
--- /dev/null
@@ -0,0 +1,354 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   ModConfig LDAP backend
+
+   Copyright (C) Simo Sorce            2003
+   Copyright (C) Jim McDonough <jmcd@us.ibm.com>       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
+   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"
+
+/*#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_CONFIG
+*/
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "smbldap.h"
+
+#define LDAP_OBJ_SAMBA_CONFIG          "sambaConfig"
+#define LDAP_OBJ_SAMBA_SHARE           "sambaShare"
+#define LDAP_OBJ_SAMBA_OPTION          "sambaConfigOption"
+
+#define LDAP_ATTR_LIST_END     0
+#define LDAP_ATTR_BOOL         1
+#define LDAP_ATTR_INTEGER      2
+#define LDAP_ATTR_STRING       3
+#define LDAP_ATTR_LIST         4
+#define LDAP_ATTR_NAME         5
+
+
+struct ldap_config_state {
+       struct smbldap_state *smbldap_state;
+       TALLOC_CTX *mem_ctx;
+};
+
+ATTRIB_MAP_ENTRY option_attr_list[] = {
+       { LDAP_ATTR_NAME,               "sambaOptionName"       },
+       { LDAP_ATTR_LIST,               "sambaListOption"       },
+       { LDAP_ATTR_STRING,             "sambaStringOption"     },
+       { LDAP_ATTR_INTEGER,            "sambaIntegerOption"    },
+       { LDAP_ATTR_BOOL,               "sambaBoolOption"       },
+       { LDAP_ATTR_LIST_END,           NULL                    }
+};
+
+static struct ldap_config_state ldap_state;
+static char *config_base_dn;
+
+static NTSTATUS ldap_config_close(void);
+
+/*
+TODO:
+       search each section
+       start with global, then with others
+       for each section parse all options
+*/
+
+static NTSTATUS parse_section(
+               const char *dn,
+               BOOL (*pfunc)(const char *, const char *))
+{
+       TALLOC_CTX *mem_ctx;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+       pstring filter;
+       pstring suffix;
+       pstring option_name;
+       pstring option_value;
+       char **attr_list = NULL;
+       char *temp;
+       int rc;
+       int count;
+
+       mem_ctx = talloc_init("parse_section");
+       
+       /* search for the options */
+       pstr_sprintf(filter, "objectClass=%s",
+                       LDAP_OBJ_SAMBA_OPTION);
+
+       DEBUG(0, ("Searching for:[%s]\n", filter));
+
+       attr_list = get_attr_list(option_attr_list);
+       rc = smbldap_search(ldap_state.smbldap_state,
+                               dn, LDAP_SCOPE_ONELEVEL,
+                               filter, attr_list, 0, &result);
+
+       if (rc != LDAP_SUCCESS) {
+               DEBUG(0,("parse_section: %s object not found\n", LDAP_OBJ_SAMBA_CONFIG));
+               goto done;
+       }
+
+       count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
+       entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
+       while (entry) {
+               int o;
+
+               if (!smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, "sambaOptionName", option_name)) {
+                       goto done;
+               }
+
+               option_value[0] = '\0';
+               for (o = 1; option_attr_list[o].name != NULL; o++) {
+                       if (smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, option_attr_list[o].name, option_value)) {
+                               break;
+                       }
+               }
+               if (option_value[0] != '\0') {
+                       if (!pfunc(option_name, option_value)) {
+                               goto done;
+                       }
+               } else {
+                       DEBUG(0,("parse_section: Missing value for option: %s\n", option_name));
+                       goto done;
+               }
+
+               entry = ldap_next_entry(ldap_state.smbldap_state->ldap_struct, entry);
+       }
+
+       ret = NT_STATUS_OK;
+
+done:
+       talloc_destroy(mem_ctx);
+       free_attr_list(attr_list);
+       if (result) ldap_msgfree(result);
+
+       return ret;
+}
+
+/*****************************************************************************
+ load configuration from ldap
+*****************************************************************************/
+
+static NTSTATUS ldap_config_load(
+               BOOL (*sfunc)(const char *),
+               BOOL (*pfunc)(const char *, const char *))
+{
+       TALLOC_CTX *mem_ctx;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+       pstring filter;
+       pstring suffix;
+       pstring attr_text;
+       char *config_dn = NULL;
+       char *temp;
+       int rc;
+       int count;
+       char *config_attr_list[] = {"description", NULL};
+       char *share_attr_list[] = {"sambaShareName", "description", NULL};
+       char **share_dn;
+       char **share_name;
+
+       mem_ctx = talloc_init("ldap_config_load");
+       
+       /* search for the base config dn */
+       pstr_sprintf(filter, "objectClass=%s",
+                       LDAP_OBJ_SAMBA_CONFIG);
+
+       DEBUG(0, ("Searching for:[%s]\n", filter));
+       
+       rc = smbldap_search(ldap_state.smbldap_state,
+                               config_base_dn, LDAP_SCOPE_SUBTREE,
+                               filter, config_attr_list, 0, &result);
+
+       if (rc != LDAP_SUCCESS) {
+               DEBUG(0,("ldap_config_load: %s object not found\n", LDAP_OBJ_SAMBA_CONFIG));
+               goto done;
+       }
+
+       count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
+       if (count != 1) {
+               DEBUG(0,("ldap_config_load: single %s object not found\n", LDAP_OBJ_SAMBA_CONFIG));
+               goto done;
+       }
+
+       if (!(temp = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result))) {
+               goto done;
+       }
+       config_dn = talloc_strdup(mem_ctx, temp);
+       SAFE_FREE(temp);
+       if (!config_dn) {
+               goto done;
+       }
+
+       entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
+
+       if (!smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, "description", attr_text)) {
+               DEBUG(0, ("ldap_config_load: no description field in %s object\n", LDAP_OBJ_SAMBA_CONFIG));
+       }
+
+       if (result) ldap_msgfree(result);
+/* TODO: finish up the last section, see loadparm's lp_load()*/
+       
+       /* retrive the section list */
+       pstr_sprintf(filter, "objectClass=%s",
+                       LDAP_OBJ_SAMBA_SHARE);
+
+       DEBUG(0, ("Searching for:[%s]\n", filter));
+       
+       rc = smbldap_search(ldap_state.smbldap_state,
+                               config_dn, LDAP_SCOPE_SUBTREE,
+                               filter, share_attr_list, 0, &result);
+
+       if (rc != LDAP_SUCCESS) {
+               DEBUG(0,("ldap_config_load: %s object not found\n", LDAP_OBJ_SAMBA_CONFIG));
+               goto done;
+       }
+
+       count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result);
+       DEBUG(0, ("config_ldap: Found %d shares\n", count));
+       if (count) {
+               int i;
+
+               share_dn = talloc(mem_ctx, (count + 1) * sizeof(char *));
+               share_name = talloc(mem_ctx, (count) * sizeof(char *));
+               if (!share_dn || !share_name) {
+                       DEBUG(0,("config_ldap: Out of memory!\n"));
+                       goto done;
+               }
+               entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result);
+               i = 0;
+               while (entry) {
+                       if (!(temp = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, entry))) {
+                               goto done;
+                       }
+                       if (!smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, "sambaShareName", attr_text)) {
+                               goto done;
+                       }
+                       share_dn[i] = talloc_strdup(mem_ctx, temp);
+                       share_name[i] = talloc_strdup(mem_ctx, attr_text);
+                       if (!share_dn[i] || !share_name[i]) {
+                               DEBUG(0,("config_ldap: Out of memory!\n"));
+                               goto done;
+                       }
+
+                       DEBUG(0, ("config_ldap: Found share [%s] (%s)\n", attr_text, temp));
+                       SAFE_FREE(temp);
+
+                       entry = ldap_next_entry(ldap_state.smbldap_state->ldap_struct, entry);
+                       i++;
+                       if (entry && (count == i)) {
+                               DEBUG(0, ("Error too many entryes in ldap result\n"));
+                               goto done;
+                       }
+               }
+               share_dn[i] = NULL;
+       }
+
+       /* parse global section*/
+       if (!sfunc("global")) {
+               goto done;
+       }
+       if (!NT_STATUS_IS_OK(parse_section(config_dn, pfunc))) {
+               goto done;
+       } else { /* parse shares */
+               int i;
+
+               for (i = 0; share_dn[i] != NULL; i++) {
+                       if (!sfunc(share_name[i])) {
+                               goto done;
+                       }
+                       if (!NT_STATUS_IS_OK(parse_section(share_dn[i], pfunc))) {
+                               goto done;
+                       }
+               }
+       }
+
+done:
+       talloc_destroy(mem_ctx);
+       if (result) ldap_msgfree(result);
+
+       return ret;
+}
+
+/*****************************************************************************
+ Initialise config_ldap module
+*****************************************************************************/
+
+static NTSTATUS ldap_config_init(char *params)
+{
+       NTSTATUS nt_status;
+       const char *location;
+       const char *basedn;
+
+       ldap_state.mem_ctx = talloc_init("config_ldap");
+       if (!ldap_state.mem_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* we assume only location is passed through an inline parameter
+        * other options go via parametrical options */
+       if (params) {
+               location = params;
+       } else {
+               location = lp_parm_const_string(GLOBAL_SECTION_SNUM, "config_ldap", "url", "ldap://localhost");
+       }
+       DEBUG(0,("config_ldap: location=%s\n", location));
+       basedn = lp_parm_const_string(GLOBAL_SECTION_SNUM, "config_ldap", "basedn", NULL);
+       if (basedn) config_base_dn = smb_xstrdup(basedn);
+       
+       if (!NT_STATUS_IS_OK(nt_status = 
+                            smbldap_init(ldap_state.mem_ctx, location, 
+                                         &ldap_state.smbldap_state))) {
+               talloc_destroy(ldap_state.mem_ctx);
+               DEBUG(0,("config_ldap: smbldap_init failed!\n"));
+               return nt_status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ End the LDAP session
+*****************************************************************************/
+
+static NTSTATUS ldap_config_close(void)
+{
+
+       smbldap_free_struct(&(ldap_state).smbldap_state);
+       talloc_destroy(ldap_state.mem_ctx);
+       
+       DEBUG(5,("The connection to the LDAP server was closed\n"));
+       /* maybe free the results here --metze */
+       
+       return NT_STATUS_OK;
+}
+
+static struct config_functions functions = {
+       ldap_config_init,
+       ldap_config_load,
+       ldap_config_close
+};
+
+NTSTATUS config_ldap_init(void)
+{
+       return smb_register_config(SAMBA_CONFIG_INTERFACE_VERSION, "ldap", &functions);
+}
index 37644c738f771085b96d1bc441fe62b0f2a55b2a..3aeb80b7f0c695fc6aa614ca1b9a6b5bd361424d 100644 (file)
@@ -95,6 +95,7 @@ struct _param_opt_struct {
  */
 typedef struct
 {
+       char *szConfigBackend;
        char *smb_ports;
        char *dos_charset;
        char *unix_charset;
@@ -755,6 +756,7 @@ static const struct enum_list enum_map_to_guest[] = {
 static struct parm_struct parm_table[] = {
        {N_("Base Options"), P_SEP, P_SEPARATOR}, 
 
+       {"config backend", P_STRING, P_GLOBAL, &Globals.szConfigBackend, NULL, NULL, FLAG_ADVANCED},
        {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED}, 
        {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED}, 
        {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED}, 
@@ -1302,6 +1304,8 @@ static void init_globals(void)
 
        DEBUG(3, ("Initialising global parameters\n"));
 
+       string_set(&Globals.szConfigBackend, NULL);
+
        string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
        string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
 
@@ -1604,6 +1608,7 @@ static char *lp_string(const char *s)
 #define FN_LOCAL_INTEGER(fn_name,val) \
  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
 
+FN_GLOBAL_STRING(lp_config_backend, &Globals.szConfigBackend)
 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
@@ -3952,6 +3957,11 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
                if (iServiceIndex >= 0)
                        bRetval = service_ok(iServiceIndex);
 
+       if (lp_config_backend()) {
+               modconf_init(lp_config_backend());
+               modconf_load(do_section, do_parameter);
+       }       
+
        lp_add_auto_services(lp_auto_services());
 
        if (add_ipc) {
diff --git a/source/param/modconf.c b/source/param/modconf.c
new file mode 100644 (file)
index 0000000..a9ab6f9
--- /dev/null
@@ -0,0 +1,96 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Configuration Modules Support
+   Copyright (C) Simo Sorce 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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+struct modconf_struct {
+       char *name;
+       struct config_functions *fns;
+};
+
+static struct modconf_struct module;
+
+NTSTATUS smb_register_config(int version, const char *name, struct config_functions *fns)
+{
+       if ((version != SAMBA_CONFIG_INTERFACE_VERSION)) {
+               DEBUG(0, ("smb_register_config: Failed to register config module.\n"
+                         "The module has been compiled with a different interface version (%d).\n"
+                         "The supported version is: %d\n",
+                         version, SAMBA_CONFIG_INTERFACE_VERSION));
+               return NT_STATUS_OBJECT_TYPE_MISMATCH;
+       }
+
+       if (!name || !name[0]) {
+               DEBUG(0,("smb_register_config: Name missing!\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       module.name = smb_xstrdup(name);
+       module.fns = fns;
+       DEBUG(5, ("smb_register_config: Successfully registeres config backend '%s'\n", name));
+       return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ * Init the configuration module
+ *********************************************************************/
+
+BOOL modconf_init(const char *config_backend)
+{
+       NTSTATUS ret;
+       BOOL bret = False;
+       char *name;
+       char *params;
+
+       /* nothing to do */
+       if (!config_backend)
+               return True;
+
+       name = smb_xstrdup(config_backend);
+       if ((params = strchr(name, ':')) != NULL ) {
+               *params = '\0';
+               params++;
+       }
+
+       ret = smb_probe_module("config", name);
+       
+       if (NT_STATUS_IS_OK(ret) && NT_STATUS_IS_OK(module.fns->init(params)))
+               bret = True;
+
+       SAFE_FREE(name);
+       return bret;
+}
+
+BOOL modconf_load(BOOL (*sfunc)(const char *),BOOL (*pfunc)(const char *, const char *))
+{
+       if (module.fns) {
+               if (NT_STATUS_IS_OK(module.fns->load(sfunc, pfunc))) {
+                       return True;
+               }
+       }
+       return False;
+}
+
+NTSTATUS modconf_close(void)
+{
+       return module.fns->close();
+}