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 /source3/param | |
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)
Diffstat (limited to 'source3/param')
-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 |
3 files changed, 460 insertions, 0 deletions
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(); +} |