diff options
author | Simo Sorce <idra@samba.org> | 2003-11-15 00:47:29 +0000 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2003-11-15 00:47:29 +0000 |
commit | e762e323897cd4ba3445016b6904136264082d25 (patch) | |
tree | 2268d5a8a60d321e8ec0a504d9f5510acc99061d | |
parent | 7301471a6a12244cd398e3c81c310ffc2b663c53 (diff) | |
download | samba-e762e323897cd4ba3445016b6904136264082d25.tar.gz samba-e762e323897cd4ba3445016b6904136264082d25.tar.bz2 samba-e762e323897cd4ba3445016b6904136264082d25.zip |
Split smbldap in a core file and a utility file
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
(This used to be commit 207968eafc2c2a185e50e2132702d7bab2142aba)
-rw-r--r-- | source3/Makefile.in | 16 | ||||
-rw-r--r-- | source3/configure.in | 10 | ||||
-rw-r--r-- | source3/include/includes.h | 1 | ||||
-rw-r--r-- | source3/include/modconf.h | 34 | ||||
-rw-r--r-- | source3/lib/smbldap.c | 175 | ||||
-rw-r--r-- | source3/lib/smbldap_util.c | 203 | ||||
-rw-r--r-- | source3/param/config_ldap.c | 354 | ||||
-rw-r--r-- | source3/param/loadparm.c | 10 | ||||
-rw-r--r-- | source3/param/modconf.c | 96 |
9 files changed, 720 insertions, 179 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index f7e13220c4..6141fd500b 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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@ diff --git a/source3/configure.in b/source3/configure.in index 8093e341ae..b8c8eeaaa0 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -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]) ################################################# diff --git a/source3/include/includes.h b/source3/include/includes.h index c463f99a90..92c5f847dd 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -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/source3/include/modconf.h b/source3/include/modconf.h new file mode 100644 index 0000000000..f5cc5ef488 --- /dev/null +++ b/source3/include/modconf.h @@ -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_ */ diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index fe34cfb852..ac35ed2a03 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -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/source3/lib/smbldap_util.c b/source3/lib/smbldap_util.c new file mode 100644 index 0000000000..f6097599bc --- /dev/null +++ b/source3/lib/smbldap_util.c @@ -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/source3/param/config_ldap.c b/source3/param/config_ldap.c new file mode 100644 index 0000000000..ad9b515381 --- /dev/null +++ b/source3/param/config_ldap.c @@ -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); +} diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 37644c738f..3aeb80b7f0 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -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/source3/param/modconf.c b/source3/param/modconf.c new file mode 100644 index 0000000000..a9ab6f9b4a --- /dev/null +++ b/source3/param/modconf.c @@ -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(); +} |