added ldap files by Matthew Chapman.
authorLuke Leighton <lkcl@samba.org>
Mon, 7 Dec 1998 22:52:49 +0000 (22:52 +0000)
committerLuke Leighton <lkcl@samba.org>
Mon, 7 Dec 1998 22:52:49 +0000 (22:52 +0000)
docs/yodldocs/LDAP.yo [new file with mode: 0644]
source/groupdb/aliasldap.c [new file with mode: 0644]
source/groupdb/builtinldap.c [new file with mode: 0644]
source/groupdb/groupldap.c [new file with mode: 0644]
source/passdb/passgrpldap.c [new file with mode: 0644]
source/passdb/sampassldap.c [new file with mode: 0644]

diff --git a/docs/yodldocs/LDAP.yo b/docs/yodldocs/LDAP.yo
new file mode 100644 (file)
index 0000000..cf45490
--- /dev/null
@@ -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(<p>
+) 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 (file)
index 0000000..35d810d
--- /dev/null
@@ -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 <lber.h>
+#include <ldap.h>
+
+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 (file)
index 0000000..f2a530c
--- /dev/null
@@ -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 <lber.h>
+#include <ldap.h>
+
+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 (file)
index 0000000..df0d755
--- /dev/null
@@ -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 <lber.h>
+#include <ldap.h>
+
+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 (file)
index 0000000..3d647cd
--- /dev/null
@@ -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 <lber.h>
+#include <ldap.h>
+
+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 (file)
index 0000000..1c3283d
--- /dev/null
@@ -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 <lber.h>
+#include <ldap.h>
+
+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