/* Unix SMB/CIFS implementation. ModConfig LDAP backend Copyright (C) Simo Sorce 2003 Copyright (C) Jim McDonough 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 #include #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); }