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/lib/smbldap_util.c | |
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/lib/smbldap_util.c')
-rw-r--r-- | source3/lib/smbldap_util.c | 203 |
1 files changed, 203 insertions, 0 deletions
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; +} + |