From 2bc031e8fafeafdc58c6a8056597b647d00657ae Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Mon, 7 Dec 1998 22:52:49 +0000 Subject: [PATCH] added ldap files by Matthew Chapman. --- docs/yodldocs/LDAP.yo | 161 +++++++++++++ source/groupdb/aliasldap.c | 316 +++++++++++++++++++++++++ source/groupdb/builtinldap.c | 317 +++++++++++++++++++++++++ source/groupdb/groupldap.c | 318 +++++++++++++++++++++++++ source/passdb/passgrpldap.c | 190 +++++++++++++++ source/passdb/sampassldap.c | 433 +++++++++++++++++++++++++++++++++++ 6 files changed, 1735 insertions(+) create mode 100644 docs/yodldocs/LDAP.yo create mode 100644 source/groupdb/aliasldap.c create mode 100644 source/groupdb/builtinldap.c create mode 100644 source/groupdb/groupldap.c create mode 100644 source/passdb/passgrpldap.c create mode 100644 source/passdb/sampassldap.c diff --git a/docs/yodldocs/LDAP.yo b/docs/yodldocs/LDAP.yo new file mode 100644 index 00000000000..cf454904d33 --- /dev/null +++ b/docs/yodldocs/LDAP.yo @@ -0,0 +1,161 @@ +mailto(samba-bugs@samba.org) +article(LDAP Support in Samba)(Matthew Chapman)(29th November 1998 +htmltag(p)(1) htmltag(hr)(1) htmltag(h2)(1) +WARNING: This is experimental code. Use at your own risk, and please report +any bugs (after reading BUGS.txt). +htmltag(h2)(0) htmltag(br)(1) +) +redef(PARAGRAPH)(0)(htmlcommand(

+) txtcommand( + +)) + +sect(What is LDAP?) +A directory is a type of hierarchical database optimised for simple query +operations, often used for storing user information. LDAP is the +Lightweight Directory Access Protocol, a protocol which is rapidly +becoming the Internet standard for accessing directories. + +Many client applications now support LDAP (including Microsoft's Active +Directory), and there are a number of servers available. The most popular +implementation for Unix is from the em(University of Michigan); its +homepage is at url(tt(http://www.umich.edu/~dirsvcs/ldap/))(http://www.umich.edu/~dirsvcs/ldap/). + +Information in an LDAP tree always comes in tt(attribute=value) pairs. +The following is an example of a Samba user entry: + +verb(uid=jbloggs, dc=samba, dc=org +objectclass=sambaAccount +uid=jbloggs +cn=Joe Bloggs +description=Samba User +uidNumber=500 +gidNumber=500 +rid=2000 +grouprid=2001 +lmPassword=46E389809F8D55BB78A48108148AD508 +ntPassword=1944CCE1AD6F80D8AEC9FC5BE77696F4 +pwdLastSet=35C11F1B +smbHome=\\samba1\jbloggs +homeDrive=Z +script=logon.bat +profile=\\samba1\jbloggs\profile +workstations=JOE) + +Note that the top line is a special set of attributes called a +em(distinguished name) which identifies the location of this entry beneath +the directory's root node. Recent Internet standards suggest the use of +domain-based naming using tt(dc) attributes (for instance, a microsoft.com +directory should have a root node of tt(dc=microsoft, dc=com)), although +this is not strictly necessary for isolated servers. + +There are a number of LDAP-related FAQ's on the internet, although +generally the best source of information is the documentation for the +individual servers. + + +nl() +sect(Why LDAP and Samba?) + +Using an LDAP directory allows Samba to store user and group information +more reliably and flexibly than the current combination of smbpasswd, +smbgroup, groupdb and aliasdb with the Unix databases. If a need emerges +for extra user information to be stored, this can easily be added without +loss of backwards compatibility. + +In addition, the Samba LDAP schema is compatible with RFC2307, allowing +Unix password database information to be stored in the same entries. This +provides a single, consistent repository for both Unix and Windows user +information. + + +nl() +sect(Using LDAP with Samba) + +starteit() + +eit() Install and configure an LDAP server if you do not already have +one. You should read your LDAP server's documentation and set up the +configuration file and access control as desired. + +eit() Build Samba (latest CVS is required) with: + +verb( ./configure --with-ldap + make clean; make install) + +eit() Add the following options to the global section of tt(smb.conf) as +required. + +startdit() +dit(ldap suffix) + +This parameter specifies the node of the LDAP tree beneath which +Samba should store its information. This parameter MUST be provided +when using LDAP with Samba. + + bf(Default:) tt(none) + + bf(Example:) tt(ldap suffix = "dc=mydomain, dc=org") + +dit(ldap bind as) + +This parameter specifies the entity to bind to an LDAP directory as. +Usually it should be safe to use the LDAP root account; for larger +installations it may be preferable to restrict Samba's access. + + bf(Default:) tt(none (bind anonymously)) + + bf(Example:) tt(ldap bind as = "uid=root, dc=mydomain, dc=org") + +dit(ldap passwd file) + +This parameter specifies a file containing the password with which +Samba should bind to an LDAP server. For obvious security reasons +this file must be set to mode 700 or less. + + bf(Default:) tt(none (bind anonymously)) + + bf(Example:) tt(ldap passwd file = /usr/local/samba/private/ldappasswd) + +dit(ldap server) + +This parameter specifies the DNS name of the LDAP server to use +when storing and retrieving information about Samba users and +groups. + + bf(Default:) tt(ldap server = localhost) + +dit(ldap port) + +This parameter specifies the TCP port number of the LDAP server. + + bf(Default:) tt(ldap port = 389) + +enddit() + +eit() You should then be able to use the normal smbpasswd(8) command for +account administration (or User Manager in the near future). + +endeit() + + +nl() +sect(Using LDAP for Unix authentication) + +The Samba LDAP code was designed to utilise RFC2307-compliant directory +entries if available. RFC2307 is a proposed standard for LDAP user +information which has been adopted by a number of vendors. Further +information is available at url(tt(http://www.xedoc.com.au/~lukeh/ldap/))(http://www.xedoc.com.au/~lukeh/ldap). + +Of particular interest is Luke Howard's nameservice switch module +(nss_ldap) and PAM module (pam_ldap) implementing this standard, providing +LDAP-based password databases for Unix. If you are setting up a server to +provide integrated Unix/NT services than these are worth investigating. + + +nl() +sect(Compatibility with Active Directory) + +The current implementation is not designed to be used with Microsoft +Active Directory, although compatibility may be added in the future. + diff --git a/source/groupdb/aliasldap.c b/source/groupdb/aliasldap.c new file mode 100644 index 00000000000..35d810dabc2 --- /dev/null +++ b/source/groupdb/aliasldap.c @@ -0,0 +1,316 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0. + LDAP local group database for SAMBA + Copyright (C) Matthew Chapman 1998 + + 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" + +#ifdef WITH_LDAP + +#include +#include + +extern int DEBUGLEVEL; + +/* Internal state */ +extern LDAP *ldap_struct; +extern LDAPMessage *ldap_results; +extern LDAPMessage *ldap_entry; + +/* Static structure filled for requests */ +static LOCAL_GRP localgrp; + + +/*************************************************************** + Get group and membership information. + ****************************************************************/ + +static LOCAL_GRP *ldapalias_getgrp(LOCAL_GRP *group, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring temp; + char **values; + LOCAL_GRP_MEMBER *memblist; + char *value, *sep; + int i; + + if(!ldap_entry) + return NULL; + + if(!ldap_get_attribute("cn", group->name)) { + DEBUG(0, ("Missing cn\n")); + return NULL; } + + DEBUG(2,("Retrieving alias [%s]\n", group->name)); + + if(ldap_get_attribute("rid", temp)) { + group->rid = atoi(temp); + } else { + DEBUG(0, ("Missing rid\n")); + return NULL; + } + + if(!ldap_get_attribute("description", group->comment)) + group->comment[0] = 0; + + if(!members || !num_membs) { + ldap_entry = ldap_next_entry(ldap_struct, ldap_entry); + return group; + } + + if(values = ldap_get_values(ldap_struct, ldap_entry, "member")) { + + *num_membs = i = ldap_count_values(values); + *members = memblist = malloc(i * sizeof(LOCAL_GRP_MEMBER)); + + do { + value = values[--i]; + + if(!(sep = strchr(value, ','))) { + DEBUG(0, ("Malformed alias member\n")); + return NULL; + } + *(sep++) = 0; + fstrcpy(memblist[i].name, value); + + if(!(value = strchr(sep, ','))) { + DEBUG(0, ("Malformed alias member\n")); + return NULL; + } + *(value++) = 0; + string_to_sid(&memblist[i].sid, sep); + + if((memblist[i].sid_use = atoi(value)) + >= SID_NAME_UNKNOWN) + DEBUG(0, ("Invalid SID use in alias")); + + } while(i > 0); + + ldap_value_free(values); + + } else { + *num_membs = 0; + *members = NULL; + } + + return group; +} + + +/************************************************************************ + Queues the necessary modifications to save a LOCAL_GRP structure + ************************************************************************/ + +static void ldapalias_grpmods(LOCAL_GRP *group, LDAPMod ***mods, int operation) +{ + fstring temp; + + *mods = NULL; + + if(operation == LDAP_MOD_ADD) { /* immutable attributes */ + ldap_make_mod(mods, LDAP_MOD_ADD, "objectClass", "sambaAlias"); + ldap_make_mod(mods, LDAP_MOD_ADD, "cn", group->name); + + slprintf(temp, sizeof(temp)-1, "%d", (gid_t)(-1)); + ldap_make_mod(mods, LDAP_MOD_ADD, "gidNumber", temp); + + slprintf(temp, sizeof(temp)-1, "%d", group->rid); + ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp); + } + + ldap_make_mod(mods, operation, "description", group->comment); +} + + +/*************************************************************** + Begin/end smbgrp enumeration. + ****************************************************************/ + +static void *ldapalias_enumfirst(BOOL update) +{ + if (lp_server_role() == ROLE_DOMAIN_NONE) + return NULL; + + if (!ldap_open_connection(False)) + return NULL; + + ldap_search_for("objectClass=sambaAlias"); + + return ldap_struct; +} + +static void ldapalias_enumclose(void *vp) +{ + ldap_close_connection(); +} + + +/************************************************************************* + Save/restore the current position in a query + *************************************************************************/ + +static SMB_BIG_UINT ldapalias_getdbpos(void *vp) +{ + return (SMB_BIG_UINT)((ulong)ldap_entry); +} + +static BOOL ldapalias_setdbpos(void *vp, SMB_BIG_UINT tok) +{ + ldap_entry = (LDAPMessage *)((ulong)tok); + return (True); +} + + +/************************************************************************* + Return limited smb_passwd information, and group membership. + *************************************************************************/ + +static LOCAL_GRP *ldapalias_getgrpbynam(const char *name, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + LOCAL_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(cn=%s)(objectClass=sambaAlias))", name); + ldap_search_for(filter); + + ret = ldapalias_getgrp(&localgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static LOCAL_GRP *ldapalias_getgrpbygid(gid_t grp_id, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + LOCAL_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(gidNumber=%d)(objectClass=sambaAlias))", grp_id); + ldap_search_for(filter); + ret = ldapalias_getgrp(&localgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static LOCAL_GRP *ldapalias_getgrpbyrid(uint32 grp_rid, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + LOCAL_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(rid=%d)(objectClass=sambaAlias))", grp_rid); + ldap_search_for(filter); + ret = ldapalias_getgrp(&localgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static LOCAL_GRP *ldapalias_getcurrentgrp(void *vp, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + return ldapalias_getgrp(&localgrp, members, num_membs); +} + +static BOOL ldapalias_addgrp(LOCAL_GRP *group) +{ + LDAPMod **mods; + + ldapalias_grpmods(group, &mods, LDAP_MOD_ADD); + return ldap_makemods("cn", group->name, mods, True); +} + +static BOOL ldapalias_modgrp(LOCAL_GRP *group) +{ + LDAPMod **mods; + + ldapalias_grpmods(group, &mods, LDAP_MOD_REPLACE); + return ldap_makemods("cn", group->name, mods, False); +} + +static BOOL ldapalias_getusergroups(const char *name, LOCAL_GRP **groups, + int *num_grps) +{ + LOCAL_GRP *grouplist; + fstring filter; + int i; + + slprintf(filter, sizeof(pstring)-1, + "(&(member=%s,*)(objectclass=sambaAlias))", name); + ldap_search_for(filter); + + *num_grps = i = ldap_count_entries(ldap_struct, ldap_results); + + if(!i) { + *groups = NULL; + return (True); + } + + *groups = grouplist = malloc(i * sizeof(LOCAL_GRP)); + do { + i--; + } while(ldapalias_getgrp(&grouplist[i], NULL, NULL) && (i > 0)); + + return (True); +} + + +static struct aliasdb_ops ldapalias_ops = +{ + ldapalias_enumfirst, + ldapalias_enumclose, + ldapalias_getdbpos, + ldapalias_setdbpos, + + ldapalias_getgrpbynam, + ldapalias_getgrpbygid, + ldapalias_getgrpbyrid, + ldapalias_getcurrentgrp, + + ldapalias_addgrp, + ldapalias_modgrp, + + ldapalias_getusergroups +}; + +struct aliasdb_ops *ldap_initialise_alias_db(void) +{ + return &ldapalias_ops; +} + +#else + void aliasldap_dummy_function(void); + void aliasldap_dummy_function(void) { } /* stop some compilers complaining */ +#endif + diff --git a/source/groupdb/builtinldap.c b/source/groupdb/builtinldap.c new file mode 100644 index 00000000000..f2a530cbb95 --- /dev/null +++ b/source/groupdb/builtinldap.c @@ -0,0 +1,317 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0. + LDAP builtin group database for SAMBA + Copyright (C) Matthew Chapman 1998 + + 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" + +#ifdef WITH_LDAP + +#include +#include + +extern int DEBUGLEVEL; + +/* Internal state */ +extern LDAP *ldap_struct; +extern LDAPMessage *ldap_results; +extern LDAPMessage *ldap_entry; + +/* Static structure filled for requests */ +static LOCAL_GRP localgrp; + + +/*************************************************************** + Get group and membership information. + ****************************************************************/ + +static LOCAL_GRP *ldapbuiltin_getgrp(LOCAL_GRP *group, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring temp; + char **values; + LOCAL_GRP_MEMBER *memblist; + char *value, *sep; + int i; + + if(!ldap_entry) + return NULL; + + if(!ldap_get_attribute("cn", group->name)) { + DEBUG(0, ("Missing cn\n")); + return NULL; } + + DEBUG(2,("Retrieving alias [%s]\n", group->name)); + + if(ldap_get_attribute("rid", temp)) { + group->rid = atoi(temp); + } else { + DEBUG(0, ("Missing rid\n")); + return NULL; + } + + if(!ldap_get_attribute("description", group->comment)) + group->comment[0] = 0; + + if(!members || !num_membs) { + ldap_entry = ldap_next_entry(ldap_struct, ldap_entry); + return group; + } + + if(values = ldap_get_values(ldap_struct, ldap_entry, "member")) { + + *num_membs = i = ldap_count_values(values); + *members = memblist = malloc(i * sizeof(LOCAL_GRP_MEMBER)); + + do { + value = values[--i]; + + if(!(sep = strchr(value, ','))) { + DEBUG(0, ("Malformed alias member\n")); + return NULL; + } + *(sep++) = 0; + fstrcpy(memblist[i].name, value); + + if(!(value = strchr(sep, ','))) { + DEBUG(0, ("Malformed alias member\n")); + return NULL; + } + *(value++) = 0; + string_to_sid(&memblist[i].sid, sep); + + if((memblist[i].sid_use = atoi(value)) + >= SID_NAME_UNKNOWN) + DEBUG(0, ("Invalid SID use in alias")); + + } while(i > 0); + + ldap_value_free(values); + + } else { + *num_membs = 0; + *members = NULL; + } + + return group; +} + + +/************************************************************************ + Queues the necessary modifications to save a LOCAL_GRP structure + ************************************************************************/ + +static void ldapbuiltin_grpmods(LOCAL_GRP *group, LDAPMod ***mods, + int operation) +{ + fstring temp; + + *mods = NULL; + + if(operation == LDAP_MOD_ADD) { /* immutable attributes */ + ldap_make_mod(mods, LDAP_MOD_ADD, "objectClass", "sambaBuiltin"); + ldap_make_mod(mods, LDAP_MOD_ADD, "cn", group->name); + + slprintf(temp, sizeof(temp)-1, "%d", (gid_t)(-1)); + ldap_make_mod(mods, LDAP_MOD_ADD, "gidNumber", temp); + + slprintf(temp, sizeof(temp)-1, "%d", group->rid); + ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp); + } + + ldap_make_mod(mods, operation, "description", group->comment); +} + + +/*************************************************************** + Begin/end smbgrp enumeration. + ****************************************************************/ + +static void *ldapbuiltin_enumfirst(BOOL update) +{ + if (lp_server_role() == ROLE_DOMAIN_NONE) + return NULL; + + if (!ldap_open_connection(False)) + return NULL; + + ldap_search_for("objectClass=sambaBuiltin"); + + return ldap_struct; +} + +static void ldapbuiltin_enumclose(void *vp) +{ + ldap_close_connection(); +} + + +/************************************************************************* + Save/restore the current position in a query + *************************************************************************/ + +static SMB_BIG_UINT ldapbuiltin_getdbpos(void *vp) +{ + return (SMB_BIG_UINT)((ulong)ldap_entry); +} + +static BOOL ldapbuiltin_setdbpos(void *vp, SMB_BIG_UINT tok) +{ + ldap_entry = (LDAPMessage *)((ulong)tok); + return (True); +} + + +/************************************************************************* + Return limited smb_passwd information, and group membership. + *************************************************************************/ + +static LOCAL_GRP *ldapbuiltin_getgrpbynam(const char *name, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + LOCAL_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(cn=%s)(objectClass=sambaBuiltin))", name); + ldap_search_for(filter); + + ret = ldapbuiltin_getgrp(&localgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static LOCAL_GRP *ldapbuiltin_getgrpbygid(gid_t grp_id, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + LOCAL_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(gidNumber=%d)(objectClass=sambaBuiltin))", grp_id); + ldap_search_for(filter); + ret = ldapbuiltin_getgrp(&localgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static LOCAL_GRP *ldapbuiltin_getgrpbyrid(uint32 grp_rid, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + LOCAL_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(rid=%d)(objectClass=sambaBuiltin))", grp_rid); + ldap_search_for(filter); + ret = ldapbuiltin_getgrp(&localgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static LOCAL_GRP *ldapbuiltin_getcurrentgrp(void *vp, + LOCAL_GRP_MEMBER **members, int *num_membs) +{ + return ldapbuiltin_getgrp(&localgrp, members, num_membs); +} + +static BOOL ldapbuiltin_addgrp(LOCAL_GRP *group) +{ + LDAPMod **mods; + + ldapbuiltin_grpmods(group, &mods, LDAP_MOD_ADD); + return ldap_makemods("cn", group->name, mods, True); +} + +static BOOL ldapbuiltin_modgrp(LOCAL_GRP *group) +{ + LDAPMod **mods; + + ldapbuiltin_grpmods(group, &mods, LDAP_MOD_REPLACE); + return ldap_makemods("cn", group->name, mods, False); +} + +static BOOL ldapbuiltin_getusergroups(const char *name, + LOCAL_GRP **groups, int *num_grps) +{ + LOCAL_GRP *grouplist; + fstring filter; + int i; + + slprintf(filter, sizeof(pstring)-1, + "(&(member=%s,*)(objectclass=sambaBuiltin))", name); + ldap_search_for(filter); + + *num_grps = i = ldap_count_entries(ldap_struct, ldap_results); + + if(!i) { + *groups = NULL; + return (True); + } + + *groups = grouplist = malloc(i * sizeof(LOCAL_GRP)); + do { + i--; + } while(ldapbuiltin_getgrp(&grouplist[i], NULL, NULL) && (i > 0)); + + return (True); +} + + +static struct aliasdb_ops ldapbuiltin_ops = +{ + ldapbuiltin_enumfirst, + ldapbuiltin_enumclose, + ldapbuiltin_getdbpos, + ldapbuiltin_setdbpos, + + ldapbuiltin_getgrpbynam, + ldapbuiltin_getgrpbygid, + ldapbuiltin_getgrpbyrid, + ldapbuiltin_getcurrentgrp, + + ldapbuiltin_addgrp, + ldapbuiltin_modgrp, + + ldapbuiltin_getusergroups +}; + +struct aliasdb_ops *ldap_initialise_builtin_db(void) +{ + return &ldapbuiltin_ops; +} + +#else + void builtinldap_dummy_function(void); + void builtinldap_dummy_function(void) { } /* stop some compilers complaining */ +#endif + diff --git a/source/groupdb/groupldap.c b/source/groupdb/groupldap.c new file mode 100644 index 00000000000..df0d7552402 --- /dev/null +++ b/source/groupdb/groupldap.c @@ -0,0 +1,318 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0. + LDAP domain group database for SAMBA + Copyright (C) Matthew Chapman 1998 + + 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" + +#ifdef WITH_LDAP + +#include +#include + +extern int DEBUGLEVEL; + +/* Internal state */ +extern LDAP *ldap_struct; +extern LDAPMessage *ldap_results; +extern LDAPMessage *ldap_entry; + +/* Static structure filled for requests */ +static DOMAIN_GRP domgrp; + + +/*************************************************************** + Get group and membership information. + ****************************************************************/ + +static DOMAIN_GRP *ldapgroup_getgrp(DOMAIN_GRP *group, + DOMAIN_GRP_MEMBER **members, int *num_membs) +{ + fstring temp; + char **values; + DOMAIN_GRP_MEMBER *memblist; + int i; + + if(!ldap_entry) + return NULL; + + if(!ldap_get_attribute("cn", group->name)) { + DEBUG(0, ("Missing cn\n")); + return NULL; } + + DEBUG(2,("Retrieving group [%s]\n", group->name)); + + if(ldap_get_attribute("rid", temp)) { + group->rid = atoi(temp); + } else { + DEBUG(0, ("Missing rid\n")); + return NULL; + } + + if(!ldap_get_attribute("description", group->comment)) + group->comment[0] = 0; + + group->attr = 0x7; + + if(!members || !num_membs) { + ldap_entry = ldap_next_entry(ldap_struct, ldap_entry); + return group; + } + + if(values = ldap_get_values(ldap_struct, ldap_entry, "uidMember")) { + + DEBUG(0, ("Need to return NT names here\n")); + + *num_membs = i = ldap_count_values(values); + *members = memblist = malloc(i * sizeof(DOMAIN_GRP_MEMBER)); + + do { + fstrcpy(memblist[--i].name, values[i]); + memblist[i].attr = 0x7; + } while(i > 0); + + ldap_value_free(values); + + } else { + *num_membs = 0; + *members = NULL; + } + + ldap_entry = ldap_next_entry(ldap_struct, ldap_entry); + return group; +} + + +/************************************************************************ + Queues the necessary modifications to save a DOMAIN_GRP structure + ************************************************************************/ + +static void ldapgroup_grpmods(DOMAIN_GRP *group, LDAPMod ***mods, + int operation) +{ + fstring temp; + + *mods = NULL; + + if(operation == LDAP_MOD_ADD) { /* immutable attributes */ + ldap_make_mod(mods, LDAP_MOD_ADD, "objectClass", "sambaGroup"); + ldap_make_mod(mods, LDAP_MOD_ADD, "cn", group->name); + + slprintf(temp, sizeof(temp)-1, "%d", (gid_t)(-1)); + ldap_make_mod(mods, LDAP_MOD_ADD, "gidNumber", temp); + + slprintf(temp, sizeof(temp)-1, "%d", group->rid); + ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp); + } + + ldap_make_mod(mods, operation, "description", group->comment); +} + + +/*************************************************************** + Begin/end domain group enumeration. + ****************************************************************/ + +static void *ldapgroup_enumfirst(BOOL update) +{ + int server_role = lp_server_role(); + + if (server_role == ROLE_DOMAIN_NONE || + server_role == ROLE_DOMAIN_MEMBER) + return NULL; + + if (!ldap_open_connection(False)) + return NULL; + + ldap_search_for("objectclass=sambaGroup"); + + return ldap_struct; +} + +static void ldapgroup_enumclose(void *vp) +{ + ldap_close_connection(); +} + + +/************************************************************************* + Save/restore the current position in a query + *************************************************************************/ + +static SMB_BIG_UINT ldapgroup_getdbpos(void *vp) +{ + return (SMB_BIG_UINT)((ulong)ldap_entry); +} + +static BOOL ldapgroup_setdbpos(void *vp, SMB_BIG_UINT tok) +{ + ldap_entry = (LDAPMessage *)((ulong)tok); + return (True); +} + + +/************************************************************************* + Return information about domain groups and their members. + *************************************************************************/ + +static DOMAIN_GRP *ldapgroup_getgrpbynam(const char *name, + DOMAIN_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + DOMAIN_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(cn=%s)(objectClass=sambaGroup))", name); + ldap_search_for(filter); + + ret = ldapgroup_getgrp(&domgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static DOMAIN_GRP *ldapgroup_getgrpbygid(gid_t grp_id, + DOMAIN_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + DOMAIN_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(gidNumber=%d)(objectClass=sambaGroup))", grp_id); + ldap_search_for(filter); + + ret = ldapgroup_getgrp(&domgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static DOMAIN_GRP *ldapgroup_getgrpbyrid(uint32 grp_rid, + DOMAIN_GRP_MEMBER **members, int *num_membs) +{ + fstring filter; + DOMAIN_GRP *ret; + + if(!ldap_open_connection(False)) + return (False); + + slprintf(filter, sizeof(filter)-1, + "(&(rid=%d)(objectClass=sambaGroup))", grp_rid); + ldap_search_for(filter); + + ret = ldapgroup_getgrp(&domgrp, members, num_membs); + + ldap_close_connection(); + return ret; +} + +static DOMAIN_GRP *ldapgroup_getcurrentgrp(void *vp, + DOMAIN_GRP_MEMBER **members, int *num_membs) +{ + return ldapgroup_getgrp(&domgrp, members, num_membs); +} + + +/************************************************************************* + Add/modify domain groups. + *************************************************************************/ + +static BOOL ldapgroup_addgrp(DOMAIN_GRP *group) +{ + LDAPMod **mods; + + ldapgroup_grpmods(group, &mods, LDAP_MOD_ADD); + return ldap_makemods("cn", group->name, mods, True); +} + +static BOOL ldapgroup_modgrp(DOMAIN_GRP *group) +{ + LDAPMod **mods; + + ldapgroup_grpmods(group, &mods, LDAP_MOD_REPLACE); + return ldap_makemods("cn", group->name, mods, False); +} + + +/************************************************************************* + Return domain groups that a user is in. + *************************************************************************/ + +static BOOL ldapgroup_getusergroups(const char *name, DOMAIN_GRP **groups, + int *num_grps) +{ + DOMAIN_GRP *grouplist; + fstring filter; + int i; + + slprintf(filter, sizeof(pstring)-1, + "(&(uidMember=%s)(objectclass=sambaGroup))", name); + ldap_search_for(filter); + + *num_grps = i = ldap_count_entries(ldap_struct, ldap_results); + + if(!i) { + *groups = NULL; + return (True); + } + + *groups = grouplist = malloc(i * sizeof(DOMAIN_GRP)); + do { + i--; + } while(ldapgroup_getgrp(&grouplist[i], NULL, NULL) && (i > 0)); + + return (True); +} + + +static struct groupdb_ops ldapgroup_ops = +{ + ldapgroup_enumfirst, + ldapgroup_enumclose, + ldapgroup_getdbpos, + ldapgroup_setdbpos, + + ldapgroup_getgrpbynam, + ldapgroup_getgrpbygid, + ldapgroup_getgrpbyrid, + ldapgroup_getcurrentgrp, + + ldapgroup_addgrp, + ldapgroup_modgrp, + + ldapgroup_getusergroups +}; + +struct groupdb_ops *ldap_initialise_group_db(void) +{ + return &ldapgroup_ops; +} + +#else + void groupldap_dummy_function(void); + void groupldap_dummy_function(void) { } /* stop some compilers complaining */ +#endif + diff --git a/source/passdb/passgrpldap.c b/source/passdb/passgrpldap.c new file mode 100644 index 00000000000..3d647cd7763 --- /dev/null +++ b/source/passdb/passgrpldap.c @@ -0,0 +1,190 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0. + LDAP passgrp database for SAMBA + Copyright (C) Matthew Chapman 1998 + + 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" + +#ifdef WITH_LDAP + +#include +#include + +extern int DEBUGLEVEL; + +/* Internal state */ +extern LDAP *ldap_struct; +extern LDAPMessage *ldap_results; +extern LDAPMessage *ldap_entry; + + +/*************************************************************** + Enumerate RIDs of groups which user is a member of, of type + given by attribute. + ****************************************************************/ + +static void ldappassgrp_member(char *attribute, uint32 **rids, int *numrids) +{ + char **values; + uint32 *ridlist; + int i; + + if((values = ldap_get_values(ldap_struct, ldap_entry, attribute))) { + *numrids = i = ldap_count_values(values); + *rids = ridlist = malloc(i * sizeof(uint32)); + do { + ridlist[--i] = atoi(values[i]); + } while(i > 0); + ldap_value_free(values); + } else { + *numrids = 0; + *rids = NULL; + } +} + + +/*************************************************************** + Begin/end smbgrp enumeration. + ****************************************************************/ + +static void *ldappassgrp_enumfirst(BOOL update) +{ + if (!ldap_open_connection(False)) + return NULL; + + ldap_search_for("&(objectclass=sambaAccount)(|(group=*)(alias=*))"); + + return ldap_struct; +} + +static void ldappassgrp_enumclose(void *vp) +{ + ldap_close_connection(); +} + + +/************************************************************************* + Save/restore the current position in a query + *************************************************************************/ + +static SMB_BIG_UINT ldappassgrp_getdbpos(void *vp) +{ + return (SMB_BIG_UINT)((ulong)ldap_entry); +} + +static BOOL ldappassgrp_setdbpos(void *vp, SMB_BIG_UINT tok) +{ + ldap_entry = (LDAPMessage *)((ulong)tok); + return (True); +} + + +/************************************************************************* + Return limited smb_passwd information, and group membership. + *************************************************************************/ + +static struct smb_passwd *ldappassgrp_getpwbynam(const char *name, + uint32 **grp_rids, int *num_grps, + uint32 **als_rids, int *num_alss) +{ + struct smb_passwd *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_ntname(name); + ldappassgrp_member("group", grp_rids, num_grps); + ldappassgrp_member("alias", als_rids, num_alss); + ret = ldap_getpw(); + + ldap_close_connection(); + return ret; +} + +static struct smb_passwd *ldappassgrp_getpwbyuid(uid_t userid, + uint32 **grp_rids, int *num_grps, + uint32 **als_rids, int *num_alss) +{ + struct smb_passwd *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_uid(userid); + ldappassgrp_member("group", grp_rids, num_grps); + ldappassgrp_member("alias", als_rids, num_alss); + ret = ldap_getpw(); + + ldap_close_connection(); + return ret; +} + +static struct smb_passwd *ldappassgrp_getpwbyrid(uint32 user_rid, + uint32 **grp_rids, int *num_grps, + uint32 **als_rids, int *num_alss) +{ + struct smb_passwd *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_rid(user_rid); + ldappassgrp_member("group", grp_rids, num_grps); + ldappassgrp_member("alias", als_rids, num_alss); + ret = ldap_getpw(); + + ldap_close_connection(); + return ret; +} + +static struct smb_passwd *ldappassgrp_getcurrentpw(void *vp, + uint32 **grp_rids, int *num_grps, + uint32 **als_rids, int *num_alss) +{ + ldappassgrp_member("group", grp_rids, num_grps); + ldappassgrp_member("alias", als_rids, num_alss); + return ldap_getpw(); +} + + + +static struct passgrp_ops ldappassgrp_ops = +{ + ldappassgrp_enumfirst, + ldappassgrp_enumclose, + ldappassgrp_getdbpos, + ldappassgrp_setdbpos, + + ldappassgrp_getpwbynam, + ldappassgrp_getpwbyuid, + ldappassgrp_getpwbyrid, + ldappassgrp_getcurrentpw, +}; + +struct passgrp_ops *ldap_initialise_password_grp(void) +{ + return &ldappassgrp_ops; +} + +#else + void passgrpldap_dummy_function(void); + void passgrpldap_dummy_function(void) { } /* stop some compilers complaining */ +#endif + diff --git a/source/passdb/sampassldap.c b/source/passdb/sampassldap.c new file mode 100644 index 00000000000..1c3283df0fd --- /dev/null +++ b/source/passdb/sampassldap.c @@ -0,0 +1,433 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0. + LDAP protocol helper functions for SAMBA + Copyright (C) Matthew Chapman 1998 + + 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" + +#ifdef WITH_LDAP + +#include +#include + +extern int DEBUGLEVEL; + +/* Internal state */ +LDAP *ldap_struct; +LDAPMessage *ldap_results; +LDAPMessage *ldap_entry; + + +/******************************************************************* + NT name/RID search functions. + ******************************************************************/ + +BOOL ldap_search_by_rid(uint32 rid) +{ + fstring filter; + + slprintf(filter, sizeof(filter)-1, + "(&(rid=%d)(objectclass=sambaAccount))", rid); + return ldap_search_for(filter); +} + +BOOL ldap_search_by_ntname(const char *ntname) +{ + fstring filter; + + slprintf(filter, sizeof(filter)-1, + "(&(ntuid=%s)(objectclass=sambaAccount))", ntname); + return ldap_search_for(filter); +} + + +/******************************************************************* + Store NTTIMEs as time_t's. + ******************************************************************/ + +static void ldap_save_time(LDAPMod ***modlist, int modop, char *attribute, + NTTIME *nttime) +{ + fstring tstr; + time_t t; + + t = nt_time_to_unix(nttime); + + if(t == -1) + return; + + slprintf(tstr, sizeof(tstr)-1, "%08X", t); + ldap_make_mod(modlist, modop, attribute, tstr); +} + +static void ldap_read_time(char *attribute, NTTIME *nttime) +{ + fstring timestr; + time_t t; + + if(ldap_get_attribute(attribute, timestr)) + t = (time_t)strtol(timestr, NULL, 16); + else + t = (time_t)(-1); + + unix_to_nt_time(nttime, t); +} + + +/******************************************************************* + Contruct a sam_passwd structure. + ******************************************************************/ + +static struct sam_passwd *ldapsam_getsam() +{ + static pstring full_name; + static pstring acct_desc; + static pstring home_dir; + static pstring home_drive; + static pstring logon_script; + static pstring profile_path; + static pstring workstations; + pstring temp; + struct sam_passwd *sam21; + struct smb_passwd *smbpw; + + if(!ldap_entry) + return NULL; + + smbpw = ldap_getpw(); + sam21 = pwdb_smb_to_sam(smbpw); + + if(ldap_get_attribute("gidNumber", temp)) + sam21->unix_gid = atoi(temp); + else + sam21->unix_gid = (gid_t)(-1); + + if(ldap_get_attribute("grouprid", temp)) + sam21->group_rid = atoi(temp); + else + sam21->group_rid = 0xFFFFFFFF; + + if(ldap_get_attribute("cn", full_name)) + sam21->full_name = full_name; + else + sam21->full_name = NULL; + + if(ldap_get_attribute("description", acct_desc)) + sam21->acct_desc = acct_desc; + else + sam21->acct_desc = NULL; + + if(ldap_get_attribute("smbHome", home_dir)) + sam21->home_dir = home_dir; + else + sam21->home_dir = NULL; + + if(ldap_get_attribute("homeDrive", home_drive)) + sam21->dir_drive = home_drive; + else + sam21->dir_drive = NULL; + + if(ldap_get_attribute("script", logon_script)) + sam21->logon_script = logon_script; + else + sam21->logon_script = NULL; + + if(ldap_get_attribute("profile", profile_path)) + sam21->profile_path = profile_path; + else + sam21->profile_path = NULL; + + if(ldap_get_attribute("workstations", workstations)) + sam21->workstations = workstations; + else + sam21->workstations = NULL; + + ldap_read_time("pwdCanChange", &sam21->pass_can_change_time); + ldap_read_time("pwdMustChange", &sam21->pass_must_change_time); + ldap_read_time("logonTime", &sam21->logon_time); + ldap_read_time("logoffTime", &sam21->logoff_time); + ldap_read_time("kickoffTime", &sam21->kickoff_time); + + sam21->unknown_3 = 0xffffff; /* don't know */ + sam21->logon_divs = 168; /* hours per week */ + sam21->hours_len = 21; /* 21 times 8 bits = 168 */ + memset(sam21->hours, 0xff, sam21->hours_len); /* all hours */ + sam21->unknown_5 = 0x00020000; /* don't know */ + sam21->unknown_6 = 0x000004ec; /* don't know */ + sam21->unknown_str = NULL; + sam21->munged_dial = NULL; + + return sam21; +} + + +/******************************************************************* + Contruct a sam_disp_info structure. + ******************************************************************/ + +static struct sam_disp_info *ldapsam_getdispinfo() +{ + static struct sam_disp_info dispinfo; + static pstring nt_name; + static pstring full_name; + pstring temp; + + if(!ldap_entry) + return NULL; + + if(!ldap_get_attribute("ntuid", nt_name) && + !ldap_get_attribute("uid", nt_name)) { + DEBUG(0,("Missing uid\n")); + return NULL; } + dispinfo.nt_name = nt_name; + + DEBUG(2,("Retrieving account [%s]\n",nt_name)); + + if(ldap_get_attribute("rid", temp)) + dispinfo.user_rid = atoi(temp); + else { + DEBUG(0,("Missing rid\n")); + return NULL; } + + if(ldap_get_attribute("cn", full_name)) + dispinfo.full_name = full_name; + else + dispinfo.full_name = NULL; + + return &dispinfo; +} + + +/************************************************************************ + Queues the necessary modifications to save a sam_passwd structure + ************************************************************************/ + +static void ldapsam_sammods(struct sam_passwd *newpwd, LDAPMod ***mods, + int operation) +{ + struct smb_passwd *smbpw; + pstring temp; + + smbpw = pwdb_sam_to_smb(newpwd); + ldap_smbpwmods(smbpw, mods, operation); + + slprintf(temp, sizeof(temp)-1, "%d", newpwd->unix_gid); + ldap_make_mod(mods, operation, "gidNumber", temp); + + slprintf(temp, sizeof(temp)-1, "%d", newpwd->group_rid); + ldap_make_mod(mods, operation, "grouprid", temp); + + ldap_make_mod(mods, operation, "cn", newpwd->full_name); + ldap_make_mod(mods, operation, "description", newpwd->acct_desc); + ldap_make_mod(mods, operation, "smbHome", newpwd->home_dir); + ldap_make_mod(mods, operation, "homeDrive", newpwd->dir_drive); + ldap_make_mod(mods, operation, "script", newpwd->logon_script); + ldap_make_mod(mods, operation, "profile", newpwd->profile_path); + ldap_make_mod(mods, operation, "workstations", newpwd->workstations); + + ldap_save_time(mods, operation, "pwdCanChange", + &newpwd->pass_can_change_time); + ldap_save_time(mods, operation, "pwdMustChange", + &newpwd->pass_must_change_time); + ldap_save_time(mods, operation, "logonTime", + &newpwd->logon_time); + ldap_save_time(mods, operation, "logoffTime", + &newpwd->logoff_time); + ldap_save_time(mods, operation, "kickoffTime", + &newpwd->kickoff_time); +} + + +/*************************************************************** + Begin/end account enumeration. + ****************************************************************/ + +static void *ldapsam_enumfirst(BOOL update) +{ + if (!ldap_open_connection(False)) + return NULL; + + ldap_search_for("objectclass=sambaAccount"); + + return ldap_struct; +} + +static void ldapsam_enumclose(void *vp) +{ + ldap_close_connection(); +} + + +/************************************************************************* + Save/restore the current position in a query + *************************************************************************/ + +static SMB_BIG_UINT ldapsam_getdbpos(void *vp) +{ + return (SMB_BIG_UINT)((ulong)ldap_entry); +} + +static BOOL ldapsam_setdbpos(void *vp, SMB_BIG_UINT tok) +{ + ldap_entry = (LDAPMessage *)((ulong)tok); + return (True); +} + + +/************************************************************************* + Return sam_passwd information. + *************************************************************************/ + +static struct sam_passwd *ldapsam_getsambynam(const char *name) +{ + struct sam_passwd *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_ntname(name); + ret = ldapsam_getsam(); + + ldap_close_connection(); + return ret; +} + +static struct sam_passwd *ldapsam_getsambyuid(uid_t userid) +{ + struct sam_passwd *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_uid(userid); + ret = ldapsam_getsam(); + + ldap_close_connection(); + return ret; +} + +static struct sam_passwd *ldapsam_getsambyrid(uint32 user_rid) +{ + struct sam_passwd *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_rid(user_rid); + ret = ldapsam_getsam(); + + ldap_close_connection(); + return ret; +} + +static struct sam_passwd *ldapsam_getcurrentsam(void *vp) +{ + return ldapsam_getsam(); +} + + +/************************************************************************ + Modify user information given a sam_passwd struct. + *************************************************************************/ + +static BOOL ldapsam_addsam(struct sam_passwd *newpwd) +{ + LDAPMod **mods; + + ldapsam_sammods(newpwd, &mods, LDAP_MOD_ADD); + return ldap_makemods("uid", newpwd->unix_name, mods, True); +} + +static BOOL ldapsam_modsam(struct sam_passwd *pwd, BOOL override) +{ + LDAPMod **mods; + + ldapsam_sammods(pwd, &mods, LDAP_MOD_REPLACE); + return ldap_makemods("uid", pwd->unix_name, mods, False); +} + + +/************************************************************************* + Return sam_disp_info information. + *************************************************************************/ + +static struct sam_disp_info *ldapsam_getdispbynam(const char *name) +{ + struct sam_disp_info *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_ntname(name); + ret = ldapsam_getdispinfo(); + + ldap_close_connection(); + return ret; +} + +static struct sam_disp_info *ldapsam_getdispbyrid(uint32 user_rid) +{ + struct sam_disp_info *ret; + + if(!ldap_open_connection(False)) + return NULL; + + ldap_search_by_rid(user_rid); + ret = ldapsam_getdispinfo(); + + ldap_close_connection(); + return ret; +} + +static struct sam_disp_info *ldapsam_getcurrentdisp(void *vp) +{ + return ldapsam_getdispinfo(); +} + + + +static struct sam_passdb_ops ldapsam_ops = +{ + ldapsam_enumfirst, + ldapsam_enumclose, + ldapsam_getdbpos, + ldapsam_setdbpos, + + ldapsam_getsambynam, + ldapsam_getsambyuid, + ldapsam_getsambyrid, + ldapsam_getcurrentsam, + ldapsam_addsam, + ldapsam_modsam, + + ldapsam_getdispbynam, + ldapsam_getdispbyrid, + ldapsam_getcurrentdisp +}; + +struct sam_passdb_ops *ldap_initialise_sam_password_db(void) +{ + return &ldapsam_ops; +} + +#else + void sampassldap_dummy_function(void); + void sampassldap_dummy_function(void) { } /* stop some compilers complaining */ +#endif -- 2.34.1