From 5fa8775d9758254f6f4784a0e34c9b5b8bf18bdb Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 6 May 1998 17:43:44 +0000 Subject: jean-francois micouleau's well-alpha code for ldap password database stuff! he's going to hate me for checking this in so early, but... (This used to be commit ad9ba0a1cbac5c4e6cbcbcadefe8f1df72231f74) --- source3/include/includes.h | 5 + source3/include/proto.h | 20 +- source3/param/loadparm.c | 29 ++ source3/passdb/ldap.c | 563 ++++++++++++++++++++++++++++++++++ source3/passdb/smbpass.c | 9 + source3/rpc_server/srv_ldap_helpers.c | 162 ++++++++++ source3/rpc_server/srv_samr.c | 126 ++++---- 7 files changed, 859 insertions(+), 55 deletions(-) create mode 100644 source3/passdb/ldap.c create mode 100644 source3/rpc_server/srv_ldap_helpers.c (limited to 'source3') diff --git a/source3/include/includes.h b/source3/include/includes.h index 5fc2811981..859603c29f 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -1212,6 +1212,11 @@ extern char *sys_errlist[]; #define MAXCODEPAGELINES 256 #endif +#ifdef USE_LDAP +#include "lber.h" +#include "ldap.h" +#endif + /***** automatically generated prototypes *****/ #include "proto.h" diff --git a/source3/include/proto.h b/source3/include/proto.h index fc41d18a1d..720806026b 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -840,6 +840,14 @@ void make_wks_r_query_info(WKS_R_QUERY_INFO *r_u, int status) ; void wks_io_r_query_info(char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int depth); +/*The following definitions come from lib/rpc/server/srv_ldap_helpers.c */ + +BOOL get_ldap_entries(SAM_USER_INFO_21 *pw_buf, + int *total_entries, int *num_entries, + int max_num_entries, + uint16 acb_mask, int switch_level); +BOOL ldap_get_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid); + /*The following definitions come from lib/rpc/server/srv_lsa.c */ BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data); @@ -952,6 +960,11 @@ char *lp_domain_admin_users(void); char *lp_domain_guest_users(void); char *lp_domain_hostsallow(void); char *lp_domain_hostsdeny(void); +char *lp_ldap_server(void); +char *lp_ldap_suffix(void); +char *lp_ldap_filter(void); +char *lp_ldap_root(void); +char *lp_ldap_rootpasswd(void); BOOL lp_dns_proxy(void); BOOL lp_wins_support(void); BOOL lp_we_are_a_wins_server(void); @@ -1005,6 +1018,7 @@ int lp_client_code_page(void); int lp_announce_as(void); int lp_lm_announce(void); int lp_lm_interval(void); +int lp_ldap_port(void); char *lp_preexec(int ); char *lp_postexec(int ); char *lp_rootpreexec(int ); @@ -1547,14 +1561,14 @@ BOOL pm_process( char *FileName, void generate_next_challenge(char *challenge); BOOL set_challenge(char *challenge); -BOOL last_challenge(char *challenge); +BOOL last_challenge(unsigned char *challenge); user_struct *get_valid_user_struct(uint16 vuid); void invalidate_vuid(uint16 vuid); char *validated_username(uint16 vuid); int setup_groups(char *user, int uid, int gid, int *p_ngroups, int **p_igroups, gid_t **p_groups, int **p_attrs); -uint16 register_vuid(int uid,int gid, char *name,BOOL guest); +uint16 register_vuid(int uid,int gid, char *unix_name, char *requested_name, BOOL guest); void add_session_user(char *user); BOOL update_smbpassword_file( char *user, fstring password); void dfs_unlogin(void); @@ -1726,7 +1740,7 @@ int reply_lanman2(char *outbuf); int reply_nt1(char *outbuf); void close_cnum(int cnum, uint16 vuid); void exit_server(char *reason); -void standard_sub(int cnum,char *str); +void standard_sub(int cnum,char *str,uint16 vuid); char *smb_fn_name(int type); int chain_reply(char *inbuf,char *outbuf,int size,int bufsize); int construct_reply(char *inbuf,char *outbuf,int size,int bufsize); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index cbb17adc95..7483af54a4 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -144,6 +144,11 @@ typedef struct char *szDomainGroups; char *szDriverFile; char *szNameResolveOrder; + char *szLdapServer; + char *szLdapSuffix; + char *szLdapFilter; + char *szLdapRoot; + char *szLdapRootPassword; int max_log_size; int mangled_stack; int max_xmit; @@ -167,6 +172,7 @@ typedef struct int shmem_size; int client_code_page; int announce_as; /* This is initialised in init_globals */ + int ldap_port; BOOL bDNSproxy; BOOL bWINSsupport; BOOL bWINSproxy; @@ -616,6 +622,16 @@ static struct parm_struct parm_table[] = {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_GLOBAL}, {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, 0}, + {"Ldap Options", P_SEP, P_SEPARATOR}, + {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, 0}, + {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, 0}, + {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, 0}, + {"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}, + + + {"Miscellaneous Options", P_SEP, P_SEPARATOR}, {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL, NULL, 0}, {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, @@ -760,6 +776,11 @@ static void init_globals(void) Globals.bUnixPasswdSync = False; Globals.bPasswdChatDebug = False; + /* default values for ldap */ + string_set(&Globals.szLdapServer, "localhost"); + Globals.ldap_port=389; + + /* these parameters are set to defaults that are more appropriate for the increasing samba install base: @@ -962,6 +983,12 @@ FN_GLOBAL_STRING(lp_domain_guest_users,&Globals.szDomainGuestUsers) FN_GLOBAL_STRING(lp_domain_hostsallow,&Globals.szDomainHostsallow) FN_GLOBAL_STRING(lp_domain_hostsdeny,&Globals.szDomainHostsdeny) +FN_GLOBAL_STRING(lp_ldap_server,&Globals.szLdapServer); +FN_GLOBAL_STRING(lp_ldap_suffix,&Globals.szLdapSuffix); +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_BOOL(lp_dns_proxy,&Globals.bDNSproxy) FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) FN_GLOBAL_BOOL(lp_we_are_a_wins_server,&Globals.bWINSsupport) @@ -1017,6 +1044,8 @@ FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as) FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce) FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval) +FN_GLOBAL_INTEGER(lp_ldap_port,&Globals.ldap_port) + FN_LOCAL_STRING(lp_preexec,szPreExec) FN_LOCAL_STRING(lp_postexec,szPostExec) FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec) diff --git a/source3/passdb/ldap.c b/source3/passdb/ldap.c new file mode 100644 index 0000000000..fedc31cbfc --- /dev/null +++ b/source3/passdb/ldap.c @@ -0,0 +1,563 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + LDAP protocol helper functions for SAMBA + Copyright (C) Jean François Micouleau 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. + +*/ + +#ifdef USE_LDAP + +#include "includes.h" +#include "lber.h" +#include "ldap.h" + +extern int DEBUGLEVEL; + +/******************************************************************* + open a connection to the ldap serve. +******************************************************************/ +BOOL ldap_open_connection(LDAP **ldap_struct) +{ + if ( (*ldap_struct = ldap_open(lp_ldap_server(),lp_ldap_port()) )== NULL) + { + DEBUG(0,("%s: The LDAP server is not responding !\n",timestring())); + return(False); + } + DEBUG(2,("ldap_open_connection: connection opened\n")); + return (True); +} + + +/******************************************************************* + connect anonymously to the ldap server. + FIXME: later (jfm) +******************************************************************/ +static BOOL ldap_connect_anonymous(LDAP *ldap_struct) +{ + if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) != LDAP_SUCCESS) + { + DEBUG(0,("%s: Couldn't bind to the LDAP server !\n", timestring() )); + return(False); + } + return (True); +} + + +/******************************************************************* + connect to the ldap server under system privileg. +******************************************************************/ +BOOL ldap_connect_system(LDAP *ldap_struct) +{ + if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) != LDAP_SUCCESS) + { + DEBUG(0,("%s: Couldn't bind to the LDAP server !\n", timestring() )); + return(False); + } + DEBUG(2,("ldap_connect_system: succesfull 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) +{ + if ( ldap_simple_bind_s(ldap_struct,lp_ldap_root(),lp_ldap_rootpasswd()) != LDAP_SUCCESS) + { + DEBUG(0,("%s: Couldn't bind to the LDAP server !\n", timestring() )); + return(False); + } + DEBUG(2,("ldap_connect_user: succesfull 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) +{ + int scope = LDAP_SCOPE_ONELEVEL; + int rc; + + 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); + + if (rc != LDAP_SUCCESS ) + { + DEBUG(0,("%s: Problem during the LDAP search\n",timestring())); + return(False); + } + return (True); +} + +/******************************************************************* + run the search by name. +******************************************************************/ +BOOL 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 :-) + */ + strcpy(filter,lp_ldap_filter()); + string_sub(filter,"%u",user); + + if ( !ldap_search_one_user(ldap_struct, filter, result) ) + { + return(False); + } + return (True); +} + +/******************************************************************* + run the search by uid. +******************************************************************/ +BOOL ldap_search_one_user_by_uid(LDAP *ldap_struct, int uid, LDAPMessage **result) +{ + pstring filter; + /* + in the filter expression, replace %u with the real name + so in ldap filter, %u MUST exist :-) + */ + snprintf(filter, sizeof(pstring), "uidAccount=%d", uid); + + if ( !ldap_search_one_user(ldap_struct, filter, result) ) + { + return(False); + } + return (True); +} + +/******************************************************************* + search an attribute and return the first value found. +******************************************************************/ +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) + { + strcpy(value, valeurs[0]); + ldap_value_free(valeurs); + DEBUG(3,("get_single_attribute: [%s]=[%s]\n", attribute, value)); + } + else + { + value=NULL; + } +} + +/******************************************************************* + find a user or a machine return a smbpass struct. +******************************************************************/ +struct passwd *Get_ldap_Pwnam(char *user) +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + char **valeur; + BOOL machine=False; + BOOL sambaAccount=False; + int i; + + static struct passwd ldap_passwd; + static char pw_name[256]; + static char pw_passwd[256]; + static char pw_gecos[256]; + static char pw_dir[256]; + static char pw_shell[256]; + ldap_passwd.pw_name=pw_name; + ldap_passwd.pw_passwd=pw_passwd; + ldap_passwd.pw_gecos=pw_gecos; + ldap_passwd.pw_dir=pw_dir; + ldap_passwd.pw_shell=pw_shell; + + DEBUG(0,("XXXX XXXX XXXX, ca merde serieux!\n")); + + /* first clear the struct */ + bzero(pw_name,sizeof(pw_name)); + bzero(pw_passwd,sizeof(pw_passwd)); + bzero(pw_gecos,sizeof(pw_gecos)); + bzero(pw_dir,sizeof(pw_dir)); + bzero(pw_shell,sizeof(pw_shell)); + ldap_passwd.pw_uid=-1; + ldap_passwd.pw_gid=-1; + + + ldap_open_connection(&ldap_struct); + + /* + to get all the attributes (specially the userPassword ) + we have to connect under the system administrator account + */ + ldap_connect_system(ldap_struct); + + ldap_search_one_user(ldap_struct, user, &result); + + if (ldap_count_entries(ldap_struct, result) != 1) + { + DEBUG(0,("%s: Strange %d user in the base!\n", + timestring(), ldap_count_entries(ldap_struct, result) )); + return(False); + } + /* take the first and unique entry */ + entry=ldap_first_entry(ldap_struct, result); + + /* check what kind of account it is */ + /* as jeremy doesn't want to split getpwnam in 2 functions :-( */ + + if (user[strlen(user)-1]=='$') + { + machine=True; + } + + if (!machine) + { + valeur=ldap_get_values(ldap_struct,entry, "objectclass"); + + /* check if the entry is a person objectclass*/ + if (valeur!=NULL) + for (i=0;valeur[i]!=NULL;i++) + { + if (!strcmp(valeur[i],"sambaAccount")) sambaAccount=True; + } + ldap_value_free(valeur); + + if (sambaAccount) + { + /* we should have enough info to fill the struct */ + strncpy(ldap_passwd.pw_name,user,strlen(user)); + + valeur=ldap_get_values(ldap_struct,entry, "uidAccount"); + if (valeur != NULL) + { + ldap_passwd.pw_uid=atoi(valeur[0]); + } + ldap_value_free(valeur); + + valeur=ldap_get_values(ldap_struct,entry, "gidAccount"); + if (valeur != NULL) + { + ldap_passwd.pw_gid=atoi(valeur[0]); + } + ldap_value_free(valeur); + + valeur=ldap_get_values(ldap_struct,entry, "userPassword"); + if (valeur != NULL) + { + /* + as we have the clear-text password, we have to crypt it ! + hum hum hum currently pass the clear text password to wait + */ + strncpy(ldap_passwd.pw_passwd,valeur[0],strlen(valeur[0])); + } + ldap_value_free(valeur); + + valeur=ldap_get_values(ldap_struct,entry, "gecos"); + if (valeur != NULL) + { + strncpy(ldap_passwd.pw_gecos,valeur[0],strlen(valeur[0])); + } + ldap_value_free(valeur); + + valeur=ldap_get_values(ldap_struct,entry, "homeDirectory"); + if (valeur != NULL) + { + strncpy(ldap_passwd.pw_dir,valeur[0],strlen(valeur[0])); + } + ldap_value_free(valeur); + + valeur=ldap_get_values(ldap_struct,entry, "loginShell"); + if (valeur != NULL) + { + strncpy(ldap_passwd.pw_shell,valeur[0],strlen(valeur[0])); + } + ldap_value_free(valeur); + } + } + else + { + } + + ldap_unbind(ldap_struct); +} + +/******************************************************************* + check if the returned entry is a sambaAccount objectclass. +******************************************************************/ +BOOL ldap_check_user(LDAP *ldap_struct, LDAPMessage *entry) +{ + BOOL sambaAccount=False; + char **valeur; + int i; + + DEBUG(2,("ldap_check_user: ")); + valeur=ldap_get_values(ldap_struct, entry, "objectclass"); + if (valeur!=NULL) + { + for (i=0;valeur[i]!=NULL;i++) + { + if (!strcmp(valeur[i],"sambaAccount")) sambaAccount=True; + } + } + DEBUG(2,("%s\n",sambaAccount?"yes":"no")); + ldap_value_free(valeur); + return (sambaAccount); +} + +/******************************************************************* + check if the returned entry is a sambaMachine objectclass. +******************************************************************/ +BOOL ldap_check_machine(LDAP *ldap_struct, LDAPMessage *entry) +{ + BOOL sambaMachine=False; + char **valeur; + int i; + + DEBUG(2,("ldap_check_machine: ")); + valeur=ldap_get_values(ldap_struct, entry, "objectclass"); + if (valeur!=NULL) + { + for (i=0;valeur[i]!=NULL;i++) + { + if (!strcmp(valeur[i],"sambaMachine")) sambaMachine=True; + } + } + DEBUG(2,("%s\n",sambaMachine?"yes":"no")); + ldap_value_free(valeur); + return (sambaMachine); +} + +/******************************************************************* + retrieve the user's info and contruct a smb_passwd structure. +******************************************************************/ +static void ldap_get_user(LDAP *ldap_struct,LDAPMessage *entry, + struct smb_passwd *ldap_passwd) +{ + static pstring user_name; + static unsigned char smbpwd[16]; + static unsigned char smbntpwd[16]; + char **valeur; + + get_single_attribute(ldap_struct, entry, "cn", user_name); + + DEBUG(2,("ldap_get_user: user: %s\n",user_name)); + + if ( (valeur=ldap_get_values(ldap_struct, entry, "uidAccount")) != NULL) + { + ldap_passwd->smb_userid=atoi(valeur[0]); + ldap_value_free(valeur); + } + + if ( (valeur=ldap_get_values(ldap_struct, entry, "userPassword")) != NULL) + { + memset(smbntpwd, '\0', 16); + E_md4hash((uchar *) valeur[0], smbntpwd); + valeur[0][14] = '\0'; + strupper(valeur[0]); + memset(smbpwd, '\0', 16); + E_P16((uchar *) valeur[0], smbpwd); + ldap_value_free(valeur); + } + + if ( (valeur=ldap_get_values(ldap_struct,entry, "userAccountControl") ) != NULL) + { + ldap_passwd->acct_ctrl=atoi(valeur[0]); + if (ldap_passwd->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) ) + { + DEBUG(0,("Inconsistency in the LDAP database\n")); + + } + if (ldap_passwd->acct_ctrl & ACB_NORMAL) + { + ldap_passwd->smb_name=user_name; + ldap_passwd->smb_passwd=smbpwd; + ldap_passwd->smb_nt_passwd=smbntpwd; + } + ldap_value_free(valeur); + } + + if ( (valeur=ldap_get_values(ldap_struct,entry, "pwdLastSet")) != NULL) + { + ldap_passwd->last_change_time=(time_t)strtol(valeur[0], NULL, 16); + ldap_value_free(valeur); + } +} + +/************************************************************* + Routine to get the next 32 hex characters and turn them + into a 16 byte array. +**************************************************************/ + +static int gethexpwd(char *p, char *pwd) +{ + int i; + unsigned char lonybble, hinybble; + char *hexchars = "0123456789ABCDEF"; + char *p1, *p2; + + for (i = 0; i < 32; i += 2) { + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); + + p1 = strchr(hexchars, hinybble); + p2 = strchr(hexchars, lonybble); + if (!p1 || !p2) + return (False); + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + pwd[i / 2] = (hinybble << 4) | lonybble; + } + return (True); +} + +/******************************************************************* + retrieve the machine's info and contruct a smb_passwd structure. +******************************************************************/ +static void ldap_get_machine(LDAP *ldap_struct,LDAPMessage *entry, + struct smb_passwd *ldap_passwd) +{ + static pstring user_name; + static unsigned char smbntpwd[16]; + char **valeur; + + /* by default it's a station */ + ldap_passwd->acct_ctrl = ACB_WSTRUST; + + get_single_attribute(ldap_struct, entry, "cn", user_name); + DEBUG(2,("ldap_get_machine: machine: %s\n", user_name)); + + if ( (valeur=ldap_get_values(ldap_struct, entry, "uidAccount")) != NULL) + { + ldap_passwd->smb_userid=atoi(valeur[0]); + ldap_value_free(valeur); + } + + if ( (valeur=ldap_get_values(ldap_struct, entry, "machinePassword")) != NULL) + { + gethexpwd(valeur[0],smbntpwd); + ldap_value_free(valeur); + } + + if ( (valeur=ldap_get_values(ldap_struct,entry, "machineRole") ) != NULL) + { + if ( !strcmp(valeur[0],"workstation") ) + ldap_passwd->acct_ctrl=ACB_WSTRUST; + else + if ( !strcmp(valeur[0],"server") ) + ldap_passwd->acct_ctrl=ACB_SVRTRUST; + ldap_value_free(valeur); + } + + ldap_passwd->smb_name=user_name; + ldap_passwd->smb_passwd=smbntpwd; + ldap_passwd->smb_nt_passwd=smbntpwd; +} + +/******************************************************************* + find a user or a machine return a smbpass struct. +******************************************************************/ +struct smb_passwd *ldap_get_smbpwd_entry(char *name, int smb_userid) +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + BOOL machine=False; + + static struct smb_passwd ldap_passwd; + + ldap_passwd.smb_name = NULL; + ldap_passwd.smb_passwd = NULL; + ldap_passwd.smb_nt_passwd = NULL; + + ldap_passwd.smb_userid = -1; + ldap_passwd.acct_ctrl = ACB_DISABLED; + ldap_passwd.last_change_time = 0; + + ldap_struct=NULL; + + if (name != NULL) + { + DEBUG(10, ("ldap_get_smbpwd_entry: search by name: %s\n", name)); + } + else + { + DEBUG(10, ("ldap_get_smbpwd_entry: search by smb_userid: %x\n", smb_userid)); + } + + if (!ldap_open_connection(&ldap_struct)) + return (NULL); + if (!ldap_connect_system(ldap_struct)) + return (NULL); + + if (name != NULL) + { + if (!ldap_search_one_user_by_name(ldap_struct, name, &result)) + return (NULL); + } + else + { + if (!ldap_search_one_user_by_uid(ldap_struct, smb_userid, &result)) + return (NULL); + } + + if (ldap_count_entries(ldap_struct, result) == 0) + { + DEBUG(2,("%s: Non existant user!\n", timestring() )); + return (NULL); + } + + if (ldap_count_entries(ldap_struct, result) > 1) + { + DEBUG(2,("%s: Strange %d users in the base!\n", + timestring(), ldap_count_entries(ldap_struct, result) )); + } + /* take the first and unique entry */ + entry=ldap_first_entry(ldap_struct, result); + + if (name != NULL) + { + DEBUG(0,("ldap_get_smbpwd_entry: Found user: %s\n",name)); + + if (name[strlen(name)-1]=='$') + machine=True; + else + machine=False; + } + + if (machine==False) + { + if (ldap_check_user(ldap_struct, entry)==True) + ldap_get_user(ldap_struct, entry, &ldap_passwd); + } + else + { + if (ldap_check_machine(ldap_struct, entry)==True) + ldap_get_machine(ldap_struct, entry, &ldap_passwd); + } + + ldap_msgfree(result); + result=NULL; + ldap_unbind(ldap_struct); + + return(&ldap_passwd); +} +#endif diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index 72e3c3035e..cb3a4a9a99 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -554,7 +554,11 @@ static struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid) struct smb_passwd *getsmbpwnam(char *name) { +#ifdef USE_LDAP + return ldap_get_smbpwd_entry(name, 0); +#else return get_smbpwd_entry(name, 0); +#endif /* USE_LDAP */ } /************************************************************************ @@ -563,7 +567,11 @@ struct smb_passwd *getsmbpwnam(char *name) struct smb_passwd *getsmbpwuid(unsigned int uid) { +#ifdef USE_LDAP + return ldap_get_smbpwd_entry(NULL, uid); +#else return get_smbpwd_entry(NULL, uid); +#endif /* USE_LDAP */ } /********************************************************** @@ -673,6 +681,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); sprintf((char *)&p[i*2], "%02X", newpwd->smb_passwd[i]); } } else { + i=0; if(newpwd->acct_ctrl & ACB_PWNOTREQ) sprintf(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); else diff --git a/source3/rpc_server/srv_ldap_helpers.c b/source3/rpc_server/srv_ldap_helpers.c new file mode 100644 index 0000000000..d1c091c6c9 --- /dev/null +++ b/source3/rpc_server/srv_ldap_helpers.c @@ -0,0 +1,162 @@ +#ifdef USE_LDAP + +#include "includes.h" +#include "lber.h" +#include "ldap.h" + +extern int DEBUGLEVEL; + +/******************************************************************* + find a user or a machine return a smbpass struct. +******************************************************************/ +static void make_ldap_sam_user_info_21(LDAP *ldap_struct, LDAPMessage *entry, SAM_USER_INFO_21 *user) +{ + pstring cn; + pstring fullname; + pstring home_dir; + pstring dir_drive; + pstring logon_script; + pstring profile_path; + pstring acct_desc; + pstring workstations; + pstring temp; + + if (ldap_check_user(ldap_struct, entry)==True) + { + get_single_attribute(ldap_struct, entry, "cn", cn); + get_single_attribute(ldap_struct, entry, "userFullName", fullname); + get_single_attribute(ldap_struct, entry, "homeDirectory", home_dir); + 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, "comment", acct_desc); + get_single_attribute(ldap_struct, entry, "userWorkstations", workstations); + + get_single_attribute(ldap_struct, entry, "rid", temp); + user->user_rid=atoi(temp); + get_single_attribute(ldap_struct, entry, "primaryGroupID", temp); + user->group_rid=atoi(temp); + get_single_attribute(ldap_struct, entry, "controlAccessRights", temp); + user->acb_info=atoi(temp); + + make_unistr2(&(user->uni_user_name), cn, strlen(cn)); + make_uni_hdr(&(user->hdr_user_name), strlen(cn), strlen(cn), 1); + make_unistr2(&(user->uni_full_name), fullname, strlen(fullname)); + make_uni_hdr(&(user->hdr_full_name), strlen(fullname), strlen(fullname), 1); + make_unistr2(&(user->uni_home_dir), home_dir, strlen(home_dir)); + make_uni_hdr(&(user->hdr_home_dir), strlen(home_dir), strlen(home_dir), 1); + make_unistr2(&(user->uni_dir_drive), dir_drive, strlen(dir_drive)); + make_uni_hdr(&(user->hdr_dir_drive), strlen(dir_drive), strlen(dir_drive), 1); + make_unistr2(&(user->uni_logon_script), logon_script, strlen(logon_script)); + make_uni_hdr(&(user->hdr_logon_script), strlen(logon_script), strlen(logon_script), 1); + make_unistr2(&(user->uni_profile_path), profile_path, strlen(profile_path)); + make_uni_hdr(&(user->hdr_profile_path), strlen(profile_path), strlen(profile_path), 1); + make_unistr2(&(user->uni_acct_desc), acct_desc, strlen(acct_desc)); + make_uni_hdr(&(user->hdr_acct_desc), strlen(acct_desc), strlen(acct_desc), 1); + make_unistr2(&(user->uni_workstations), workstations, strlen(workstations)); + make_uni_hdr(&(user->hdr_workstations), strlen(workstations), strlen(workstations), 1); + } +} + +/******************************************************************* + find a user or a machine return a smbpass struct. +******************************************************************/ +BOOL get_ldap_entries(SAM_USER_INFO_21 *pw_buf, + int *total_entries, int *num_entries, + int max_num_entries, + uint16 acb_mask, int switch_level) +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + + int scope = LDAP_SCOPE_ONELEVEL; + int rc; + + char filter[256]; + + (*num_entries) = 0; + (*total_entries) = 0; + + if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + return (False); + + if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + return (False); + + + /* when the class is known the search is much faster */ + switch (switch_level) + { + case 1: strcpy(filter, "objectclass=sambaAccount"); + break; + case 2: strcpy(filter, "objectclass=sambaMachine"); + break; + default: strcpy(filter, "(|(objectclass=sambaMachine)(objectclass=sambaAccount))"); + break; + } + + rc=ldap_search_s(ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &result); + + DEBUG(2,("%d entries in the base!\n", ldap_count_entries(ldap_struct, result) )); + + for ( entry = ldap_first_entry(ldap_struct, result); + (entry != NULL) && (*num_entries) < max_num_entries; + entry = ldap_next_entry(ldap_struct, entry) ) + { + make_ldap_sam_user_info_21(ldap_struct, entry, &(pw_buf[(*num_entries)]) ); + + if (acb_mask == 0 || IS_BITS_SET_SOME(pw_buf[(*num_entries)].acb_info, acb_mask)) + { + DEBUG(5,(" acb_mask %x accepts\n", acb_mask)); + (*num_entries)++; + } + else + { + DEBUG(5,(" acb_mask %x rejects\n", acb_mask)); + } + + (*total_entries)++; + } + + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return (*num_entries) > 0; +} + +BOOL ldap_get_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid) +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + + if (!ldap_open_connection(&ldap_struct)) + return (False); + if (!ldap_connect_system(ldap_struct)) + return (False); + + if (!ldap_search_one_user_by_uid(ldap_struct, rid, &result)) + return (False); + + if (ldap_count_entries(ldap_struct, result) == 0) + { + DEBUG(2,("%s: Non existant user!\n", timestring() )); + return (False); + } + + if (ldap_count_entries(ldap_struct, result) > 1) + { + DEBUG(2,("%s: Strange %d users in the base!\n", + timestring(), ldap_count_entries(ldap_struct, result) )); + } + /* take the first and unique entry */ + entry=ldap_first_entry(ldap_struct, result); + + make_ldap_sam_user_info_21(ldap_struct, entry, id21); + + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return(True); +} + +#endif diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c index 162d9c45d0..aa240ad3c6 100644 --- a/source3/rpc_server/srv_samr.c +++ b/source3/rpc_server/srv_samr.c @@ -45,55 +45,55 @@ static BOOL get_smbpwd_entries(SAM_USER_INFO_21 *pw_buf, { void *vp = NULL; struct smb_passwd *pwd = NULL; - - (*num_entries) = 0; - (*total_entries) = 0; - - if (pw_buf == NULL) return False; - - vp = startsmbpwent(False); - if (!vp) - { - DEBUG(0, ("get_smbpwd_entries: Unable to open SMB password file.\n")); - return False; - } - - while (((pwd = getsmbpwent(vp)) != NULL) && (*num_entries) < max_num_entries) - { - int user_name_len = strlen(pwd->smb_name); - make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len); - make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len, - user_name_len, 1); - pw_buf[(*num_entries)].user_rid = pwd->smb_userid; - bzero( pw_buf[(*num_entries)].nt_pwd , 16); - - /* Now check if the NT compatible password is available. */ - if (pwd->smb_nt_passwd != NULL) - { - memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16); - } - - pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl; - - DEBUG(5, ("get_smbpwd_entries: idx: %d user %s, uid %d, acb %x", - (*num_entries), pwd->smb_name, pwd->smb_userid, pwd->acct_ctrl)); - - if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask)) - { - DEBUG(5,(" acb_mask %x accepts\n", acb_mask)); - (*num_entries)++; - } - else - { - DEBUG(5,(" acb_mask %x rejects\n", acb_mask)); - } - - (*total_entries)++; - } - - endsmbpwent(vp); - - return (*num_entries) > 0; + + (*num_entries) = 0; + (*total_entries) = 0; + + if (pw_buf == NULL) return False; + + vp = startsmbpwent(False); + if (!vp) + { + DEBUG(0, ("get_smbpwd_entries: Unable to open SMB password file.\n")); + return False; + } + + while (((pwd = getsmbpwent(vp)) != NULL) && (*num_entries) < max_num_entries) + { + int user_name_len = strlen(pwd->smb_name); + make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len-1); + make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len-1, + user_name_len-1, 1); + pw_buf[(*num_entries)].user_rid = pwd->smb_userid; + bzero( pw_buf[(*num_entries)].nt_pwd , 16); + + /* Now check if the NT compatible password is available. */ + if (pwd->smb_nt_passwd != NULL) + { + memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16); + } + + pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl; + + DEBUG(5, ("get_smbpwd_entries: idx: %d user %s, uid %d, acb %x", + (*num_entries), pwd->smb_name, pwd->smb_userid, pwd->acct_ctrl)); + + if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask)) + { + DEBUG(5,(" acb_mask %x accepts\n", acb_mask)); + (*num_entries)++; + } + else + { + DEBUG(5,(" acb_mask %x rejects\n", acb_mask)); + } + + (*total_entries)++; + } + + endsmbpwent(vp); + + return (*num_entries) > 0; } /******************************************************************* @@ -463,33 +463,52 @@ static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u, DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__)); +#ifndef USE_LDAP become_root(True); got_pwds = get_smbpwd_entries(pass, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0); unbecome_root(True); +#endif switch (q_u->switch_level) { case 0x1: { + /* query disp info is for users */ + switch_level = 0x1; +#ifdef USE_LDAP + got_pwds = get_ldap_entries(pass, + &total_entries, + &num_entries, + MAX_SAM_ENTRIES, + 0, + switch_level); +#endif make_sam_info_1(&info1, ACB_NORMAL, q_u->start_idx, num_entries, pass); ctr.sam.info1 = &info1; - switch_level = 0x1; break; } case 0x2: { /* query disp info is for servers */ + switch_level = 0x2; +#ifdef USE_LDAP + got_pwds = get_ldap_entries(pass, + &total_entries, + &num_entries, + MAX_SAM_ENTRIES, + 0, + switch_level); +#endif make_sam_info_2(&info2, ACB_WSTRUST, q_u->start_idx, num_entries, pass); ctr.sam.info2 = &info2; - switch_level = 0x2; break; } @@ -1025,8 +1044,11 @@ static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, case 21: { info = (void*)&id21; +#ifdef USE_LDAP + status = ldap_get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER; +#else status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER; - +#endif break; } -- cgit