diff options
author | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
commit | 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 (patch) | |
tree | 866dd15416c3d8554bb207709f433a87ad0c012d /source3/passdb/ldap.c | |
parent | f6276724bafdb6145c0c7b565172d80cb04516ea (diff) | |
download | samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.gz samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.xz samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.zip |
first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
(This used to be commit 453a822a76780063dff23526c35408866d0c0154)
Diffstat (limited to 'source3/passdb/ldap.c')
-rw-r--r-- | source3/passdb/ldap.c | 1160 |
1 files changed, 814 insertions, 346 deletions
diff --git a/source3/passdb/ldap.c b/source3/passdb/ldap.c index 7bdbdab320e..43fea00a644 100644 --- a/source3/passdb/ldap.c +++ b/source3/passdb/ldap.c @@ -1,9 +1,8 @@ /* Unix SMB/Netbios implementation. - Version 2.0. + Version 1.9. LDAP protocol helper functions for SAMBA Copyright (C) Jean François Micouleau 1998 - Copyright (C) Matthew Chapman 1998 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,536 +20,1005 @@ */ -#include "includes.h" - #ifdef WITH_LDAP +#include "includes.h" + #include <lber.h> #include <ldap.h> +#define ADD_USER 1 +#define MODIFY_USER 2 + extern int DEBUGLEVEL; -/* Internal state */ -LDAP *ldap_struct; -LDAPMessage *ldap_results; -LDAPMessage *ldap_entry; +/******************************************************************* + open a connection to the ldap serve. +******************************************************************/ +static BOOL ldap_open_connection(LDAP **ldap_struct) +{ + 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 password */ -static pstring ldap_secret; +/******************************************************************* + 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, ( "Couldn't bind to the LDAP server !\n" ) ); + return(False); + } + return (True); +} /******************************************************************* - Open connections to the LDAP server. - ******************************************************************/ + connect to the ldap server under system privileg. +******************************************************************/ +static BOOL ldap_connect_system(LDAP *ldap_struct) +{ + if ( 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(2,("ldap_connect_system: succesful connection to the LDAP server\n")); + return (True); +} -BOOL ldap_connect(void) +/******************************************************************* + connect to the ldap server under a particular user. +******************************************************************/ +static BOOL ldap_connect_user(LDAP *ldap_struct, char *user, char *password) { - int err; + if ( 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(2,("ldap_connect_user: succesful connection to the LDAP server\n")); + return (True); +} - if (!(ldap_struct = ldap_open(lp_ldap_server(), lp_ldap_port()))) { - DEBUG(0, ("open: %s\n", strerror(errno))); - return (False); +/******************************************************************* + 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, ( "Problem during the LDAP search\n" ) ); + return(False); } + return (True); +} - err = ldap_simple_bind_s(ldap_struct, lp_ldap_bind_as(), ldap_secret); - if (err != LDAP_SUCCESS) { - DEBUG(0, ("bind: %s\n", ldap_err2string(err))); - return (False); +/******************************************************************* + run the search by name. +******************************************************************/ +static 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 :-) + */ + pstrcpy(filter,lp_ldap_filter()); + pstring_sub(filter,"%u",user); + + if ( !ldap_search_one_user(ldap_struct, filter, result) ) + { + return(False); } + return (True); +} - DEBUG(2,("Connected to LDAP server\n")); +/******************************************************************* + run the search by uid. +******************************************************************/ +static BOOL ldap_search_one_user_by_uid(LDAP *ldap_struct, int uid, LDAPMessage **result) +{ + pstring filter; + + slprintf(filter, sizeof(pstring)-1, "uidAccount = %d", uid); + + if ( !ldap_search_one_user(ldap_struct, filter, result) ) + { + return(False); + } return (True); } /******************************************************************* - close connections to the LDAP server. - ******************************************************************/ + search an attribute and return the first value found. +******************************************************************/ +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) + { + pstrcpy(value, valeurs[0]); + ldap_value_free(valeurs); + DEBUG(3,("get_single_attribute: [%s] = [%s]\n", attribute, value)); + } + else + { + value = NULL; + } +} -void ldap_disconnect(void) +/******************************************************************* + check if the returned entry is a sambaAccount objectclass. +******************************************************************/ +static BOOL ldap_check_user(LDAP *ldap_struct, LDAPMessage *entry) { - if(!ldap_struct) - return; + BOOL sambaAccount = False; + char **valeur; + int i; - if(ldap_results) { - ldap_msgfree(ldap_results); - ldap_results = NULL; } + 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); +} - ldap_unbind(ldap_struct); - ldap_struct = NULL; +/******************************************************************* + 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,("Connection closed\n")); + DEBUG(2,("ldap_check_trust: ")); + valeur = ldap_get_values(ldap_struct, entry, "objectclass"); + if (valeur! = NULL) + { + for (i = 0;valeur[i]! = NULL;i++) + { + if (!strcmp(valeur[i],"sambaTrust")) sambaTrust = True; + } + } + DEBUG(2,("%s\n",sambaTrust?"yes":"no")); + ldap_value_free(valeur); + return (sambaTrust); } - /******************************************************************* - Search the directory using a given filter. - ******************************************************************/ + 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]; -BOOL ldap_search_for(char *filter) -{ - int err; + pdb_init_smb(user); - DEBUG(2,("Searching in [%s] for [%s]\n", lp_ldap_suffix(), filter)); + memset((char *)smblmpwd, '\0', sizeof(smblmpwd)); + memset((char *)smbntpwd, '\0', sizeof(smbntpwd)); - err = ldap_search_s(ldap_struct, lp_ldap_suffix(), LDAP_SCOPE_ONELEVEL, - filter, NULL, 0, &ldap_results); + 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 */ - if(err != LDAP_SUCCESS) { - DEBUG(0, ("search: %s\n", ldap_err2string(err))); - } + 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); - DEBUG(2, ("%d matching entries found\n", - ldap_count_entries(ldap_struct, ldap_results))); + get_single_attribute(ldap_struct, entry, "pwdLastSet", temp); + user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); - ldap_entry = ldap_first_entry(ldap_struct, ldap_results); - return (True); -} + get_single_attribute(ldap_struct, entry, "rid", temp); -BOOL ldap_search_by_name(const char *user) -{ - fstring filter; + /* the smb (unix) ids are not stored: they are created */ + user->smb_userid = pdb_user_rid_to_uid (atoi(temp)); - slprintf(filter, sizeof(filter)-1, - "(&(uid=%s)(objectclass=sambaAccount))", user); - return ldap_search_for(filter); + if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) ) + { + DEBUG(0,("Inconsistency in the LDAP database\n")); + } + if (user->acct_ctrl & ACB_NORMAL) + { + user->smb_name = user_name; + user->smb_passwd = smblmpwd; + user->smb_nt_passwd = smbntpwd; + } } -BOOL ldap_search_by_uid(int uid) -{ - fstring filter; +/******************************************************************* + retrieve the user's info and contruct a sam_passwd structure. + + calls ldap_get_smb_passwd function first, though, to save code duplication. + +******************************************************************/ +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; + static pstring dir_drive; + static pstring logon_script; + static pstring profile_path; + static pstring acct_desc; + static pstring workstations; + static pstring temp; + static struct smb_passwd pw_buf; + + pdb_init_sam(user); + + ldap_get_smb_passwd(ldap_struct, entry, &pw_buf); - slprintf(filter, sizeof(filter)-1, - "(&(uidNumber=%d)(objectclass=sambaAccount))", uid); - return ldap_search_for(filter); -} + user->pass_last_set_time = pw_buf.pass_last_set_time; + get_single_attribute(ldap_struct, entry, "logonTime", temp); + user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); -/******************************************************************* - Get the first value of an attribute. - ******************************************************************/ + get_single_attribute(ldap_struct, entry, "logoffTime", temp); + user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); -BOOL ldap_get_attribute(char *attribute, char *value) -{ - char **values; - - if(!(values = ldap_get_values(ldap_struct, ldap_entry, attribute))) - return (False); + get_single_attribute(ldap_struct, entry, "kickoffTime", temp); + user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); - pstrcpy(value, values[0]); - ldap_value_free(values); - DEBUG(3, ("get: [%s] = [%s]\n", attribute, value)); - - return (True); -} + 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, "pwdCanChange", temp); + user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); -/******************************************************************* - Construct an smb_passwd structure - ******************************************************************/ -struct smb_passwd *ldap_getpw(void) -{ - static struct smb_passwd smbpw; - static pstring unix_name; - static pstring nt_name; - static unsigned char smblmpwd[16]; - static unsigned char smbntpwd[16]; - pstring temp; + get_single_attribute(ldap_struct, entry, "pwdMustChange", temp); + user->pass_last_set_time = (time_t)strtol(temp, NULL, 16); - if(!ldap_entry) - return NULL; + user->smb_name = pw_buf.smb_name; - if(!ldap_get_attribute("uid", unix_name)) { - DEBUG(0,("Missing uid\n")); - return NULL; } - smbpw.unix_name = unix_name; + DEBUG(2,("ldap_get_sam_passwd: user: %s\n", user_name)); + + get_single_attribute(ldap_struct, entry, "userFullName", fullname); + user->full_name = fullname; - DEBUG(2,("Retrieving account [%s]\n",unix_name)); + get_single_attribute(ldap_struct, entry, "homeDirectory", home_dir); + user->home_dir = home_dir; - if(!ldap_get_attribute("uidNumber", temp)) { - DEBUG(0,("Missing uidNumber\n")); - return NULL; } - smbpw.unix_uid = atoi(temp); + get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive); + user->dir_drive = dir_drive; - if(!ldap_get_attribute("ntuid", nt_name)) { - DEBUG(0,("Missing ntuid\n")); - return NULL; } - smbpw.nt_name = nt_name; + get_single_attribute(ldap_struct, entry, "scriptPath", logon_script); + user->logon_script = logon_script; - if(!ldap_get_attribute("rid", temp)) { - DEBUG(0,("Missing rid\n")); - return NULL; } - smbpw.user_rid = strtol(temp, NULL, 16); + get_single_attribute(ldap_struct, entry, "profilePath", profile_path); + user->profile_path = profile_path; - if(ldap_get_attribute("acctFlags", temp)) - smbpw.acct_ctrl = pwdb_decode_acct_ctrl(temp); - else - smbpw.acct_ctrl = ACB_NORMAL; + get_single_attribute(ldap_struct, entry, "comment", acct_desc); + user->acct_desc = acct_desc; - if(ldap_get_attribute("lmPassword", temp)) { - pwdb_gethexpwd(temp, smblmpwd, NULL); - smbpw.smb_passwd = smblmpwd; - } else { - smbpw.smb_passwd = NULL; - smbpw.acct_ctrl |= ACB_DISABLED; - } + get_single_attribute(ldap_struct, entry, "userWorkstations", workstations); + user->workstations = workstations; - if(ldap_get_attribute("ntPassword", temp)) { - pwdb_gethexpwd(temp, smbntpwd, NULL); - smbpw.smb_nt_passwd = smbntpwd; - } else { - smbpw.smb_nt_passwd = NULL; - } + user->unknown_str = NULL; /* don't know, yet! */ + user->munged_dial = NULL; /* "munged" dial-back telephone number */ - if(ldap_get_attribute("pwdLastSet", temp)) - smbpw.pass_last_set_time = (time_t)strtol(temp, NULL, 16); - else - smbpw.pass_last_set_time = (time_t)(-1); + get_single_attribute(ldap_struct, entry, "rid", temp); + user->user_rid = atoi(temp); - return &smbpw; -} + get_single_attribute(ldap_struct, entry, "primaryGroupID", temp); + user->group_rid = atoi(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); + + user->acct_ctrl = pw_buf.acct_ctrl; + 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 */ + + if (user->acct_ctrl & (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST) ) + { + DEBUG(0,("Inconsistency in the LDAP database\n")); + } + + if (!(user->acct_ctrl & ACB_NORMAL)) + { + DEBUG(0,("User's acct_ctrl bits not set to ACT_NORMAL in LDAP database\n")); + return; + } +} /************************************************************************ - Adds a modification to a LDAPMod queue. - ************************************************************************/ + Routine to manage the LDAPMod structure array + manage memory used by the array, by each struct, and values - void ldap_make_mod(LDAPMod ***modlist,int modop, char *attribute, char *value) +************************************************************************/ +static void make_a_mod(LDAPMod ***modlist,int modop, char *attribute, char *value) { LDAPMod **mods; int i; int j; - - DEBUG(3, ("set: [%s] = [%s]\n", attribute, value)); mods = *modlist; - if (mods == NULL) { - mods = (LDAPMod **)malloc(sizeof(LDAPMod *)); + if (mods == NULL) + { + mods = (LDAPMod **)malloc( sizeof(LDAPMod *) ); + if (mods == NULL) + { + DEBUG(0,("make_a_mod: out of memory!\n")); + return; + } mods[0] = NULL; } - for (i = 0; mods[i] != NULL; ++i) { - if (mods[i]->mod_op == modop && - !strcasecmp(mods[i]->mod_type, attribute)) { + for ( i = 0; mods[ i ] ! = NULL; ++i ) + { + if ( mods[ i ]->mod_op == modop && + !strcasecmp( mods[ i ]->mod_type, attribute ) ) + { break; } } - if (mods[i] == NULL) { - mods = (LDAPMod **)realloc(mods, (i+2) * sizeof(LDAPMod *)); - mods[i] = (LDAPMod *)malloc(sizeof(LDAPMod)); + if (mods[i] == NULL) + { + mods = (LDAPMod **)realloc( mods, (i+2) * sizeof( LDAPMod * ) ); + if (mods == NULL) + { + DEBUG(0,("make_a_mod: out of memory!\n")); + return; + } + 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]->mod_type = strdup( attribute ); mods[i+1] = NULL; } - if (value) { + if (value ! = NULL ) + { j = 0; - if (mods[i]->mod_values) { - for (; mods[i]->mod_values[j]; j++); + 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 *)); - mods[i]->mod_values[j] = strdup(value); - mods[i]->mod_values[j+1] = NULL; + 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; } - /************************************************************************ - Queues the necessary modifications to save a smb_passwd structure - ************************************************************************/ + Add or modify an entry. Only the smb struct values - void ldap_smbpwmods(struct smb_passwd *newpwd, LDAPMod ***mods, int operation) +*************************************************************************/ +static BOOL modadd_ldappwd_entry(struct smb_passwd *newpwd, int flag) { - fstring temp; - int i; + + /* 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; - *mods = NULL; - if(operation == LDAP_MOD_ADD) { /* immutable attributes */ - ldap_make_mod(mods, LDAP_MOD_ADD, "objectclass", "sambaAccount"); + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMod **mods; + + smb_name = newpwd->smb_name; - ldap_make_mod(mods, LDAP_MOD_ADD, "uid", newpwd->unix_name); - slprintf(temp, sizeof(temp)-1, "%d", newpwd->unix_uid); - ldap_make_mod(mods, LDAP_MOD_ADD, "uidNumber", temp); + if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + { + return False; + } - ldap_make_mod(mods, LDAP_MOD_ADD, "ntuid", newpwd->nt_name); - slprintf(temp, sizeof(temp)-1, "%x", newpwd->user_rid); - ldap_make_mod(mods, LDAP_MOD_ADD, "rid", temp); + if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + { + 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_passwd) { - for( i = 0; i < 16; i++) { - slprintf(&temp[2*i], 3, "%02X", newpwd->smb_passwd[i]); - } - ldap_make_mod(mods, operation, "lmPassword", temp); + 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: + { + if (ldap_count_entries(ldap_struct, result) ! = 0) + { + DEBUG(0,("User already in the base, with samba properties\n")); + ldap_unbind(ldap_struct); + return False; + } + ldap_state = LDAP_MOD_ADD; + break; + } + case MODIFY_USER: + { + if (ldap_count_entries(ldap_struct, result) ! = 1) + { + DEBUG(0,("No user to modify !\n")); + ldap_unbind(ldap_struct); + return False; + } + ldap_state = LDAP_MOD_REPLACE; + break; + } + default: + { + DEBUG(0,("How did you come here? \n")); + ldap_unbind(ldap_struct); + return False; + break; + } } + slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() ); - if (newpwd->smb_nt_passwd) { - for( i = 0; i < 16; i++) { - slprintf(&temp[2*i], 3, "%02X", newpwd->smb_nt_passwd[i]); - } - ldap_make_mod(mods, operation, "ntPassword", temp); + if (newpwd->smb_passwd ! = NULL) + { + int i; + for( i = 0; i < 16; i++) + { + slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_passwd[i]); + } + } + else + { + if (newpwd->acct_ctrl & ACB_PWNOTREQ) + { + slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + } + else + { + slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } + } + slprintf(lmhash, sizeof(lmhash)-1, "%s", temp); - newpwd->pass_last_set_time = time(NULL); - slprintf(temp, sizeof(temp)-1, "%08X", newpwd->pass_last_set_time); - ldap_make_mod(mods, operation, "pwdLastSet", temp); + if (newpwd->smb_nt_passwd ! = NULL) + { + int i; + for( i = 0; i < 16; i++) + { + slprintf(&temp[2*i], sizeof(temp) - 1, "%02X", newpwd->smb_nt_passwd[i]); + } + + } + else + { + if (newpwd->acct_ctrl & ACB_PWNOTREQ) + { + slprintf(temp, sizeof(temp) - 1, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + } + else + { + slprintf(temp, sizeof(temp) - 1, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } + } + slprintf(nthash, sizeof(nthash)-1, "%s", temp); - ldap_make_mod(mods, operation, "acctFlags", - pwdb_encode_acct_ctrl(newpwd->acct_ctrl, - NEW_PW_FORMAT_SPACE_PADDED_LEN)); -} + 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; + 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 + { + 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); + } + + 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)); + + 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: + { + DEBUG(2,("modadd_ldappwd_entry: How did you come here? \n")); + ldap_unbind(ldap_struct); + return False; + break; + } + } + + ldap_mods_free(mods, 1); + + ldap_unbind(ldap_struct); + + return True; +} /************************************************************************ - Commit changes to a directory entry. - *************************************************************************/ - BOOL ldap_makemods(char *attribute, char *value, LDAPMod **mods, BOOL add) + 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; + int rc; + char *smb_name; + int trust = False; + int ldap_state; pstring filter; - char *dn; - int entries; - int err = 0; - BOOL rc; - - slprintf(filter, sizeof(filter)-1, "%s=%s", attribute, value); + pstring dn; + pstring lmhash; + pstring nthash; + pstring rid; + pstring lst; + pstring temp; - if (!ldap_connect()) - return (False); + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMod **mods; + + smb_name = newpwd->smb_name; - ldap_search_for(filter); + if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + { + return False; + } - if (ldap_entry) + if (!ldap_connect_system(ldap_struct)) /* connect as system account */ { - dn = ldap_get_dn(ldap_struct, ldap_entry); - err = ldap_modify_s(ldap_struct, dn, mods); - free(dn); + ldap_unbind(ldap_struct); + return False; } - else if (add) + + if (smb_name[strlen(smb_name)-1] == '$' ) { - pstrcat(filter, ", "); - pstrcat(filter, lp_ldap_suffix()); - err = ldap_add_s(ldap_struct, filter, mods); + smb_name[strlen(smb_name)-1] = '\0'; + trust = True; } - if (err == LDAP_SUCCESS) + 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) { - DEBUG(2,("Updated entry [%s]\n", value)); - rc = True; - } else { - DEBUG(0,("update: %s\n", ldap_err2string(err))); - rc = False; + 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); + return False; + } + ldap_state = LDAP_MOD_ADD; + break; + } + + case MODIFY_USER: + { + if (ldap_count_entries(ldap_struct, result) ! = 1) + { + DEBUG(2,("No user to modify !\n")); + ldap_unbind(ldap_struct); + return False; + } + ldap_state = LDAP_MOD_REPLACE; + break; + } + + default: + { + DEBUG(2,("How did you come here? \n")); + ldap_unbind(ldap_struct); + return False; + break; + } } + slprintf(dn, sizeof(dn)-1, "cn = %s, %s",smb_name, lp_ldap_suffix() ); + + mods = NULL; - ldap_disconnect(); + if (trust) + { + } + else + { + } + + 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); - return rc; + + ldap_unbind(ldap_struct); + + return True; } +/************************************************************************ + Routine to add an entry to the ldap passwd file. + + do not call this function directly. use passdb.c instead. + +*************************************************************************/ +static BOOL add_ldappwd_entry(struct smb_passwd *newpwd) +{ + return (modadd_ldappwd_entry(newpwd, ADD_USER) ); +} /************************************************************************ - Return next available RID, starting from 1000 - ************************************************************************/ + 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 -BOOL ldap_allocaterid(uint32 *rid) + do not call this function directly. use passdb.c instead. + +************************************************************************/ +static BOOL mod_ldappwd_entry(struct smb_passwd *pwd, BOOL override) { - pstring newdn; - fstring rid_str; - LDAPMod **mods; - char *dn; - int err; + return (modadd_ldappwd_entry(pwd, MODIFY_USER) ); +} - DEBUG(2, ("Allocating new RID\n")); +/************************************************************************ + Routine to add an entry to the ldap passwd file. - if (!ldap_connect()) - return (False); + do not call this function directly. use passdb.c instead. - ldap_search_for("(&(id=root)(objectClass=sambaConfig))"); +*************************************************************************/ +static BOOL add_ldap21pwd_entry(struct sam_passwd *newpwd) +{ + return( modadd_ldappwd_entry(newpwd, ADD_USER)? + modadd_ldap21pwd_entry(newpwd, ADD_USER):False); +} - if (ldap_entry && ldap_get_attribute("nextrid", rid_str)) - *rid = strtol(rid_str, NULL, 16); - else - *rid = 1000; +/************************************************************************ + 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 - mods = NULL; - if(!ldap_entry) - { - ldap_make_mod(&mods, LDAP_MOD_ADD, "objectClass", - "sambaConfig"); - ldap_make_mod(&mods, LDAP_MOD_ADD, "id", "root"); - } + do not call this function directly. use passdb.c instead. + +************************************************************************/ +static BOOL mod_ldap21pwd_entry(struct sam_passwd *pwd, BOOL override) +{ + return( modadd_ldappwd_entry(pwd, MODIFY_USER)? + modadd_ldap21pwd_entry(pwd, MODIFY_USER):False); +} + +struct ldap_enum_info +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; +}; + +static struct ldap_enum_info ldap_ent; + +/*************************************************************** + Start to enumerate the ldap passwd list. Returns a void pointer + to ensure no modification outside this module. + + do not call this function directly. use passdb.c instead. - slprintf(rid_str, sizeof(fstring)-1, "%x", (*rid) + 1); - ldap_make_mod(&mods, LDAP_MOD_REPLACE, "nextrid", rid_str); + ****************************************************************/ +static void *startldappwent(BOOL update) +{ + int scope = LDAP_SCOPE_ONELEVEL; + int rc; - if (ldap_entry) + pstring filter; + + if (!ldap_open_connection(&ldap_ent.ldap_struct)) /* open a connection to the server */ { - dn = ldap_get_dn(ldap_struct, ldap_entry); - err = ldap_modify_s(ldap_struct, dn, mods); - free(dn); - } else { - pstrcpy(newdn, "id=root, "); - pstrcat(newdn, lp_ldap_suffix()); - ldap_add_s(ldap_struct, newdn, mods); + return NULL; } - ldap_disconnect(); + if (!ldap_connect_system(ldap_ent.ldap_struct)) /* connect as system account */ + { + return NULL; + } - if(err != LDAP_SUCCESS) + /* when the class is known the search is much faster */ + switch (0) { - DEBUG(0,("nextrid update: %s\n", ldap_err2string(err))); - return (False); + case 1: + { + pstrcpy(filter, "objectclass = sambaAccount"); + break; + } + case 2: + { + pstrcpy(filter, "objectclass = sambaTrust"); + break; + } + default: + { + pstrcpy(filter, "(|(objectclass = sambaTrust)(objectclass = sambaAccount))"); + break; + } } - return (True); + rc = ldap_search_s(ldap_ent.ldap_struct, lp_ldap_suffix(), scope, filter, NULL, 0, &ldap_ent.result); + + DEBUG(2,("%d entries in the base!\n", ldap_count_entries(ldap_ent.ldap_struct, ldap_ent.result) )); + + ldap_ent.entry = ldap_first_entry(ldap_ent.ldap_struct, ldap_ent.result); + + return &ldap_ent; } +/************************************************************************* + Routine to return the next entry in the ldap passwd list. -/*************************************************************** - Begin/end account enumeration. - ****************************************************************/ + do not call this function directly. use passdb.c instead. -static void *ldap_enumfirst(BOOL update) + *************************************************************************/ +static struct smb_passwd *getldappwent(void *vp) { - if (!ldap_connect()) - return NULL; + static struct smb_passwd user; + struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp; - ldap_search_for("objectclass=sambaAccount"); + ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry); - return ldap_struct; + if (ldap_vp->entry ! = NULL) + { + ldap_get_smb_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user); + return &user; + } + return NULL; } -static void ldap_enumclose(void *vp) -{ - ldap_disconnect(); -} +/************************************************************************* + Routine to return the next entry in the ldap passwd list. + do not call this function directly. use passdb.c instead. -/************************************************************************* - Save/restore the current position in a query *************************************************************************/ - -static SMB_BIG_UINT ldap_getdbpos(void *vp) +static struct sam_passwd *getldap21pwent(void *vp) { - return (SMB_BIG_UINT)((ulong)ldap_entry); -} + static struct sam_passwd user; + struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp; -static BOOL ldap_setdbpos(void *vp, SMB_BIG_UINT tok) -{ - ldap_entry = (LDAPMessage *)((ulong)tok); - return (True); + ldap_vp->entry = ldap_next_entry(ldap_vp->ldap_struct, ldap_vp->entry); + + if (ldap_vp->entry ! = NULL) + { + ldap_get_sam_passwd(ldap_vp->ldap_struct, ldap_vp->entry, &user); + return &user; + } + return NULL; } +/*************************************************************** + End enumeration of the ldap passwd list. -/************************************************************************* - Return smb_passwd information. - *************************************************************************/ + do not call this function directly. use passdb.c instead. -static struct smb_passwd *ldap_getpwbynam(const char *name) +****************************************************************/ +static void endldappwent(void *vp) { - struct smb_passwd *ret; - - if(!ldap_connect()) - return NULL; + struct ldap_enum_info *ldap_vp = (struct ldap_enum_info *)vp; + ldap_msgfree(ldap_vp->result); + ldap_unbind(ldap_vp->ldap_struct); +} - ldap_search_by_name(name); - ret = ldap_getpw(); +/************************************************************************* + Return the current position in the ldap passwd list as an SMB_BIG_UINT. + This must be treated as an opaque token. - ldap_disconnect(); - return ret; -} + do not call this function directly. use passdb.c instead. -static struct smb_passwd *ldap_getpwbyuid(uid_t userid) +*************************************************************************/ +static SMB_BIG_UINT getldappwpos(void *vp) { - struct smb_passwd *ret; + return (SMB_BIG_UINT)0; +} - if(!ldap_connect()) - return NULL; +/************************************************************************* + Set the current position in the ldap passwd list from SMB_BIG_UINT. + This must be treated as an opaque token. - ldap_search_by_uid(userid); - ret = ldap_getpw(); + do not call this function directly. use passdb.c instead. - ldap_disconnect(); - return ret; +*************************************************************************/ +static BOOL setldappwpos(void *vp, SMB_BIG_UINT tok) +{ + return False; } -static struct smb_passwd *ldap_getcurrentpw(void *vp) -{ - struct smb_passwd *ret; +/* + * Ldap derived functions. + */ - ret = ldap_getpw(); - ldap_entry = ldap_next_entry(ldap_struct, ldap_entry); - return ret; +static struct smb_passwd *getldappwnam(char *name) +{ + return pdb_sam_to_smb(iterate_getsam21pwnam(name)); } +static struct smb_passwd *getldappwuid(uid_t smb_userid) +{ + return pdb_sam_to_smb(iterate_getsam21pwuid(smb_userid)); +} -/************************************************************************ - Modify user information given an smb_passwd struct. - *************************************************************************/ -static BOOL ldap_addpw(struct smb_passwd *newpwd) +static struct smb_passwd *getldappwrid(uint32 user_rid) { - LDAPMod **mods; + return pdb_sam_to_smb(iterate_getsam21pwuid(pdb_user_rid_to_uid(user_rid))); +} - if (!newpwd || !ldap_allocaterid(&newpwd->user_rid)) - return (False); +static struct smb_passwd *getldappwent(void *vp) +{ + return pdb_sam_to_smb(getldap21pwent(vp)); +} - ldap_smbpwmods(newpwd, &mods, LDAP_MOD_ADD); - return ldap_makemods("uid", newpwd->unix_name, mods, True); +static BOOL add_ldappwd_entry(struct smb_passwd *newpwd) +{ + return add_ldap21pwd_entry(pdb_smb_to_sam(newpwd)); } -static BOOL ldap_modpw(struct smb_passwd *pwd, BOOL override) +static BOOL mod_ldappwd_entry(struct smb_passwd* pwd, BOOL override) { - LDAPMod **mods; + return mod_ldap21pwd_entry(pdb_smb_to_sam(pwd), override); +} - if (!pwd) - return (False); +static struct sam_disp_info *getldapdispnam(char *name) +{ + return pdb_sam_to_dispinfo(getldap21pwnam(name)); +} - ldap_smbpwmods(pwd, &mods, LDAP_MOD_REPLACE); - return ldap_makemods("uid", pwd->unix_name, mods, False); +static struct sam_disp_info *getldapdisprid(uint32 rid) +{ + return pdb_sam_to_dispinfo(getldap21pwrid(rid)); } +static struct sam_disp_info *getldapdispent(void *vp) +{ + return pdb_sam_to_dispinfo(getldap21pwent(vp)); +} -static struct smb_passdb_ops ldap_ops = +static struct sam_passwd *getldap21pwuid(uid_t uid) { - ldap_enumfirst, - ldap_enumclose, - ldap_getdbpos, - ldap_setdbpos, + return pdb_smb_to_sam(iterate_getsam21pwuid(pdb_uid_to_user_rid(uid))); +} - ldap_getpwbynam, - ldap_getpwbyuid, - ldap_getcurrentpw, - ldap_addpw, - ldap_modpw +static struct passdb_ops ldap_ops = +{ + startldappwent, + endldappwent, + getldappwpos, + setldappwpos, + getldappwnam, + getldappwuid, + getldappwrid, + getldappwent, + add_ldappwd_entry, + mod_ldappwd_entry, + getldap21pwent, + iterate_getsam21pwnam, /* From passdb.c */ + iterate_getsam21pwuid, /* From passdb.c */ + iterate_getsam21pwrid, /* From passdb.c */ + add_ldap21pwd_entry, + mod_ldap21pwd_entry, + getldapdispnam, + getldapdisprid, + getldapdispent }; -struct smb_passdb_ops *ldap_initialise_password_db(void) +struct passdb_ops *ldap_initialize_password_db(void) { - FILE *pwdfile; - char *pwdfilename; - char *p; - - pwdfilename = lp_ldap_passwd_file(); - - if(pwdfilename[0]) { - if(pwdfile = sys_fopen(pwdfilename, "r")) { - fgets(ldap_secret, sizeof(ldap_secret), pwdfile); - if(p = strchr(ldap_secret, '\n')) - *p = 0; - fclose(pwdfile); - } else { - DEBUG(0,("Failed to open LDAP passwd file\n")); - } - } - - return &ldap_ops; + return &ldap_ops; } #else - void ldap_dummy_function(void); - void ldap_dummy_function(void) { } /* stop some compilers complaining */ + void dummy_function(void); + void dummy_function(void) { } /* stop some compilers complaining */ #endif |