Subject: 2.2.1a and 2.2 cvs samba ldap patch From: "Shahms E. King" To: samba-technical@lists.samba.org Content-Type: multipart/mixed; boundary="=-1/q6XNvs1fy4xj2xf0LG" Message-Id: <996164590.8966.20.camel@sking.mesd.k12.or.us> Mime-Version: 1.0 Date: 26 Jul 2001 09:23:10 -0700 --=-1/q6XNvs1fy4xj2xf0LG Content-Type: text/plain Content-Transfer-Encoding: 7bit I've recently managed to finish up a patch for 2.2 to use ldap for the password backend. I'd like to get some feedback on it and someone else testing. At the moment, I can't get win2k to become part of a domain, although that might be caused by something else (or my own incompetence), all the code I can see in the patch does what it should. the configure checks aren't complete (it compiles with OpenLDAP 2.x only for the moment, although in the future it may work with OpenLDAP 1.x, and if I get time, the Netscape SDK). It supports SSL/TLS using both ldaps and Start TLS. It will work unencrypted against LDAPv2 servers, but I'm still fighting some SSL issues with v2. Enjoy! --Shahms --=-1/q6XNvs1fy4xj2xf0LG Content-Type: text/x-patch Content-Disposition: attachment; filename=samba-ldap.patch Content-ID: <996163725.8959.4.camel@sking.mesd.k12.or.us> Content-Transfer-Encoding: 7bit diff -urbN samba-2.2.1a/source/configure.in samba-2.2.1a-shahms/source/configure.in --- samba-2.2.1a/source/configure.in Mon Jul 9 17:12:50 2001 +++ samba-2.2.1a-shahms/source/configure.in Wed Jul 25 16:00:57 2001 @@ -1712,22 +1712,23 @@ # --jerry # # check for a LDAP password database -#AC_MSG_CHECKING(whether to use LDAP password database) -#AC_ARG_WITH(ldap, -#[ --with-ldap Include LDAP support -# --without-ldap Don't include LDAP support (default)], -#[ case "$withval" in -# yes) -# AC_MSG_RESULT(yes) -# AC_DEFINE(WITH_LDAP) +AC_MSG_CHECKING(whether to use LDAP password database) +AC_ARG_WITH(ldap, +[ --with-ldap Include LDAP support + --without-ldap Don't include LDAP support (default)], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LDAP) + LIBS="-lldap -llber -lresolv $LIBS" # AC_MSG_ERROR([LDAP password database not supported in this version.]) -# ;; -# *) -# AC_MSG_RESULT(no) -# ;; -# esac ], -# AC_MSG_RESULT(no) -#) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], + AC_MSG_RESULT(no) +) ################################################# # check for a NISPLUS password database diff -urbN samba-2.2.1a/source/include/smb.h samba-2.2.1a-shahms/source/include/smb.h --- samba-2.2.1a/source/include/smb.h Thu Jul 5 19:01:30 2001 +++ samba-2.2.1a-shahms/source/include/smb.h Mon Jul 23 12:36:41 2001 @@ -1448,6 +1448,12 @@ #endif /* DEVELOPER */ }; +/* LDAP schema types */ +enum schema_types {SCHEMA_COMPAT, SCHEMA_AD, SCHEMA_SAMBA}; + +/* LDAP SSL options */ +enum ldap_ssl_types {LDAP_SSL_ON, LDAP_SSL_OFF, LDAP_SSL_START_TLS}; + /* Remote architectures we know about. */ enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_WIN2K, RA_SAMBA}; diff -urbN samba-2.2.1a/source/param/loadparm.c samba-2.2.1a-shahms/source/param/loadparm.c --- samba-2.2.1a/source/param/loadparm.c Thu Jul 5 19:01:44 2001 +++ samba-2.2.1a-shahms/source/param/loadparm.c Mon Jul 23 14:10:50 2001 @@ -152,11 +152,6 @@ char *szNetbiosAliases; char *szDomainOtherSIDs; char *szNameResolveOrder; - char *szLdapServer; - char *szLdapSuffix; - char *szLdapFilter; - char *szLdapRoot; - char *szLdapRootPassword; char *szPanicAction; char *szAddUserScript; char *szDelUserScript; @@ -211,7 +206,16 @@ int winbind_cache_time; #ifdef WITH_LDAP int ldap_port; + int ldap_schema; + char *szLdapServer; + char *szLdapSuffix; + char *szLdapFilter; + char *szLdapRoot; + char *szLdapRootPassword; #endif /* WITH_LDAP */ +#if (defined(WITH_LDAP) && defined(WITH_SSL)) + int ldap_ssl; +#endif #ifdef WITH_SSL int sslVersion; char *sslHostsRequire; @@ -571,6 +575,27 @@ {-1, NULL} }; +static struct enum_list enum_ldap_schema[] = { + {SCHEMA_COMPAT, "compat"}, + {SCHEMA_AD, "ad"}, + {SCHEMA_AD, "active directory"}, + {SCHEMA_SAMBA, "samba"}, + {-1, NULL} +}; + +static struct enum_list enum_ldap_ssl[] = { + {LDAP_SSL_ON, "Yes"}, + {LDAP_SSL_ON, "yes"}, + {LDAP_SSL_ON, "on"}, + {LDAP_SSL_ON, "On"}, + {LDAP_SSL_OFF, "no"}, + {LDAP_SSL_OFF, "No"}, + {LDAP_SSL_OFF, "off"}, + {LDAP_SSL_OFF, "Off"}, + {LDAP_SSL_START_TLS, "start tls"}, + {-1, NULL} +}; + /* Types of machine we can announce as. */ #define ANNOUNCE_AS_NT_SERVER 1 #define ANNOUNCE_AS_WIN95 2 @@ -746,7 +771,9 @@ {"ssl CA certDir", P_STRING, P_GLOBAL, &Globals.sslCaCertDir, NULL, NULL, 0}, {"ssl CA certFile", P_STRING, P_GLOBAL, &Globals.sslCaCertFile, NULL, NULL, 0}, {"ssl server cert", P_STRING, P_GLOBAL, &Globals.sslCert, NULL, NULL, 0}, + {"ssl cert", P_STRING, P_GLOBAL, &Globals.sslCert, NULL, NULL, 0}, {"ssl server key", P_STRING, P_GLOBAL, &Globals.sslPrivKey, NULL, NULL, 0}, + {"ssl key", P_STRING, P_GLOBAL, &Globals.sslPrivKey, NULL, NULL, 0}, {"ssl client cert", P_STRING, P_GLOBAL, &Globals.sslClientCert, NULL, NULL, 0}, {"ssl client key", P_STRING, P_GLOBAL, &Globals.sslClientPrivKey, NULL, NULL, 0}, {"ssl require clientcert", P_BOOL, P_GLOBAL, &Globals.sslReqClientCert, NULL, NULL, 0}, @@ -942,7 +969,11 @@ {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, 0}, {"ldap root", P_STRING, P_GLOBAL, &Globals.szLdapRoot, NULL, NULL, 0}, {"ldap root passwd", P_STRING, P_GLOBAL, &Globals.szLdapRootPassword, NULL, NULL, 0}, + {"ldap schema", P_ENUM, P_GLOBAL, &Globals.ldap_schema, NULL, enum_ldap_schema, 0}, #endif /* WITH_LDAP */ +#if (defined(WITH_LDAP) && defined(WITH_SSL)) + {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, 0}, +#endif {"Miscellaneous Options", P_SEP, P_SEPARATOR}, {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, 0}, @@ -1280,12 +1311,6 @@ Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */ Globals.enhanced_browsing = True; -#ifdef WITH_LDAP - /* default values for ldap */ - string_set(&Globals.szLdapServer, "localhost"); - Globals.ldap_port = 389; -#endif /* WITH_LDAP */ - #ifdef WITH_SSL Globals.sslVersion = SMB_SSL_V23; string_set(&Globals.sslHostsRequire, ""); @@ -1303,6 +1328,18 @@ Globals.sslCompatibility = False; #endif /* WITH_SSL */ +#ifdef WITH_LDAP + string_set(&Globals.szLdapServer, "localhost"); + string_set(&Globals.szLdapSuffix, ""); + string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))"); + string_set(&Globals.szLdapRoot, ""); + string_set(&Globals.szLdapRootPassword, ""); + Globals.ldap_port = 389; + Globals.ldap_schema = SCHEMA_COMPAT; +#endif /* WITH_LDAP */ +#if (defined(WITH_LDAP) && defined(WITH_SSL)) + Globals.ldap_ssl = LDAP_SSL_OFF; +#endif /* these parameters are set to defaults that are more appropriate for the increasing samba install base: @@ -1476,7 +1513,12 @@ FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter) FN_GLOBAL_STRING(lp_ldap_root, &Globals.szLdapRoot) FN_GLOBAL_STRING(lp_ldap_rootpasswd, &Globals.szLdapRootPassword) +FN_GLOBAL_INTEGER(lp_ldap_schema, &Globals.ldap_schema) +FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port) #endif /* WITH_LDAP */ +#if (defined(WITH_LDAP) && defined(WITH_SSL)) +FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl) +#endif FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand) FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand) FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand) @@ -1569,9 +1611,6 @@ FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest) FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length) FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time) -#ifdef WITH_LDAP -FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port) -#endif /* WITH_LDAP */ FN_LOCAL_STRING(lp_preexec, szPreExec) FN_LOCAL_STRING(lp_postexec, szPostExec) FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec) diff -urbN samba-2.2.1a/source/passdb/ldap.c samba-2.2.1a-shahms/source/passdb/ldap.c --- samba-2.2.1a/source/passdb/ldap.c Fri Feb 25 14:25:24 2000 +++ samba-2.2.1a-shahms/source/passdb/ldap.c Wed Jul 25 12:43:37 2001 @@ -1,7 +1,8 @@ /* Unix SMB/Netbios implementation. - Version 1.9. + Version 2.9. LDAP protocol helper functions for SAMBA + Copyright (C) Shahms King 2001 Copyright (C) Jean François Micouleau 1998 This program is free software; you can redistribute it and/or modify @@ -20,983 +21,1100 @@ */ +#include "includes.h" + #ifdef WITH_LDAP +/* TODO: +* persistent connections: don't make a new connection for each LDAP op +* perhaps ldap_init() and ldap_bind? on ldap_initialize_database +* +* SSL/SASL support, I don't like keeping plaintext passwords in the +* smb.conf file, nor do I like sending them over the wire, SSL let's us +* do Cert. based auth with the server +*/ -#include "includes.h" +/* NOTE: this will NOT work against an Active Directory server +* due to the fact that the two password fields cannot be retrieved +* from a server; recommend using security = domain in this situation +* and/or winbind +*/ #include #include -#define ADD_USER 1 -#define MODIFY_USER 2 +#define SAM_ACCOUNT struct sam_passwd extern int DEBUGLEVEL; -/******************************************************************* - open a connection to the ldap serve. -******************************************************************/ -static BOOL ldap_open_connection(LDAP **ldap_struct) +struct ldap_enum_info { - if ( (*ldap_struct = ldap_open(lp_ldap_server(),lp_ldap_port()) ) == NULL) - { - DEBUG( 0, ( "The LDAP server is not responding !\n" ) ); - return( False ); - } - DEBUG(2,("ldap_open_connection: connection opened\n")); - return (True); -} + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; +}; +static struct ldap_enum_info global_ldap_ent; /******************************************************************* - connect anonymously to the ldap server. - FIXME: later (jfm) + open a connection to the ldap server. ******************************************************************/ -static BOOL ldap_connect_anonymous(LDAP *ldap_struct) +static BOOL +ldap_open_connection (LDAP ** ldap_struct) { - if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS) + int port; + int version, rc; +#ifdef WITH_SSL + int tls = LDAP_OPT_X_TLS_HARD; + if (lp_ldap_ssl () == LDAP_SSL_ON && lp_ldap_port () == 389) + { + port = 636; + } + else + { + port = lp_ldap_port (); + } + if ((*ldap_struct = ldap_init (lp_ldap_server (), port)) == NULL) + { + DEBUG (0, ("The LDAP server is not responding !\n")); + return (False); + } + /* Connect to older servers using SSL and V2 rather than Start TLS */ + if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) + == LDAP_OPT_SUCCESS) + { + if (version != LDAP_VERSION2) + { + version = LDAP_VERSION2; + ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version); + } + } + + switch (lp_ldap_ssl ()) + { + case LDAP_SSL_START_TLS: + if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) + == LDAP_OPT_SUCCESS) + { + if (version < LDAP_VERSION3) + { + version = LDAP_VERSION3; + ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, + &version); + } + } + if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) { - DEBUG( 0, ( "Couldn't bind to the LDAP server !\n" ) ); - return(False); + DEBUG (0, + ("Failed to issue the StartTLS instruction: %s\n", + ldap_err2string (rc))); + return False; + } + DEBUG (2, ("StartTLS issued: using a TLS connection\n")); + break; + case LDAP_SSL_ON: + if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != + LDAP_SUCCESS) + { + DEBUG (0, ("Failed to setup a TLS session\n")); + } + break; + case LDAP_SSL_OFF: + default: } +#endif /* WITH_SSL */ + DEBUG (2, ("ldap_open_connection: connection opened\n")); return (True); } /******************************************************************* - connect to the ldap server under system privileg. + connect to the ldap server under system privilege. ******************************************************************/ -static BOOL ldap_connect_system(LDAP *ldap_struct) +static BOOL +ldap_connect_system (LDAP * ldap_struct) { - if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS) + int rc; + + /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite + * (OpenLDAP) doesnt' seem to support it + */ + if ((rc = ldap_simple_bind_s (ldap_struct, lp_ldap_root (), + lp_ldap_rootpasswd ())) != LDAP_SUCCESS) { - DEBUG( 0, ( "Couldn't bind to the LDAP server!\n" ) ); - return(False); + DEBUG (0, ("Bind failed: %s\n", ldap_err2string (rc))); + return (False); } - DEBUG(2,("ldap_connect_system: succesful connection to the LDAP server\n")); + DEBUG (2, + ("ldap_connect_system: succesful connection to the LDAP server\n")); return (True); } /******************************************************************* connect to the ldap server under a particular user. ******************************************************************/ -static BOOL ldap_connect_user(LDAP *ldap_struct, char *user, char *password) +static BOOL +ldap_connect_user (LDAP * ldap_struct, char *user, char *password) { - if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) ! = LDAP_SUCCESS) + int rc; + if ((rc = ldap_simple_bind_s (ldap_struct, user, password)) != LDAP_SUCCESS) { - DEBUG( 0, ( "Couldn't bind to the LDAP server !\n" ) ); - return(False); + DEBUG (0, + ("Couldn't bind to the LDAP server %s!\n", + ldap_err2string (rc))); + return (False); } - DEBUG(2,("ldap_connect_user: succesful connection to the LDAP server\n")); + DEBUG (2, ("ldap_connect_user: succesful connection to the LDAP server\n")); return (True); } /******************************************************************* run the search by name. ******************************************************************/ -static BOOL ldap_search_one_user(LDAP *ldap_struct, char *filter, LDAPMessage **result) +static int +ldap_search_one_user (LDAP * ldap_struct, char *filter, LDAPMessage ** result) { - int scope = LDAP_SCOPE_ONELEVEL; + int scope = LDAP_SCOPE_SUBTREE; int rc; - DEBUG(2,("ldap_search_one_user: searching for:[%s]\n", filter)); + DEBUG (2, ("ldap_search_one_user: searching for:[%s]\n", filter)); - rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, result); + rc = + ldap_search_s (ldap_struct, lp_ldap_suffix (), scope, filter, NULL, 0, + result); - if (rc ! = LDAP_SUCCESS ) + if (rc != LDAP_SUCCESS) { - DEBUG( 0, ( "Problem during the LDAP search\n" ) ); - return(False); + DEBUG (0, + ("Problem during the LDAP search: %s\n", ldap_err2string (rc))); + DEBUG (3, ("Query was: %s, %s\n", lp_ldap_suffix (), filter)); } - return (True); + return (rc); } /******************************************************************* run the search by name. ******************************************************************/ -static BOOL ldap_search_one_user_by_name(LDAP *ldap_struct, char *user, LDAPMessage **result) +static int +ldap_search_one_user_by_name (LDAP * ldap_struct, char *user, + LDAPMessage ** result) { pstring filter; /* in the filter expression, replace %u with the real name so in ldap filter, %u MUST exist :-) */ - pstrcpy(filter,lp_ldap_filter()); - pstring_sub(filter,"%u",user); + pstrcpy (filter, lp_ldap_filter ()); + /* have to use this here because $ is filtered out + * in pstring_sub + */ + all_string_sub (filter, "%u", user, sizeof (pstring)); - if ( !ldap_search_one_user(ldap_struct, filter, result) ) - { - return(False); - } - return (True); + return ldap_search_one_user (ldap_struct, filter, result); } /******************************************************************* run the search by uid. ******************************************************************/ -static BOOL ldap_search_one_user_by_uid(LDAP *ldap_struct, int uid, LDAPMessage **result) +static int +ldap_search_one_user_by_uid (LDAP * ldap_struct, int uid, + LDAPMessage ** result) { + struct passwd *user; pstring filter; - slprintf(filter, sizeof(pstring)-1, "uidAccount = %d", uid); + /* Get the username from the system and look that up in the LDAP */ + user = sys_getpwuid (uid); + pstrcpy (filter, lp_ldap_filter ()); + all_string_sub (filter, "%u", user->pw_name, sizeof (pstring)); - if ( !ldap_search_one_user(ldap_struct, filter, result) ) - { - return(False); + return ldap_search_one_user (ldap_struct, filter, result); } - return (True); -} -/******************************************************************* + /******************************************************************* search an attribute and return the first value found. -******************************************************************/ -static void get_single_attribute(LDAP *ldap_struct, LDAPMessage *entry, char *attribute, char *value) -{ + ******************************************************************/ + static void + get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, + char *attribute, char *value) + { char **valeurs; - if ( (valeurs = ldap_get_values(ldap_struct, entry, attribute)) ! = NULL) + if ((valeurs = ldap_get_values (ldap_struct, entry, attribute)) != NULL) { - pstrcpy(value, valeurs[0]); - ldap_value_free(valeurs); - DEBUG(3,("get_single_attribute: [%s] = [%s]\n", attribute, value)); + pstrcpy (value, valeurs[0]); + ldap_value_free (valeurs); + DEBUG (2, ("get_single_attribute: [%s] = [%s]\n", attribute, value)); } else { value = NULL; + DEBUG (2, ("get_single_attribute: [%s] = [NULL]\n", attribute)); + } } -} -/******************************************************************* - check if the returned entry is a sambaAccount objectclass. -******************************************************************/ -static BOOL ldap_check_user(LDAP *ldap_struct, LDAPMessage *entry) -{ - BOOL sambaAccount = False; - char **valeur; + /************************************************************************ + Routine to manage the LDAPMod structure array + manage memory used by the array, by each struct, and values + + ************************************************************************/ + static void + make_a_mod (LDAPMod *** modlist, int modop, char *attribute, char *value) + { + LDAPMod **mods; int i; + int j; + + mods = *modlist; - DEBUG(2,("ldap_check_user: ")); - valeur = ldap_get_values(ldap_struct, entry, "objectclass"); - if (valeur! = NULL) + if (attribute == NULL || *attribute == '\0') + return; + + if (value == NULL || *value == '\0') + return; + + if (mods == NULL) { - for (i = 0;valeur[i]! = NULL;i++) + mods = (LDAPMod **) malloc (sizeof (LDAPMod *)); + if (mods == NULL) { - if (!strcmp(valeur[i],"sambaAccount")) sambaAccount = True; + DEBUG (0, ("make_a_mod: out of memory!\n")); + return; } + mods[0] = NULL; } - DEBUG(2,("%s\n",sambaAccount?"yes":"no")); - ldap_value_free(valeur); - return (sambaAccount); -} -/******************************************************************* - check if the returned entry is a sambaTrust objectclass. -******************************************************************/ -static BOOL ldap_check_trust(LDAP *ldap_struct, LDAPMessage *entry) -{ - BOOL sambaTrust = False; - char **valeur; - int i; - - DEBUG(2,("ldap_check_trust: ")); - valeur = ldap_get_values(ldap_struct, entry, "objectclass"); - if (valeur! = NULL) + for (i = 0; mods[i] != NULL; ++i) { - for (i = 0;valeur[i]! = NULL;i++) + if (mods[i]->mod_op == modop && + !strcasecmp (mods[i]->mod_type, attribute)) { - if (!strcmp(valeur[i],"sambaTrust")) sambaTrust = True; + break; } } - DEBUG(2,("%s\n",sambaTrust?"yes":"no")); - ldap_value_free(valeur); - return (sambaTrust); -} - -/******************************************************************* - retrieve the user's info and contruct a smb_passwd structure. -******************************************************************/ -static void ldap_get_smb_passwd(LDAP *ldap_struct,LDAPMessage *entry, - struct smb_passwd *user) -{ - static pstring user_name; - static pstring user_pass; - static pstring temp; - static unsigned char smblmpwd[16]; - static unsigned char smbntpwd[16]; - - pdb_init_smb(user); - - memset((char *)smblmpwd, '\0', sizeof(smblmpwd)); - memset((char *)smbntpwd, '\0', sizeof(smbntpwd)); - - get_single_attribute(ldap_struct, entry, "cn", user_name); - DEBUG(2,("ldap_get_smb_passwd: user: %s\n",user_name)); - -#ifdef LDAP_PLAINTEXT_PASSWORD - get_single_attribute(ldap_struct, entry, "userPassword", temp); - nt_lm_owf_gen(temp, user->smb_nt_passwd, user->smb_passwd); - memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */ -#else - get_single_attribute(ldap_struct, entry, "unicodePwd", temp); - pdb_gethexpwd(temp, smbntpwd); - memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */ - - get_single_attribute(ldap_struct, entry, "dBCSPwd", temp); - pdb_gethexpwd(temp, smblmpwd); - memset((char *)temp, '\0', sizeof(temp)); /* destroy local copy of the password */ -#endif - get_single_attribute(ldap_struct, entry, "userAccountControl", temp); - user->acct_ctrl = pdb_decode_acct_ctrl(temp); - - get_single_attribute(ldap_struct, entry, "pwdLastSet", temp); - user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); - - get_single_attribute(ldap_struct, entry, "rid", temp); - - /* the smb (unix) ids are not stored: they are created */ - user->smb_userid = pdb_user_rid_to_uid (atoi(temp)); - - if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) ) + if (mods[i] == NULL) + { + mods = (LDAPMod **) realloc (mods, (i + 2) * sizeof (LDAPMod *)); + if (mods == NULL) { - DEBUG(0,("Inconsistency in the LDAP database\n")); + DEBUG (0, ("make_a_mod: out of memory!\n")); + return; } - if (user->acct_ctrl & ACB_NORMAL) + mods[i] = (LDAPMod *) malloc (sizeof (LDAPMod)); + if (mods[i] == NULL) { - user->smb_name = user_name; - user->smb_passwd = smblmpwd; - user->smb_nt_passwd = smbntpwd; + DEBUG (0, ("make_a_mod: out of memory!\n")); + return; + } + mods[i]->mod_op = modop; + mods[i]->mod_values = NULL; + mods[i]->mod_type = strdup (attribute); + mods[i + 1] = NULL; } -} -/******************************************************************* - retrieve the user's info and contruct a sam_passwd structure. + if (value != NULL) + { + j = 0; + if (mods[i]->mod_values != NULL) + { + for (; mods[i]->mod_values[j] != NULL; j++); + } + mods[i]->mod_values = (char **) realloc (mods[i]->mod_values, + (j + 2) * sizeof (char *)); + if (mods[i]->mod_values == NULL) + { + DEBUG (0,("make_a_mod: Memory allocation failure!\n")); + return; + } + mods[i]->mod_values[j] = strdup (value); + mods[i]->mod_values[j + 1] = NULL; + } + *modlist = mods; + } - calls ldap_get_smb_passwd function first, though, to save code duplication. + /* New Interface is being implemented here */ -******************************************************************/ -static void ldap_get_sam_passwd(LDAP *ldap_struct, LDAPMessage *entry, - struct sam_passwd *user) -{ - static pstring user_name; - static pstring fullname; - static pstring home_dir; + /********************************************************************** + Initialize SAM_ACCOUNT from an LDAP query + (Based on init_sam_from_buffer in pdb_tdb.c) + *********************************************************************/ + static BOOL + init_sam_from_ldap (SAM_ACCOUNT * sampass, + LDAP * ldap_struct, LDAPMessage * entry) + { + time_t logon_time, + logoff_time, + kickoff_time, + pass_last_set_time, pass_can_change_time, pass_must_change_time; + static pstring username; static pstring dir_drive; + static pstring munged_dial; + static pstring fullname; + static pstring homedir; static pstring logon_script; static pstring profile_path; static pstring acct_desc; static pstring workstations; - static pstring temp; - static struct smb_passwd pw_buf; + static uint8 smblmpwd[16]; + static uint8 smbntpwd[16]; + pstring temp; + struct passwd *sys_user; + uint32 user_rid, group_rid, hours_len; + uint16 acct_ctrl, logon_divs; + uint8 *hours; - pdb_init_sam(user); + get_single_attribute (ldap_struct, entry, "uid", username); + DEBUG (2, ("Entry found for user: %s\n", username)); - ldap_get_smb_passwd(ldap_struct, entry, &pw_buf); + get_single_attribute (ldap_struct, entry, "pwdLastSet", temp); + pass_last_set_time = (time_t) strtol (temp, NULL, 16); - user->pass_last_set_time = pw_buf.pass_last_set_time; + get_single_attribute (ldap_struct, entry, "logonTime", temp); + logon_time = (time_t) strtol (temp, NULL, 16); - get_single_attribute(ldap_struct, entry, "logonTime", temp); - user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); + get_single_attribute (ldap_struct, entry, "logoffTime", temp); + logoff_time = (time_t) strtol (temp, NULL, 16); - get_single_attribute(ldap_struct, entry, "logoffTime", temp); - user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); + get_single_attribute (ldap_struct, entry, "kickoffTime", temp); + kickoff_time = (time_t) strtol (temp, NULL, 16); - get_single_attribute(ldap_struct, entry, "kickoffTime", temp); - user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); + get_single_attribute (ldap_struct, entry, "pwdCanChange", temp); + pass_can_change_time = (time_t) strtol (temp, NULL, 16); - get_single_attribute(ldap_struct, entry, "pwdLastSet", temp); - user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); + get_single_attribute (ldap_struct, entry, "pwdMustChange", temp); + pass_must_change_time = (time_t) strtol (temp, NULL, 16); - get_single_attribute(ldap_struct, entry, "pwdCanChange", temp); - user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); + /* recommend that 'gecos' and 'displayName' should refer to the same + * attribute OID. userFullName depreciated, only used by Samba + * primary rules of LDAP: don't make a new attribute when one is already defined + * that fits your needs; using gecos then displayName then cn rather than 'userFullName' + */ - get_single_attribute(ldap_struct, entry, "pwdMustChange", temp); - user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); + get_single_attribute (ldap_struct, entry, "gecos", fullname); + if (!fullname) + get_single_attribute (ldap_struct, entry, "displayName", fullname); + if (!fullname) + get_single_attribute (ldap_struct, entry, "cn", fullname); + + get_single_attribute (ldap_struct, entry, "homeDrive", dir_drive); + get_single_attribute (ldap_struct, entry, "scriptPath", logon_script); + get_single_attribute (ldap_struct, entry, "profilePath", profile_path); + get_single_attribute (ldap_struct, entry, "description", acct_desc); + get_single_attribute (ldap_struct, entry, "userWorkstations", workstations); + + /* Don't know the appropriate attribute names for these two */ + get_single_attribute (ldap_struct, entry, "rid", temp); + user_rid = (uint32) strtol (temp, NULL, 16); + get_single_attribute (ldap_struct, entry, "primaryGroupID", temp); + group_rid = (uint32) strtol (temp, NULL, 16); + + + /* These values MAY be in LDAP, but they can also be retrieved through + * sys_getpw*() which is how we're doing it (if you use nss_ldap, then + * these values will be stored in LDAP as well, but if not, we want the + * local values to override the LDAP for this anyway + * homeDirectory attribute + */ + sys_user = sys_getpwnam (username); + pstrcpy (homedir, sys_user->pw_dir); - user->smb_name = pw_buf.smb_name; - DEBUG(2,("ldap_get_sam_passwd: user: %s\n", user_name)); + /* FIXME: hours stuff should be cleaner */ + logon_divs = 168; + hours_len = 21; + hours = malloc (sizeof (hours) * hours_len); + memset (hours, 0xff, hours_len); + + switch (lp_ldap_schema ()) + { + case SCHEMA_COMPAT: + get_single_attribute (ldap_struct, entry, "lmPassword", temp); + pdb_gethexpwd (temp, smblmpwd); + memset ((char *) temp, '\0', sizeof (temp)); + get_single_attribute (ldap_struct, entry, "ntPassword", temp); + pdb_gethexpwd (temp, smbntpwd); + memset ((char *) temp, '\0', sizeof (temp)); + get_single_attribute (ldap_struct, entry, "acctFlags", temp); + acct_ctrl = pdb_decode_acct_ctrl (temp); + break; + case SCHEMA_AD: + case SCHEMA_SAMBA: + default: + /* must write appropriate decoding routines for dBCSPwd, unicodePwd, and userAccountControl */ + get_single_attribute (ldap_struct, entry, "dBCSPwd", temp); + pdb_gethexpwd (temp, smblmpwd); + memset ((char *) temp, '\0', sizeof (temp)); + get_single_attribute (ldap_struct, entry, "unicodePwd", temp); + pdb_gethexpwd (temp, smbntpwd); + memset ((char *) temp, '\0', sizeof (temp)); + get_single_attribute (ldap_struct, entry, "userAccountControl", temp); + acct_ctrl = pdb_decode_acct_ctrl (temp); + DEBUG (0, ("Schema not yet implemented\n")); + } + + if (acct_ctrl == 0) + acct_ctrl |= ACB_NORMAL; + + + sampass->logon_time = logon_time; + sampass->logoff_time = logoff_time; + sampass->kickoff_time = kickoff_time; + sampass->pass_can_change_time = pass_can_change_time; + sampass->pass_must_change_time = pass_must_change_time; + sampass->pass_last_set_time = pass_last_set_time; + + sampass->smb_name = username; + sampass->full_name = fullname; + sampass->home_dir = homedir; + sampass->dir_drive = dir_drive; + sampass->logon_script = logon_script; + sampass->profile_path = profile_path; + sampass->acct_desc = acct_desc; + sampass->workstations = workstations; + sampass->munged_dial = munged_dial; + sampass->smb_passwd = smblmpwd; + sampass->smb_nt_passwd = smbntpwd; + + sampass->smb_userid = sys_user->pw_uid; + sampass->smb_grpid = sys_user->pw_gid; + sampass->user_rid = user_rid; + sampass->group_rid = group_rid; + sampass->hours_len = hours_len; + sampass->acct_ctrl = acct_ctrl; + sampass->logon_divs = logon_divs; + memcpy (sampass->hours, hours, hours_len); + + return True; + } + + /********************************************************************** + Initialize SAM_ACCOUNT from an LDAP query + (Based on init_buffer_from_sam in pdb_tdb.c) + *********************************************************************/ + static BOOL + init_ldap_from_sam (LDAPMod *** mods, int ldap_state, SAM_ACCOUNT * sampass) + { + static uint8 smblmpwd[16]; + static uint8 smbntpwd[16]; + pstring temp; - get_single_attribute(ldap_struct, entry, "userFullName", fullname); - user->full_name = fullname; + *mods = NULL; - get_single_attribute(ldap_struct, entry, "homeDirectory", home_dir); - user->home_dir = home_dir; + make_a_mod (mods, LDAP_MOD_ADD, "objectclass", "sambaAccount"); - get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive); - user->dir_drive = dir_drive; + make_a_mod (mods, ldap_state, "uid", sampass->smb_name); + DEBUG (2, ("Setting entry for user: %s\n", sampass->smb_name)); - get_single_attribute(ldap_struct, entry, "scriptPath", logon_script); - user->logon_script = logon_script; + slprintf (temp, sizeof (temp) - 1, "%i", sampass->smb_userid); + make_a_mod (mods, ldap_state, "uidNumber", temp); - get_single_attribute(ldap_struct, entry, "profilePath", profile_path); - user->profile_path = profile_path; + slprintf (temp, sizeof (temp) - 1, "%li", sampass->pass_last_set_time); + make_a_mod (mods, ldap_state, "pwdLastSet", temp); - get_single_attribute(ldap_struct, entry, "comment", acct_desc); - user->acct_desc = acct_desc; + slprintf (temp, sizeof (temp) - 1, "%li", sampass->logon_time); + make_a_mod (mods, ldap_state, "logonTime", temp); - get_single_attribute(ldap_struct, entry, "userWorkstations", workstations); - user->workstations = workstations; + slprintf (temp, sizeof (temp) - 1, "%li", sampass->logoff_time); + make_a_mod (mods, ldap_state, "logoffTime", temp); - user->unknown_str = NULL; /* don't know, yet! */ - user->munged_dial = NULL; /* "munged" dial-back telephone number */ + slprintf (temp, sizeof (temp) - 1, "%li", sampass->kickoff_time); + make_a_mod (mods, ldap_state, "kickoffTime", temp); - get_single_attribute(ldap_struct, entry, "rid", temp); - user->user_rid = atoi(temp); + slprintf (temp, sizeof (temp) - 1, "%li", sampass->pass_can_change_time); + make_a_mod (mods, ldap_state, "pwdCanChange", temp); - get_single_attribute(ldap_struct, entry, "primaryGroupID", temp); - user->group_rid = atoi(temp); + slprintf (temp, sizeof (temp) - 1, "%li", sampass->pass_must_change_time); + make_a_mod (mods, ldap_state, "pwdMustChange", temp); - /* the smb (unix) ids are not stored: they are created */ - user->smb_userid = pw_buf.smb_userid; - user->smb_grpid = group_rid_to_uid(user->group_rid); + /* displayName, cn, and gecos should all be the same + * most easily accomplished by giving them the same OID + * gecos isn't set here b/c it should be handled by the + * add-user script + */ - user->acct_ctrl = pw_buf.acct_ctrl; + make_a_mod (mods, ldap_state, "displayName", sampass->full_name); + make_a_mod (mods, ldap_state, "cn", sampass->full_name); - user->unknown_3 = 0xffffff; /* don't know */ - user->logon_divs = 168; /* hours per week */ - user->hours_len = 21; /* 21 times 8 bits = 168 */ - memset(user->hours, 0xff, user->hours_len); /* available at all hours */ - user->unknown_5 = 0x00020000; /* don't know */ - user->unknown_5 = 0x000004ec; /* don't know */ + make_a_mod (mods, ldap_state, "homeDirectory", sampass->home_dir); + make_a_mod (mods, ldap_state, "homeDrive", sampass->dir_drive); + make_a_mod (mods, ldap_state, "scriptPath", sampass->logon_script); + make_a_mod (mods, ldap_state, "profilePath", sampass->profile_path); + make_a_mod (mods, ldap_state, "description", sampass->acct_desc); + make_a_mod (mods, ldap_state, "userWorkstations", sampass->workstations); + + /* Don't know the appropriate attribute names for these two */ + /* slprintf (temp, sizeof (temp) - 1, "%i", sampass->user_rid); + * make_a_mod (mods, ldap_state, "rid", temp); + * slprintf (temp, sizeof (temp) - 1, "%i", sampass->group_rid); + * make_a_mod (mods, ldap_state, "primaryGroupID", temp); + */ + /* FIXME: Hours stuff goes in LDAP? */ - if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) ) + switch (lp_ldap_schema ()) { - DEBUG(0,("Inconsistency in the LDAP database\n")); + case SCHEMA_COMPAT: + pdb_sethexpwd (temp, smblmpwd, sampass->acct_ctrl); + make_a_mod (mods, ldap_state, "lmPassword", temp); + pdb_sethexpwd (temp, smbntpwd, sampass->acct_ctrl); + make_a_mod (mods, ldap_state, "ntPassword", temp); + make_a_mod (mods, ldap_state, "acctFlags", + pdb_encode_acct_ctrl (sampass->acct_ctrl, + NEW_PW_FORMAT_SPACE_PADDED_LEN)); + break; + case SCHEMA_AD: + case SCHEMA_SAMBA: + default: + /* must write appropriate decoding routines for dBCSPwd, unicodePwd, and userAccountControl */ + pdb_sethexpwd (temp, smblmpwd, sampass->acct_ctrl); + make_a_mod (mods, ldap_state, "dBCSPwd", temp); + pdb_sethexpwd (temp, smbntpwd, sampass->acct_ctrl); + make_a_mod (mods, ldap_state, "unicodePwd", temp); + make_a_mod (mods, ldap_state, "userAccountControl", + pdb_encode_acct_ctrl (sampass->acct_ctrl, + NEW_PW_FORMAT_SPACE_PADDED_LEN)); + DEBUG (0, ("Schema not yet implemented\n")); } - if (!(user->acct_ctrl & ACB_NORMAL)) - { - DEBUG(0,("User's acct_ctrl bits not set to ACT_NORMAL in LDAP database\n")); - return; + return True; } -} - -/************************************************************************ - Routine to manage the LDAPMod structure array - manage memory used by the array, by each struct, and values -************************************************************************/ -static void make_a_mod(LDAPMod ***modlist,int modop, char *attribute, char *value) -{ - LDAPMod **mods; - int i; - int j; - - mods = *modlist; - - if (mods == NULL) + /********************************************************************** + Connect to LDAP server for password enumeration + *********************************************************************/ + static BOOL + pdb_setsampwent (BOOL update) { - mods = (LDAPMod **)malloc( sizeof(LDAPMod *) ); - if (mods == NULL) + int rc; + pstring filter; + + if (!ldap_open_connection (&global_ldap_ent.ldap_struct)) { - DEBUG(0,("make_a_mod: out of memory!\n")); - return; + return False; } - mods[0] = NULL; + if (!ldap_connect_system (global_ldap_ent.ldap_struct)) + { + ldap_unbind (global_ldap_ent.ldap_struct); + return False; } - for ( i = 0; mods[ i ] ! = NULL; ++i ) - { - if ( mods[ i ]->mod_op == modop && - !strcasecmp( mods[ i ]->mod_type, attribute ) ) - { - break; + pstrcpy (filter, lp_ldap_filter ()); + all_string_sub (filter, "%u", "*", sizeof (pstring)); + + rc = + ldap_search_s (global_ldap_ent.ldap_struct, lp_ldap_suffix (), + LDAP_SCOPE_SUBTREE, filter, NULL, 0, + &global_ldap_ent.result); + + if (rc != LDAP_SUCCESS) + { + DEBUG (0, ("LDAP search failed: %s\n", ldap_err2string (rc))); + DEBUG (3, ("Query was: %s, %s\n", lp_ldap_suffix (), filter)); + ldap_msgfree (global_ldap_ent.result); + ldap_unbind (global_ldap_ent.ldap_struct); + global_ldap_ent.ldap_struct = NULL; + global_ldap_ent.result = NULL; + return False; } + + DEBUG (2, + ("%d entries in the base!\n", + ldap_count_entries (global_ldap_ent.ldap_struct, + global_ldap_ent.result))); + + global_ldap_ent.entry = + ldap_first_entry (global_ldap_ent.ldap_struct, global_ldap_ent.result); + + return True; } - if (mods[i] == NULL) + /********************************************************************** + End enumeration of the LDAP password list + *********************************************************************/ + static void + pdb_endsampwent (void) { - mods = (LDAPMod **)realloc( mods, (i+2) * sizeof( LDAPMod * ) ); - if (mods == NULL) + if (global_ldap_ent.ldap_struct && global_ldap_ent.result) { - DEBUG(0,("make_a_mod: out of memory!\n")); - return; + ldap_msgfree (global_ldap_ent.result); + ldap_unbind (global_ldap_ent.ldap_struct); + global_ldap_ent.ldap_struct = NULL; + global_ldap_ent.result = NULL; } - mods[i] = (LDAPMod *)malloc( sizeof( LDAPMod ) ); - if (mods[i] == NULL) - { - DEBUG(0,("make_a_mod: out of memory!\n")); - return; - } - mods[i]->mod_op = modop; - mods[i]->mod_values = NULL; - mods[i]->mod_type = strdup( attribute ); - mods[i+1] = NULL; } - if (value ! = NULL ) + /********************************************************************** + Get the next entry in the LDAP password database + *********************************************************************/ + static BOOL + pdb_getsampwent (SAM_ACCOUNT * user) { - j = 0; - if ( mods[ i ]->mod_values ! = NULL ) + if (!global_ldap_ent.entry) { - for ( ; mods[ i ]->mod_values[ j ] ! = NULL; j++ ); + return False; } - mods[ i ]->mod_values = (char **)realloc(mods[ i ]->mod_values, - (j+2) * sizeof( char * )); - if ( mods[ i ]->mod_values == NULL) + + global_ldap_ent.entry = + ldap_next_entry (global_ldap_ent.ldap_struct, global_ldap_ent.entry); + + if (global_ldap_ent.entry != NULL) { - DEBUG(0, "make_a_mod: Memory allocation failure!\n"); - return; + return init_sam_from_ldap (user, global_ldap_ent.ldap_struct, + global_ldap_ent.entry); } - mods[ i ]->mod_values[ j ] = strdup(value); - mods[ i ]->mod_values[ j + 1 ] = NULL; + return False; } - *modlist = mods; -} - -/************************************************************************ - Add or modify an entry. Only the smb struct values - -*************************************************************************/ -static BOOL modadd_ldappwd_entry(struct smb_passwd *newpwd, int flag) -{ - - /* assume the struct is correct and filled - that's the job of passdb.c to check */ - int scope = LDAP_SCOPE_ONELEVEL; - int rc; - char *smb_name; - int trust = False; - int ldap_state; - pstring filter; - pstring dn; - pstring lmhash; - pstring nthash; - pstring rid; - pstring lst; - pstring temp; + /********************************************************************** + Get SAM_ACCOUNT entry from LDAP by username + *********************************************************************/ + static BOOL + pdb_getsampwnam (SAM_ACCOUNT * user, char *sname) + { LDAP *ldap_struct; LDAPMessage *result; - LDAPMod **mods; - - smb_name = newpwd->smb_name; + LDAPMessage *entry; - if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + if (!ldap_open_connection (&ldap_struct)) + return False; + if (!ldap_connect_system (ldap_struct)) { + ldap_unbind (ldap_struct); return False; } - - if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + if (ldap_search_one_user_by_name (ldap_struct, sname, &result) != LDAP_SUCCESS) { - ldap_unbind(ldap_struct); + ldap_unbind (ldap_struct); return False; } - - if (smb_name[strlen(smb_name)-1] == '$' ) + if (ldap_count_entries (ldap_struct, result) < 1) { - smb_name[strlen(smb_name)-1] = '\0'; - trust = True; + DEBUG (0, + ("We don't find this user [%s] count=%d\n", sname, + ldap_count_entries (ldap_struct, result))); + ldap_unbind (ldap_struct); + return False; } - - slprintf(filter, sizeof(filter)-1, - "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))", - smb_name); - - rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result); - - switch (flag) - { - case ADD_USER: + entry = ldap_first_entry (ldap_struct, result); + if (entry) { - if (ldap_count_entries(ldap_struct, result) ! = 0) + init_sam_from_ldap (user, ldap_struct, entry); + ldap_msgfree (result); + ldap_unbind (ldap_struct); + return True; + } + else { - DEBUG(0,("User already in the base, with samba properties\n")); - ldap_unbind(ldap_struct); + ldap_msgfree (result); + ldap_unbind (ldap_struct); return False; } - ldap_state = LDAP_MOD_ADD; - break; } - case MODIFY_USER: + + + /********************************************************************** + Get SAM_ACCOUNT entry from LDAP by uid + *********************************************************************/ + static BOOL + pdb_getsampwuid (SAM_ACCOUNT * user, uid_t uid) { - if (ldap_count_entries(ldap_struct, result) ! = 1) + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + + if (!ldap_open_connection (&ldap_struct)) + return False; + if (!ldap_connect_system (ldap_struct)) { - DEBUG(0,("No user to modify !\n")); - ldap_unbind(ldap_struct); + ldap_unbind (ldap_struct); return False; } - ldap_state = LDAP_MOD_REPLACE; - break; - } - default: + if (ldap_search_one_user_by_uid (ldap_struct, uid, &result) != LDAP_SUCCESS) { - DEBUG(0,("How did you come here? \n")); - ldap_unbind(ldap_struct); + ldap_unbind (ldap_struct); return False; - break; - } } - slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() ); - if (newpwd->smb_passwd ! = NULL) - { - int i; - for( i = 0; i < 16; i++) + if (ldap_count_entries (ldap_struct, result) < 1) { - slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_passwd[i]); - } - + DEBUG (0, + ("We don't find this uid [%i] count=%d\n", uid, + ldap_count_entries (ldap_struct, result))); + ldap_unbind (ldap_struct); + return False; } - else - { - if (newpwd->acct_ctrl & ACB_PWNOTREQ) + entry = ldap_first_entry (ldap_struct, result); + if (entry) { - slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + init_sam_from_ldap (user, ldap_struct, entry); + ldap_msgfree (result); + ldap_unbind (ldap_struct); + return True; } else { - slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + ldap_msgfree (result); + ldap_unbind (ldap_struct); + return False; } } - slprintf(lmhash, sizeof(lmhash)-1, "%s", temp); - if (newpwd->smb_nt_passwd ! = NULL) - { - int i; - for( i = 0; i < 16; i++) + + /********************************************************************** + Delete entry from LDAP for username + *********************************************************************/ + static BOOL + pdb_delete_sam_account (char *sname) { - slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_nt_passwd[i]); + /* FIXME: make this work */ + return False; } - } - else + /********************************************************************** + Update SAM_ACCOUNT + *********************************************************************/ + static BOOL + pdb_update_sam_account (SAM_ACCOUNT * newpwd, BOOL override) { - if (newpwd->acct_ctrl & ACB_PWNOTREQ) + int rc; + pstring dn; + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + LDAPMod **mods; + + if (!ldap_open_connection (&ldap_struct)) /* open a connection to the server */ { - slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + return False; } - else + + if (!ldap_connect_system (ldap_struct)) /* connect as system account */ { - slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); - } + ldap_unbind (ldap_struct); + return False; } - slprintf(nthash, sizeof(nthash)-1, "%s", temp); - - slprintf(rid, sizeof(rid)-1, "%d", uid_to_user_rid(newpwd->smb_userid) ); - slprintf(lst, sizeof(lst)-1, "%08X", newpwd->pass_last_set_time); - mods = NULL; + rc = ldap_search_one_user_by_name (ldap_struct, newpwd->smb_name, &result); - if (trust) - { - make_a_mod(&mods, ldap_state, "objectclass", "sambaTrust"); - make_a_mod(&mods, ldap_state, "netbiosTrustName", smb_name); - make_a_mod(&mods, ldap_state, "trustPassword", nthash); - } - else + if (ldap_count_entries (ldap_struct, result) == 0) { - make_a_mod(&mods, ldap_state, "objectclass", "sambaAccount"); - make_a_mod(&mods, ldap_state, "dBCSPwd", lmhash); - make_a_mod(&mods, ldap_state, "uid", smb_name); - make_a_mod(&mods, ldap_state, "unicodePwd", nthash); + DEBUG (0, ("No user to modify!\n")); + ldap_msgfree (result); + ldap_unbind (ldap_struct); + return False; } - make_a_mod(&mods, ldap_state, "cn", smb_name); + init_ldap_from_sam (&mods, LDAP_MOD_REPLACE, newpwd); - make_a_mod(&mods, ldap_state, "rid", rid); - make_a_mod(&mods, ldap_state, "pwdLastSet", lst); - make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN)); + entry = ldap_first_entry (ldap_struct, result); + get_single_attribute (ldap_struct, entry, "dn", dn); - switch(flag) - { - case ADD_USER: - { - ldap_add_s(ldap_struct, dn, mods); - DEBUG(2,("modadd_ldappwd_entry: added: cn = %s in the LDAP database\n",smb_name)); - break; - } - case MODIFY_USER: - { - ldap_modify_s(ldap_struct, dn, mods); - DEBUG(2,("modadd_ldappwd_entry: changed: cn = %s in the LDAP database_n",smb_name)); - break; - } - default: + rc = ldap_modify_s (ldap_struct, dn, mods); + + if (rc != LDAP_SUCCESS) { - DEBUG(2,("modadd_ldappwd_entry: How did you come here? \n")); - ldap_unbind(ldap_struct); + char *ld_error; + ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG (0, + ("failed to modify user with uid = %s with: %s\n\t%s\n", + newpwd->smb_name, ldap_err2string (rc), ld_error)); + free(ld_error); + ldap_unbind (ldap_struct); return False; - break; - } } - ldap_mods_free(mods, 1); - - ldap_unbind(ldap_struct); - + DEBUG (2, + ("successfully modified uid = %s in the LDAP database\n", + newpwd->smb_name)); + ldap_mods_free (mods, 1); + ldap_unbind (ldap_struct); return True; -} - -/************************************************************************ - Add or modify an entry. everything except the smb struct - -*************************************************************************/ -static BOOL modadd_ldap21pwd_entry(struct sam_passwd *newpwd, int flag) -{ + } - /* assume the struct is correct and filled - that's the job of passdb.c to check */ - int scope = LDAP_SCOPE_ONELEVEL; + /********************************************************************** + Add SAM_ACCOUNT to LDAP + *********************************************************************/ + static BOOL + pdb_add_sam_account (SAM_ACCOUNT * newpwd) + { int rc; - char *smb_name; - int trust = False; - int ldap_state; pstring filter; - pstring dn; - pstring lmhash; - pstring nthash; - pstring rid; - pstring lst; - pstring temp; - LDAP *ldap_struct; LDAPMessage *result; LDAPMod **mods; + pstring dn; + int ldap_op = LDAP_MOD_ADD; - smb_name = newpwd->smb_name; - - if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + if (!ldap_open_connection (&ldap_struct)) /* open a connection to the server */ { return False; } - if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + if (!ldap_connect_system (ldap_struct)) /* connect as system account */ { - ldap_unbind(ldap_struct); + ldap_unbind (ldap_struct); return False; } - if (smb_name[strlen(smb_name)-1] == '$' ) - { - smb_name[strlen(smb_name)-1] = '\0'; - trust = True; - } + if(newpwd->smb_name != NULL) + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", newpwd->smb_name, + lp_ldap_suffix ()); + else + return False; - slprintf(filter, sizeof(filter)-1, - "(&(cn = %s)(|(objectclass = sambaTrust)(objectclass = sambaAccount)))", - smb_name); - rc = ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result); + rc = ldap_search_one_user_by_name (ldap_struct, newpwd->smb_name, &result); - switch (flag) + if (ldap_count_entries (ldap_struct, result) != 0) { - case ADD_USER: - { - if (ldap_count_entries(ldap_struct, result) ! = 1) - { - DEBUG(2,("User already in the base, with samba properties\n")); - ldap_unbind(ldap_struct); + DEBUG (0, ("User already in the base, with samba properties\n")); + ldap_msgfree (result); + ldap_unbind (ldap_struct); return False; } - ldap_state = LDAP_MOD_ADD; - break; - } + ldap_msgfree (result); - case MODIFY_USER: - { - if (ldap_count_entries(ldap_struct, result) ! = 1) + slprintf(filter, sizeof(filter) - 1, "uid=%s", newpwd->smb_name); + rc = ldap_search_one_user (ldap_struct, filter, &result); + if (ldap_count_entries (ldap_struct, result) == 1) { - DEBUG(2,("No user to modify !\n")); - ldap_unbind(ldap_struct); - return False; + DEBUG(3,("User exists without samba properties: adding them\n")); + ldap_op = LDAP_MOD_REPLACE; } - ldap_state = LDAP_MOD_REPLACE; - break; - } - - default: + else { - DEBUG(2,("How did you come here? \n")); - ldap_unbind(ldap_struct); + DEBUG(3,("More than one user with that uid exists: bailing out!\n")); return False; - break; - } } - slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() ); - mods = NULL; + ldap_msgfree (result); - if (trust) + init_ldap_from_sam (&mods, ldap_op, newpwd); + + if(ldap_op == LDAP_MOD_REPLACE) { + rc = ldap_modify_s (ldap_struct, dn, mods); } else { + rc = ldap_add_s (ldap_struct, dn, mods); } - make_a_mod(&mods, ldap_state, "cn", smb_name); - - make_a_mod(&mods, ldap_state, "rid", rid); - make_a_mod(&mods, ldap_state, "pwdLastSet", lst); - make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl,NEW_PW_FORMAT_SPACE_PADDED_LEN)); - - ldap_modify_s(ldap_struct, dn, mods); - - ldap_mods_free(mods, 1); - - ldap_unbind(ldap_struct); - + if (rc != LDAP_SUCCESS) + { + char *ld_error; + ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG (0, + ("failed to modify user with uid = %s with: %s\n\t%s\n", + newpwd->smb_name, ldap_err2string (rc), ld_error)); + free(ld_error); + ldap_mods_free (mods, 1); + ldap_unbind (ldap_struct); + return False; + } + DEBUG (2, ("added: uid = %s in the LDAP database\n", newpwd->smb_name)); + ldap_mods_free (mods, 1); + ldap_unbind (ldap_struct); return True; } -/************************************************************************ - Routine to add an entry to the ldap passwd file. +/*************************************************************** + wrapper function for the old interface below + ****************************************************************/ +static void * +startldappwent (BOOL update) +{ + if (pdb_setsampwent (update)) + return &global_ldap_ent; - do not call this function directly. use passdb.c instead. + return NULL; +} -*************************************************************************/ -static BOOL add_ldappwd_entry(struct smb_passwd *newpwd) +static struct smb_passwd * +getldappwent (void *vp) { - return (modadd_ldappwd_entry(newpwd, ADD_USER) ); -} + /* ignores the vp passed, uses global */ -/************************************************************************ - Routine to search the ldap passwd file for an entry matching the username. - and then modify its password entry. We can't use the startldappwent()/ - getldappwent()/endldappwent() interfaces here as we depend on looking - in the actual file to decide how much room we have to write data. - override = False, normal - override = True, override XXXXXXXX'd out password or NO PASS + SAM_ACCOUNT user; - do not call this function directly. use passdb.c instead. + pdb_init_sam (&user); + if (pdb_getsampwent (&user)) + return pdb_sam_to_smb (&user); -************************************************************************/ -static BOOL mod_ldappwd_entry(struct smb_passwd *pwd, BOOL override) -{ - return (modadd_ldappwd_entry(pwd, MODIFY_USER) ); -} + return NULL; -/************************************************************************ - Routine to add an entry to the ldap passwd file. +} - do not call this function directly. use passdb.c instead. -*************************************************************************/ -static BOOL add_ldap21pwd_entry(struct sam_passwd *newpwd) +static void +endldappwent (void *vp) { - return( modadd_ldappwd_entry(newpwd, ADD_USER)? - modadd_ldap21pwd_entry(newpwd, ADD_USER):False); + pdb_endsampwent (); } -/************************************************************************ - Routine to search the ldap passwd file for an entry matching the username. - and then modify its password entry. We can't use the startldappwent()/ - getldappwent()/endldappwent() interfaces here as we depend on looking - in the actual file to decide how much room we have to write data. - override = False, normal - override = True, override XXXXXXXX'd out password or NO PASS - - do not call this function directly. use passdb.c instead. - -************************************************************************/ -static BOOL mod_ldap21pwd_entry(struct sam_passwd *pwd, BOOL override) +static SMB_BIG_UINT +getldappwpos (void *vp) { - return( modadd_ldappwd_entry(pwd, MODIFY_USER)? - modadd_ldap21pwd_entry(pwd, MODIFY_USER):False); + return (SMB_BIG_UINT) 0; } -struct ldap_enum_info +static BOOL +setldappwpos (void *vp, SMB_BIG_UINT tok) { - LDAP *ldap_struct; - LDAPMessage *result; - LDAPMessage *entry; -}; + return False; +} -static struct ldap_enum_info ldap_ent; +static struct smb_passwd * +getldappwnam (char *name) +{ + SAM_ACCOUNT user; -/*************************************************************** - Start to enumerate the ldap passwd list. Returns a void pointer - to ensure no modification outside this module. + pdb_init_sam (&user); + if (pdb_getsampwnam (&user, name)) + return pdb_sam_to_smb (&user); - do not call this function directly. use passdb.c instead. + return NULL; +} - ****************************************************************/ -static void *startldappwent(BOOL update) +static struct smb_passwd * +getldappwuid (uid_t smb_userid) { - int scope = LDAP_SCOPE_ONELEVEL; - int rc; + SAM_ACCOUNT user; - pstring filter; + pdb_init_sam (&user); + if (pdb_getsampwuid (&user, smb_userid)) + return pdb_sam_to_smb (&user); - if (!ldap_open_connection(&ldap_ent.ldap_struct)) /* open a connection to the server */ - { - return NULL; - } - - if (!ldap_connect_system(ldap_ent.ldap_struct)) /* connect as system account */ - { return NULL; - } - - /* when the class is known the search is much faster */ - switch (0) - { - case 1: - { - pstrcpy(filter, "objectclass = sambaAccount"); - break; - } - case 2: - { - pstrcpy(filter, "objectclass = sambaTrust"); - break; - } - default: - { - pstrcpy(filter, "(|(objectclass = sambaTrust)(objectclass = sambaAccount))"); - break; - } - } +} - rc = ldap_search_s(ldap_ent.ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &ldap_ent.result); +static struct smb_passwd * +getldappwrid (uint32 user_rid) +{ + return getldappwuid (pdb_user_rid_to_uid (user_rid)); +} - DEBUG(2,("%d entries in the base!\n", ldap_count_entries(ldap_ent.ldap_struct, ldap_ent.result) )); +static BOOL +add_ldappwd_entry (struct smb_passwd *newpwd) +{ - ldap_ent.entry = ldap_first_entry(ldap_ent.ldap_struct, ldap_ent.result); + return pdb_add_sam_account (pdb_smb_to_sam (newpwd)); +} - return &ldap_ent; +static BOOL +mod_ldappwd_entry (struct smb_passwd *pwd, BOOL override) +{ + return pdb_update_sam_account (pdb_smb_to_sam (pwd), override); } -/************************************************************************* - Routine to return the next entry in the ldap passwd list. +static BOOL +del_ldappwd_entry (const char *name) +{ + return False; /* Dummy... */ +} - do not call this function directly. use passdb.c instead. +static BOOL +add_ldap21pwd_entry (SAM_ACCOUNT * newpwd) +{ + return pdb_add_sam_account (newpwd); +} - *************************************************************************/ -static struct smb_passwd *getldappwent(void *vp) +static BOOL +mod_ldap21pwd_entry (SAM_ACCOUNT * newpwd, BOOL override) { - static struct smb_passwd user; - struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp; + return pdb_update_sam_account (newpwd, override); +} - ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry); +static struct sam_disp_info * +getldapdispnam (char *name) +{ + SAM_ACCOUNT user; - if (ldap_vp->entry ! = NULL) + pdb_init_sam (&user); + if (pdb_getsampwnam (&user, name)) { - ldap_get_smb_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user); - return &user; + return pdb_sam_to_dispinfo (&user); } + return NULL; } -/************************************************************************* - Routine to return the next entry in the ldap passwd list. - - do not call this function directly. use passdb.c instead. - - *************************************************************************/ -static struct sam_passwd *getldap21pwent(void *vp) +static struct sam_disp_info * +getldapdisprid (uint32 rid) { - static struct sam_passwd user; - struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp; + SAM_ACCOUNT user; - ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry); - if (ldap_vp->entry ! = NULL) + pdb_init_sam (&user); + if (pdb_getsampwuid (&user, pdb_user_rid_to_uid (rid))) { - ldap_get_sam_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user); - return &user; + return pdb_sam_to_dispinfo (&user); } - return NULL; -} -/*************************************************************** - End enumeration of the ldap passwd list. - - do not call this function directly. use passdb.c instead. - -****************************************************************/ -static void endldappwent(void *vp) -{ - struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp; - ldap_msgfree(ldap_vp->result); - ldap_unbind(ldap_vp->ldap_struct); + return NULL; } -/************************************************************************* - Return the current position in the ldap passwd list as an SMB_BIG_UINT. - This must be treated as an opaque token. - - do not call this function directly. use passdb.c instead. - -*************************************************************************/ -static SMB_BIG_UINT getldappwpos(void *vp) +static struct sam_disp_info * +getldapdispent (void *vp) { - return (SMB_BIG_UINT)0; -} + SAM_ACCOUNT user; -/************************************************************************* - Set the current position in the ldap passwd list from SMB_BIG_UINT. - This must be treated as an opaque token. - - do not call this function directly. use passdb.c instead. + pdb_init_sam (&user); + if (pdb_getsampwent (&user)) + { + return pdb_sam_to_dispinfo (&user); + } -*************************************************************************/ -static BOOL setldappwpos(void *vp, SMB_BIG_UINT tok) -{ - return False; + return NULL; } -/* - * Ldap derived functions. - */ - -static struct smb_passwd *getldappwnam(char *name) +static SAM_ACCOUNT * +getldap21pwent (void *vp) { - return pdb_sam_to_smb(iterate_getsam21pwnam(name)); -} + static SAM_ACCOUNT user; -static struct smb_passwd *getldappwuid(uid_t smb_userid) -{ - return pdb_sam_to_smb(iterate_getsam21pwuid(smb_userid)); -} + pdb_init_sam (&user); + if (pdb_getsampwent (&user)) + return &user; -static struct smb_passwd *getldappwrid(uint32 user_rid) -{ - return pdb_sam_to_smb(iterate_getsam21pwuid(pdb_user_rid_to_uid(user_rid))); -} + return NULL; -static struct smb_passwd *getldappwent(void *vp) -{ - return pdb_sam_to_smb(getldap21pwent(vp)); } -static BOOL add_ldappwd_entry(struct smb_passwd *newpwd) +static SAM_ACCOUNT * +getldap21pwnam (char *sname) { - return add_ldap21pwd_entry(pdb_smb_to_sam(newpwd)); -} + static SAM_ACCOUNT user; + pdb_init_sam (&user); -static BOOL mod_ldappwd_entry(struct smb_passwd* pwd, BOOL override) -{ - return mod_ldap21pwd_entry(pdb_smb_to_sam(pwd), override); -} + if (pdb_getsampwnam (&user, sname)) + { + return &user; + } -static BOOL del_ldappwd_entry(const char *name) -{ - return False; /* Dummy... */ + return NULL; } -static struct sam_disp_info *getldapdispnam(char *name) +static SAM_ACCOUNT * +getldap21pwuid (uid_t uid) { - return pdb_sam_to_dispinfo(getldap21pwnam(name)); -} + static SAM_ACCOUNT user; + pdb_init_sam (&user); -static struct sam_disp_info *getldapdisprid(uint32 rid) -{ - return pdb_sam_to_dispinfo(getldap21pwrid(rid)); -} + if (pdb_getsampwuid (&user, uid)) + { + return &user; + } -static struct sam_disp_info *getldapdispent(void *vp) -{ - return pdb_sam_to_dispinfo(getldap21pwent(vp)); + return NULL; } -static struct sam_passwd *getldap21pwuid(uid_t uid) +static SAM_ACCOUNT * +getldap21pwrid (uint32 rid) { - return pdb_smb_to_sam(iterate_getsam21pwuid(pdb_uid_to_user_rid(uid))); + return getldap21pwuid (pdb_user_rid_to_uid (rid)); } -static struct passdb_ops ldap_ops = -{ +static struct passdb_ops ldap_ops = { startldappwent, endldappwent, getldappwpos, @@ -1009,9 +1127,9 @@ mod_ldappwd_entry, del_ldappwd_entry, getldap21pwent, - iterate_getsam21pwnam, /* From passdb.c */ - iterate_getsam21pwuid, /* From passdb.c */ - iterate_getsam21pwrid, /* From passdb.c */ + getldap21pwnam, + getldap21pwuid, + getldap21pwrid, add_ldap21pwd_entry, mod_ldap21pwd_entry, getldapdispnam, @@ -1019,12 +1137,15 @@ getldapdispent }; -struct passdb_ops *ldap_initialize_password_db(void) +struct passdb_ops * +ldap_initialize_password_db (void) { return &ldap_ops; } - #else - void dummy_function(void); - void dummy_function(void) { } /* stop some compilers complaining */ +void dummy_function (void); +void +dummy_function (void) +{ +} /* stop some compilers complaining */ #endif --=-1/q6XNvs1fy4xj2xf0LG--