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 | |
parent | f6276724bafdb6145c0c7b565172d80cb04516ea (diff) | |
download | samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.gz samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.bz2 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')
-rw-r--r-- | source3/passdb/ldap.c | 1160 | ||||
-rw-r--r-- | source3/passdb/nispass.c | 643 | ||||
-rw-r--r-- | source3/passdb/pass_check.c | 183 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 1079 | ||||
-rw-r--r-- | source3/passdb/passgrp.c | 56 | ||||
-rw-r--r-- | source3/passdb/smbpass.c | 682 | ||||
-rw-r--r-- | source3/passdb/smbpasschange.c | 176 | ||||
-rw-r--r-- | source3/passdb/smbpassfile.c | 104 | ||||
-rw-r--r-- | source3/passdb/smbpassgroup.c | 47 |
9 files changed, 3059 insertions, 1071 deletions
diff --git a/source3/passdb/ldap.c b/source3/passdb/ldap.c index 7bdbdab320..43fea00a64 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 diff --git a/source3/passdb/nispass.c b/source3/passdb/nispass.c index f554958ade..27409eca4c 100644 --- a/source3/passdb/nispass.c +++ b/source3/passdb/nispass.c @@ -19,14 +19,37 @@ * Mass Ave, Cambridge, MA 02139, USA. */ +#include "includes.h" + #ifdef WITH_NISPLUS -#include "includes.h" +#ifdef BROKEN_NISPLUS_INCLUDE_FILES + +/* + * The following lines are needed due to buggy include files + * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and + * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA. + * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as + * an enum in /usr/include/rpcsvc/nis.h. + */ + +#if defined(GROUP) +#undef GROUP +#endif + +#if defined(GROUP_OBJ) +#undef GROUP_OBJ +#endif + +#endif + #include <rpcsvc/nis.h> extern int DEBUGLEVEL; +extern pstring samlogon_user; +extern BOOL sam_logon_in_ssb; -static int gotalarm; +static VOLATILE SIG_ATOMIC_T gotalarm; /*************************************************************** @@ -154,9 +177,218 @@ static void get_single_attribute(nis_object *new_obj, int col, len = entry_len; } - safe_strcpy(val, len, ENTRY_VAL(new_obj, col)); + safe_strcpy(val, ENTRY_VAL(new_obj, col), len-1); } +/************************************************************************ + makes a struct sam_passwd from a NIS+ object. + ************************************************************************/ +static BOOL make_sam_from_nisp_object(struct sam_passwd *pw_buf, nis_object *obj) +{ + int uidval; + static pstring user_name; + static pstring full_name; + static pstring home_dir; + static pstring home_drive; + static pstring logon_script; + static pstring profile_path; + static pstring acct_desc; + static pstring workstations; + static pstring temp; + static unsigned char smbpwd[16]; + static unsigned char smbntpwd[16]; + + char *p; + + pdb_init_sam(pw_buf); + pw_buf->acct_ctrl = ACB_NORMAL; + + pstrcpy(user_name, ENTRY_VAL(obj, NPF_NAME)); + pw_buf->smb_name = user_name; + + uidval = atoi(ENTRY_VAL(obj, NPF_UID)); + pw_buf->smb_userid = uidval; + + /* Check the lanman password column. */ + p = (char *)ENTRY_VAL(obj, NPF_LMPWD); + if (*p == '*' || *p == 'X') { + /* Password deliberately invalid - end here. */ + DEBUG(10, ("make_sam_from_nisp_object: entry invalidated for user %s\n", user_name)); + pw_buf->smb_nt_passwd = NULL; + pw_buf->smb_passwd = NULL; + pw_buf->acct_ctrl |= ACB_DISABLED; + return True; + } + if (!strncasecmp(p, "NO PASSWORD", 11)) { + pw_buf->smb_passwd = NULL; + pw_buf->acct_ctrl |= ACB_PWNOTREQ; + } else { + if (strlen(p) != 32 || !pdb_gethexpwd(p, smbpwd)) + { + DEBUG(0, ("make_sam_from_nisp_object: malformed LM pwd entry.\n")); + return False; + } + } + + pw_buf->smb_passwd = smbpwd; + + /* Check the NT password column. */ + p = ENTRY_VAL(obj, NPF_NTPWD); + if (*p != '*' && *p != 'X') { + if (strlen(p) != 32 || !pdb_gethexpwd(p, smbntpwd)) + { + DEBUG(0, ("make_smb_from_nisp_object: malformed NT pwd entry\n")); + return False; + } + pw_buf->smb_nt_passwd = smbntpwd; + } + + p = (char *)ENTRY_VAL(obj, NPF_ACB); + if (*p == '[') + { + pw_buf->acct_ctrl = pdb_decode_acct_ctrl(p); + + /* Must have some account type set. */ + if(pw_buf->acct_ctrl == 0) + pw_buf->acct_ctrl = ACB_NORMAL; + + /* Now try and get the last change time. */ + if(*p == ']') + p++; + if(*p == ':') { + p++; + if(*p && (StrnCaseCmp(p, "LCT-", 4)==0)) { + int i; + p += 4; + for(i = 0; i < 8; i++) { + if(p[i] == '\0' || !isxdigit(p[i])) + break; + } + if(i == 8) { + /* + * p points at 8 characters of hex digits - + * read into a time_t as the seconds since + * 1970 that the password was last changed. + */ + pw_buf->pass_last_set_time = (time_t)strtol(p, NULL, 16); + } + } + } + } else { + /* 'Old' style file. Fake up based on user name. */ + /* + * Currently trust accounts are kept in the same + * password file as 'normal accounts'. If this changes + * we will have to fix this code. JRA. + */ + if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') { + pw_buf->acct_ctrl &= ~ACB_NORMAL; + pw_buf->acct_ctrl |= ACB_WSTRUST; + } + } + + get_single_attribute(obj, NPF_SMB_GRPID, temp, sizeof(pstring)); + pw_buf->smb_grpid = atoi(temp); + + get_single_attribute(obj, NPF_USER_RID, temp, sizeof(pstring)); + pw_buf->user_rid = (strlen(temp) > 0) ? + strtol(temp, NULL, 16) : pdb_uid_to_user_rid (pw_buf->smb_userid); + + if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$') { + + /* XXXX hack to get standard_sub_basic() to use sam logon username */ + /* possibly a better way would be to do a become_user() call */ + pstrcpy(samlogon_user, pw_buf->smb_name); + sam_logon_in_ssb = True; + + get_single_attribute(obj, NPF_GROUP_RID, temp, sizeof(pstring)); + pw_buf->group_rid = (strlen(temp) > 0) ? + strtol(temp, NULL, 16) : pdb_gid_to_group_rid (pw_buf->smb_grpid); + + get_single_attribute(obj, NPF_FULL_NAME, full_name, sizeof(pstring)); +#if 1 + /* It seems correct to use the global values - but in that case why + * do we want these NIS+ entries anyway ?? + */ + pstrcpy(logon_script , lp_logon_script ()); + pstrcpy(profile_path , lp_logon_path ()); + pstrcpy(home_drive , lp_logon_drive ()); + pstrcpy(home_dir , lp_logon_home ()); +#else + get_single_attribute(obj, NPF_LOGON_SCRIPT, logon_script, sizeof(pstring)); + get_single_attribute(obj, NPF_PROFILE_PATH, profile_path, sizeof(pstring)); + get_single_attribute(obj, NPF_DIR_DRIVE, home_drive, sizeof(pstring)); + get_single_attribute(obj, NPF_HOME_DIR, home_dir, sizeof(pstring)); +#endif + get_single_attribute(obj, NPF_ACCT_DESC, acct_desc, sizeof(pstring)); + get_single_attribute(obj, NPF_WORKSTATIONS, workstations, sizeof(pstring)); + + sam_logon_in_ssb = False; + + } else { + + pw_buf->group_rid = DOMAIN_GROUP_RID_USERS; /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ + + pstrcpy(full_name , ""); + pstrcpy(logon_script , ""); + pstrcpy(profile_path , ""); + pstrcpy(home_drive , ""); + pstrcpy(home_dir , ""); + pstrcpy(acct_desc , ""); + pstrcpy(workstations , ""); + } + + pw_buf->full_name = full_name; + pw_buf->home_dir = home_dir; + pw_buf->dir_drive = home_drive; + pw_buf->logon_script = logon_script; + pw_buf->profile_path = profile_path; + pw_buf->acct_desc = acct_desc; + pw_buf->workstations = workstations; + + pw_buf->unknown_str = NULL; /* don't know, yet! */ + pw_buf->munged_dial = NULL; /* "munged" dial-back telephone number */ + + pw_buf->unknown_3 = 0xffffff; /* don't know */ + pw_buf->logon_divs = 168; /* hours per week */ + pw_buf->hours_len = 21; /* 21 times 8 bits = 168 */ + memset(pw_buf->hours, 0xff, pw_buf->hours_len); /* available at all hours */ + pw_buf->unknown_5 = 0x00020000; /* don't know */ + pw_buf->unknown_6 = 0x000004ec; /* don't know */ + + return True; +} + +/************************************************************************ + makes a struct sam_passwd from a NIS+ result. + ************************************************************************/ +static BOOL make_sam_from_nisresult(struct sam_passwd *pw_buf, nis_result *result) +{ + if (pw_buf == NULL || result == NULL) return False; + + if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND) + { + DEBUG(0, ("make_sam_from_nisresult: NIS+ lookup failure: %s\n", + nis_sperrno(result->status))); + return False; + } + + /* User not found. */ + if (NIS_RES_NUMOBJ(result) <= 0) + { + DEBUG(10, ("make_sam_from_nisresult: user not found in NIS+\n")); + return False; + } + + if (NIS_RES_NUMOBJ(result) > 1) + { + DEBUG(10, ("make_sam_from_nisresult: WARNING: Multiple entries for user in NIS+ table!\n")); + } + + /* Grab the first hit. */ + return make_sam_from_nisp_object(pw_buf, &NIS_RES_OBJECT(result)[0]); + } + /*************************************************************** calls nis_list, returns results. ****************************************************************/ @@ -205,21 +437,36 @@ static void *startnisppwent(BOOL update) ****************************************************************/ static void endnisppwent(void *vp) { + struct nisp_enum_info *res = (struct nisp_enum_info *)vp; + nis_freeresult(res->result); + DEBUG(7,("endnisppwent: freed enumeration list\n")); } /************************************************************************* Routine to return the next entry in the nisplus passwd list. - this function is a nice, messy combination of reading: - - the nisplus passwd file - - the unix password database - - nisp.conf options (not done at present). do not call this function directly. use passdb.c instead. *************************************************************************/ static struct sam_passwd *getnisp21pwent(void *vp) { - return NULL; + struct nisp_enum_info *res = (struct nisp_enum_info *)vp; + static struct sam_passwd pw_buf; + int which; + BOOL ret; + + if (res == NULL || (int)(res->enum_entry) < 0 || + (int)(res->enum_entry) > (NIS_RES_NUMOBJ(res->result) - 1)) { + ret = False; + } else { + which = (int)(res->enum_entry); + ret = make_sam_from_nisp_object(&pw_buf, + &NIS_RES_OBJECT(res->result)[which]); + if (ret && which < (NIS_RES_NUMOBJ(res->result) - 1)) + (int)(res->enum_entry)++; + } + + return ret ? &pw_buf : NULL; } /************************************************************************* @@ -231,7 +478,8 @@ static struct sam_passwd *getnisp21pwent(void *vp) *************************************************************************/ static SMB_BIG_UINT getnisppwpos(void *vp) { - return (SMB_BIG_UINT)0; + struct nisp_enum_info *res = (struct nisp_enum_info *)vp; + return (SMB_BIG_UINT)(res->enum_entry); } /************************************************************************* @@ -243,7 +491,13 @@ static SMB_BIG_UINT getnisppwpos(void *vp) *************************************************************************/ static BOOL setnisppwpos(void *vp, SMB_BIG_UINT tok) { - return False; + struct nisp_enum_info *res = (struct nisp_enum_info *)vp; + if (tok < (NIS_RES_NUMOBJ(res->result) - 1)) { + res->enum_entry = tok; + return True; + } else { + return False; + } } /************************************************************************* @@ -255,7 +509,7 @@ static void set_single_attribute(nis_object *new_obj, int col, if (new_obj == NULL) return; ENTRY_VAL(new_obj, col) = val; - ENTRY_LEN(new_obj, col) = len; + ENTRY_LEN(new_obj, col) = len+1; if (flags != 0) { @@ -295,12 +549,12 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) fstring pwdlchg_t; fstring pwdmchg_t; - bzero(logon_t , sizeof(logon_t )); - bzero(logoff_t , sizeof(logoff_t )); - bzero(kickoff_t, sizeof(kickoff_t)); - bzero(pwdlset_t, sizeof(pwdlset_t)); - bzero(pwdlchg_t, sizeof(pwdlchg_t)); - bzero(pwdmchg_t, sizeof(pwdmchg_t)); + memset((char *)logon_t , '\0', sizeof(logon_t )); + memset((char *)logoff_t , '\0', sizeof(logoff_t )); + memset((char *)kickoff_t, '\0', sizeof(kickoff_t)); + memset((char *)pwdlset_t, '\0', sizeof(pwdlset_t)); + memset((char *)pwdlchg_t, '\0', sizeof(pwdlchg_t)); + memset((char *)pwdmchg_t, '\0', sizeof(pwdmchg_t)); pfile = lp_smb_passwd_file(); @@ -308,19 +562,17 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) result = nisp_get_nis_list(nisname); if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND) { - DEBUG(3, ( "add_nisppwd_entry: nis_list failure: %s: %s\n", + DEBUG(3, ( "add_nis21ppwd_entry: nis_list failure: %s: %s\n", nisname, nis_sperrno(result->status))); - nis_freeresult(nis_user); nis_freeresult(result); return False; } if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0) { - DEBUG(3, ("add_nisppwd_entry: User already exists in NIS+ password db: %s\n", + DEBUG(3, ("add_nisp21pwd_entry: User already exists in NIS+ password db: %s\n", pfile)); nis_freeresult(result); - nis_freeresult(nis_user); return False; } @@ -328,10 +580,9 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) /* User not found. */ if (!add_user) { - DEBUG(3, ("add_nisppwd_entry: User not found in NIS+ password db: %s\n", + DEBUG(3, ("add_nisp21pwd_entry: User not found in NIS+ password db: %s\n", pfile)); nis_freeresult(result); - nis_freeresult(nis_user); return False; } @@ -341,9 +592,8 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) if (tblresult->status != NIS_SUCCESS) { nis_freeresult(result); - nis_freeresult(nis_user); nis_freeresult(tblresult); - DEBUG(3, ( "add_nisppwd_entry: nis_lookup failure: %s\n", + DEBUG(3, ( "add_nisp21pwd_entry: nis_lookup failure: %s\n", nis_sperrno(tblresult->status))); return False; } @@ -361,22 +611,37 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) new_obj.zo_data.objdata_u.en_data.en_cols.en_cols_len = NIS_RES_OBJECT(tblresult)->zo_data.objdata_u.ta_data.ta_maxcol; new_obj.zo_data.objdata_u.en_data.en_cols.en_cols_val = calloc(new_obj.zo_data.objdata_u.en_data.en_cols.en_cols_len, sizeof(entry_col)); - pwdb_sethexpwd(smb_passwd , newpwd->smb_passwd , newpwd->acct_ctrl); - pwdb_sethexpwd(smb_nt_passwd, newpwd->smb_nt_passwd, newpwd->acct_ctrl); + if (new_obj.zo_data.objdata_u.en_data.en_cols.en_cols_val == NULL) + { + DEBUG(0, ("add_nisp21pwd_entry: memory allocation failure\n")); + nis_freeresult(result); + nis_freeresult(tblresult); + return False; + } + + pdb_sethexpwd(smb_passwd , newpwd->smb_passwd , newpwd->acct_ctrl); + pdb_sethexpwd(smb_nt_passwd, newpwd->smb_nt_passwd, newpwd->acct_ctrl); + + newpwd->pass_last_set_time = (time_t)time(NULL); + newpwd->logon_time = (time_t)-1; + newpwd->logoff_time = (time_t)-1; + newpwd->kickoff_time = (time_t)-1; + newpwd->pass_can_change_time = (time_t)-1; + newpwd->pass_must_change_time = (time_t)-1; - pwdb_set_logon_time (logon_t , sizeof(logon_t ), newpwd->logon_time ); - pwdb_set_logoff_time (logoff_t , sizeof(logoff_t ), newpwd->logoff_time ); - pwdb_set_kickoff_time (kickoff_t, sizeof(kickoff_t), newpwd->kickoff_time ); - pwdb_set_last_set_time (pwdlset_t, sizeof(pwdlset_t), newpwd->pass_last_set_time ); - pwdb_set_can_change_time (pwdlchg_t, sizeof(pwdlchg_t), newpwd->pass_can_change_time ); - pwdb_set_must_change_time(pwdmchg_t, sizeof(pwdmchg_t), newpwd->pass_must_change_time); + slprintf(logon_t, 13, "LNT-%08X", (uint32)newpwd->logon_time); + slprintf(logoff_t, 13, "LOT-%08X", (uint32)newpwd->logoff_time); + slprintf(kickoff_t, 13, "KOT-%08X", (uint32)newpwd->kickoff_time); + slprintf(pwdlset_t, 13, "LCT-%08X", (uint32)newpwd->pass_last_set_time); + slprintf(pwdlchg_t, 13, "CCT-%08X", (uint32)newpwd->pass_can_change_time); + slprintf(pwdmchg_t, 13, "MCT-%08X", (uint32)newpwd->pass_must_change_time); - slprintf(uid, sizeof(uid), "%u", newpwd->unix_uid); + slprintf(uid, sizeof(uid), "%u", newpwd->smb_userid); slprintf(user_rid, sizeof(user_rid), "0x%x", newpwd->user_rid); slprintf(smb_grpid, sizeof(smb_grpid), "%u", newpwd->smb_grpid); slprintf(group_rid, sizeof(group_rid), "0x%x", newpwd->group_rid); - safe_strcpy(acb, pwdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), sizeof(acb)); + safe_strcpy(acb, pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), sizeof(acb)-1); set_single_attribute(&new_obj, NPF_NAME , newpwd->smb_name , strlen(newpwd->smb_name) , 0); set_single_attribute(&new_obj, NPF_UID , uid , strlen(uid) , 0); @@ -392,6 +657,7 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) set_single_attribute(&new_obj, NPF_PWDLSET_T , pwdlset_t , strlen(pwdlset_t) , 0); set_single_attribute(&new_obj, NPF_PWDLCHG_T , pwdlchg_t , strlen(pwdlchg_t) , 0); set_single_attribute(&new_obj, NPF_PWDMCHG_T , pwdmchg_t , strlen(pwdmchg_t) , 0); +#if 0 set_single_attribute(&new_obj, NPF_FULL_NAME , newpwd->full_name , strlen(newpwd->full_name) , 0); set_single_attribute(&new_obj, NPF_HOME_DIR , newpwd->home_dir , strlen(newpwd->home_dir) , 0); set_single_attribute(&new_obj, NPF_DIR_DRIVE , newpwd->dir_drive , strlen(newpwd->dir_drive) , 0); @@ -400,26 +666,24 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) set_single_attribute(&new_obj, NPF_ACCT_DESC , newpwd->acct_desc , strlen(newpwd->acct_desc) , 0); set_single_attribute(&new_obj, NPF_WORKSTATIONS , newpwd->workstations , strlen(newpwd->workstations) , 0); set_single_attribute(&new_obj, NPF_HOURS , newpwd->hours , newpwd->hours_len , 0); +#endif obj = &new_obj; addresult = nis_add_entry(pfile, obj, ADD_OVERWRITE | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP); - nis_freeresult(nis_user); - if (tblresult) - { - nis_freeresult(tblresult); - } if (addresult->status != NIS_SUCCESS) { - DEBUG(3, ( "add_nisppwd_entry: NIS+ table update failed: %s\n", + DEBUG(3, ( "add_nisp21pwd_entry: NIS+ table update failed: %s\n", nisname, nis_sperrno(addresult->status))); + nis_freeresult(tblresult); nis_freeresult(addresult); nis_freeresult(result); return False; } + nis_freeresult(tblresult); nis_freeresult(addresult); nis_freeresult(result); @@ -439,73 +703,198 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) ************************************************************************/ static BOOL mod_nisp21pwd_entry(struct sam_passwd* pwd, BOOL override) { - return False; + char *oldnislmpwd, *oldnisntpwd, *oldnisacb, *oldnislct, *user_name; + char lmpwd[33], ntpwd[33], lct[13]; + nis_result *result, *addresult; + nis_object *obj; + fstring acb; + pstring nisname; + BOOL got_pass_last_set_time, ret; + int i; + + if (!*lp_smb_passwd_file()) + { + DEBUG(0, ("mod_getnisp21pwd_entry: no SMB password file set\n")); + return False; + } + + DEBUG(10, ("mod_getnisp21pwd_entry: search by name: %s\n", pwd->smb_name)); + DEBUG(10, ("mod_getnisp21pwd_entry: using NIS+ table %s\n", lp_smb_passwd_file())); + + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s", pwd->smb_name, lp_smb_passwd_file()); + + /* Search the table. */ + gotalarm = 0; + CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(5); + + result = nis_list(nisname, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP, NULL, NULL); + + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL); + + if (gotalarm) + { + DEBUG(0,("mod_getnisp21pwd_entry: NIS+ lookup time out\n")); + nis_freeresult(result); + return False; + } + + if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) { + /* User not found. */ + DEBUG(0,("mod_getnisp21pwd_entry: user not found in NIS+\n")); + nis_freeresult(result); + return False; + } + + DEBUG(6,("mod_getnisp21pwd_entry: entry exists\n")); + + obj = NIS_RES_OBJECT(result); + + user_name = ENTRY_VAL(obj, NPF_NAME); + oldnislmpwd = ENTRY_VAL(obj, NPF_LMPWD); + oldnisntpwd = ENTRY_VAL(obj, NPF_NTPWD); + oldnisacb = ENTRY_VAL(obj, NPF_ACB); + oldnislct = ENTRY_VAL(obj, NPF_PWDLSET_T); + + + if (!override && (*oldnislmpwd == '*' || *oldnislmpwd == 'X' || + *oldnisntpwd == '*' || *oldnisntpwd == 'X')) { + /* Password deliberately invalid - end here. */ + DEBUG(10, ("mod_nisp21pwd_entry: entry invalidated for user %s\n", user_name)); + nis_freeresult(result); + return False; + } + + if (strlen(oldnislmpwd) != 32 || strlen(oldnisntpwd) != 32) { + DEBUG(0, ("mod_nisp21pwd_entry: malformed password entry (incorrect length)\n")); + nis_freeresult(result); + return False; + } + + + + /* + * Now check if the account info and the password last + * change time is available. + */ + + /* + * If both NT and lanman passwords are provided - reset password + * not required flag. + */ + + if(pwd->smb_passwd != NULL || pwd->smb_nt_passwd != NULL) { + /* Require password in the future (should ACB_DISABLED also be reset?) */ + pwd->acct_ctrl &= ~(ACB_PWNOTREQ); + } + + if (*oldnisacb == '[') { + + i = 0; + acb[i++] = oldnisacb[i]; + while(i < (sizeof(fstring) - 2) && (oldnisacb[i] != ']')) + acb[i] = oldnisacb[i++]; + + acb[i++] = ']'; + acb[i++] = '\0'; + + if (i == NEW_PW_FORMAT_SPACE_PADDED_LEN) { + /* + * We are using a new format, space padded + * acct ctrl field. Encode the given acct ctrl + * bits into it. + */ + fstrcpy(acb, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN)); + } else { + /* + * If using the old format and the ACB_DISABLED or + * ACB_PWNOTREQ are set then set the lanman and NT passwords to NULL + * here as we have no space to encode the change. + */ + if(pwd->acct_ctrl & (ACB_DISABLED|ACB_PWNOTREQ)) { + pwd->smb_passwd = NULL; + pwd->smb_nt_passwd = NULL; + } + } + + /* Now do the LCT stuff. */ + if (StrnCaseCmp(oldnislct, "LCT-", 4) == 0) { + + for(i = 0; i < 8; i++) { + if(oldnislct[i+4] == '\0' || !isxdigit(oldnislct[i+4])) + break; + } + if (i == 8) { + /* + * p points at 8 characters of hex digits - + * read into a time_t as the seconds since + * 1970 that the password was last changed. + */ + got_pass_last_set_time = True; + } /* i == 8 */ + } /* StrnCaseCmp() */ + + } /* p == '[' */ + + /* Entry is correctly formed. */ + + + + /* Create the 32 byte representation of the new p16 */ + if(pwd->smb_passwd != NULL) { + for (i = 0; i < 16; i++) { + slprintf(&lmpwd[i*2], 32, "%02X", (uchar) pwd->smb_passwd[i]); + } + } else { + if(pwd->acct_ctrl & ACB_PWNOTREQ) + fstrcpy(lmpwd, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + else + fstrcpy(lmpwd, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } + + /* Add on the NT md4 hash */ + if (pwd->smb_nt_passwd != NULL) { + for (i = 0; i < 16; i++) { + slprintf(&ntpwd[i*2], 32, "%02X", (uchar) pwd->smb_nt_passwd[i]); + } + } else { + if(pwd->acct_ctrl & ACB_PWNOTREQ) + fstrcpy(ntpwd, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + else + fstrcpy(ntpwd, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } + + pwd->pass_last_set_time = time(NULL); + + if(got_pass_last_set_time) { + slprintf(lct, 12, "LCT-%08X", (uint32)pwd->pass_last_set_time); + } + + set_single_attribute(obj, NPF_LMPWD, lmpwd, strlen(lmpwd), EN_CRYPT); + set_single_attribute(obj, NPF_NTPWD, ntpwd, strlen(ntpwd), EN_CRYPT); + set_single_attribute(obj, NPF_ACB, acb, strlen(acb), 0); + set_single_attribute(obj, NPF_PWDLSET_T, lct, strlen(lct), 0); + + addresult = + nis_add_entry(lp_smb_passwd_file(), obj, + ADD_OVERWRITE | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP); + + if(addresult->status != NIS_SUCCESS) { + DEBUG(0, ("mod_nisp21pwd_entry: NIS+ table update failed: %s %s\n", nisname, nis_sperrno(addresult->status))); + nis_freeresult(addresult); + nis_freeresult(result); + return False; + } + + DEBUG(6,("mod_nisp21pwd_entry: password changed\n")); + + nis_freeresult(addresult); + nis_freeresult(result); + + return True; } -/************************************************************************ - makes a struct sam_passwd from a NIS+ result. - ************************************************************************/ -static BOOL make_sam_from_nisp(struct sam_passwd *pw_buf, nis_result *result) -{ - int uidval; - static pstring user_name; - static unsigned char smbpwd[16]; - static unsigned char smbntpwd[16]; - nis_object *obj; - uchar *p; - - if (pw_buf == NULL || result == NULL) return False; - - pwdb_init_sam(pw_buf); - - if (result->status != NIS_SUCCESS) - { - DEBUG(0, ("make_smb_from_nisp: NIS+ lookup failure: %s\n", - nis_sperrno(result->status))); - return False; - } - - /* User not found. */ - if (NIS_RES_NUMOBJ(result) <= 0) - { - DEBUG(10, ("make_smb_from_nisp: user not found in NIS+\n")); - return False; - } - - if (NIS_RES_NUMOBJ(result) > 1) - { - DEBUG(10, ("make_smb_from_nisp: WARNING: Multiple entries for user in NIS+ table!\n")); - } - - /* Grab the first hit. */ - obj = &NIS_RES_OBJECT(result)[0]; - - /* Check the lanman password column. */ - p = (uchar *)ENTRY_VAL(obj, NPF_LMPWD); - if (strlen((char *)p) != 32 || !pwdb_gethexpwd((char *)p, (char *)smbpwd)) - { - DEBUG(0, ("make_smb_from_nisp: malformed LM pwd entry.\n")); - return False; - } - - /* Check the NT password column. */ - p = (uchar *)ENTRY_VAL(obj, NPF_NTPWD); - if (strlen((char *)p) != 32 || !pwdb_gethexpwd((char *)p, (char *)smbntpwd)) - { - DEBUG(0, ("make_smb_from_nisp: malformed NT pwd entry\n")); - return False; - } - - strncpy(user_name, ENTRY_VAL(obj, NPF_NAME), sizeof(user_name)); - uidval = atoi(ENTRY_VAL(obj, NPF_UID)); - - pw_buf->smb_name = user_name; - pw_buf->unix_uid = uidval; - pw_buf->smb_passwd = smbpwd; - pw_buf->smb_nt_passwd = smbntpwd; - - return True; -} /************************************************************************* Routine to search the nisplus passwd file for an entry matching the username @@ -524,8 +913,8 @@ static struct sam_passwd *getnisp21pwnam(char *name) return NULL; } - DEBUG(10, ("getnisppwnam: search by name: %s\n", name)); - DEBUG(10, ("getnisppwnam: using NIS+ table %s\n", lp_smb_passwd_file())); + DEBUG(10, ("getnisp21pwnam: search by name: %s\n", name)); + DEBUG(10, ("getnisp21pwnam: using NIS+ table %s\n", lp_smb_passwd_file())); slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s", name, lp_smb_passwd_file()); @@ -541,12 +930,12 @@ static struct sam_passwd *getnisp21pwnam(char *name) if (gotalarm) { - DEBUG(0,("getnisppwnam: NIS+ lookup time out\n")); + DEBUG(0,("getnisp21pwnam: NIS+ lookup time out\n")); nis_freeresult(result); return NULL; } - ret = make_sam_from_nisp(&pw_buf, result); + ret = make_sam_from_nisresult(&pw_buf, result); nis_freeresult(result); return ret ? &pw_buf : NULL; @@ -565,7 +954,7 @@ static struct sam_passwd *getnisp21pwrid(uint32 rid) if (!*lp_smb_passwd_file()) { - DEBUG(0, ("No SMB password file set\n")); + DEBUG(0, ("getnisp21pwrid: no SMB password file set\n")); return NULL; } @@ -591,7 +980,7 @@ static struct sam_passwd *getnisp21pwrid(uint32 rid) return NULL; } - ret = make_sam_from_nisp(&pw_buf, result); + ret = make_sam_from_nisresult(&pw_buf, result); nis_freeresult(result); return ret ? &pw_buf : NULL; @@ -603,52 +992,52 @@ static struct sam_passwd *getnisp21pwrid(uint32 rid) static struct smb_passwd *getnisppwent(void *vp) { - return pwdb_sam_to_smb(getnisp21pwent(vp)); + return pdb_sam_to_smb(getnisp21pwent(vp)); } static BOOL add_nisppwd_entry(struct smb_passwd *newpwd) { - return add_nisp21pwd_entry(pwdb_smb_to_sam(newpwd)); + return add_nisp21pwd_entry(pdb_smb_to_sam(newpwd)); } static BOOL mod_nisppwd_entry(struct smb_passwd* pwd, BOOL override) { - return mod_nisp21pwd_entry(pwdb_smb_to_sam(pwd), override); + return mod_nisp21pwd_entry(pdb_smb_to_sam(pwd), override); } static struct smb_passwd *getnisppwnam(char *name) { - return pwdb_sam_to_smb(getnisp21pwnam(name)); + return pdb_sam_to_smb(getnisp21pwnam(name)); } -static struct sam_passwd *getnisp21pwuid(uid_t unix_uid) +static struct sam_passwd *getnisp21pwuid(uid_t smb_userid) { - return getnisp21pwrid(pwdb_uid_to_user_rid(unix_uid)); + return getnisp21pwrid(pdb_uid_to_user_rid(smb_userid)); } -static struct smb_passwd *getnisppwrid(uid_t user_rid) +static struct smb_passwd *getnisppwrid(uint32 user_rid) { - return pwdb_sam_to_smb(getnisp21pwuid(pwdb_user_rid_to_uid(user_rid))); + return pdb_sam_to_smb(getnisp21pwuid(pdb_user_rid_to_uid(user_rid))); } -static struct smb_passwd *getnisppwuid(uid_t unix_uid) +static struct smb_passwd *getnisppwuid(uid_t smb_userid) { - return pwdb_sam_to_smb(getnisp21pwuid(unix_uid)); + return pdb_sam_to_smb(getnisp21pwuid(smb_userid)); } static struct sam_disp_info *getnispdispnam(char *name) { - return pwdb_sam_to_dispinfo(getnisp21pwnam(name)); + return pdb_sam_to_dispinfo(getnisp21pwnam(name)); } static struct sam_disp_info *getnispdisprid(uint32 rid) { - return pwdb_sam_to_dispinfo(getnisp21pwrid(rid)); + return pdb_sam_to_dispinfo(getnisp21pwrid(rid)); } static struct sam_disp_info *getnispdispent(void *vp) { - return pwdb_sam_to_dispinfo(getnisp21pwent(vp)); + return pdb_sam_to_dispinfo(getnisp21pwent(vp)); } static struct passdb_ops nispasswd_ops = { @@ -673,7 +1062,7 @@ static struct passdb_ops nispasswd_ops = { getnispdispent }; -struct passdb_ops *nisplus_initialise_password_db(void) +struct passdb_ops *nisplus_initialize_password_db(void) { return &nispasswd_ops; } @@ -693,7 +1082,7 @@ static void useful_code(void) { if (nis_user->status != NIS_SUCCESS || NIS_RES_NUMOBJ(nis_user) <= 0) { - DEBUG(3, ("add_nisppwd_entry: Unable to get NIS+ passwd entry for user: %s.\n", + DEBUG(3, ("useful_code: Unable to get NIS+ passwd entry for user: %s.\n", nis_sperrno(nis_user->status))); return False; } diff --git a/source3/passdb/pass_check.c b/source3/passdb/pass_check.c index 7effbfef8d..11ce0d754e 100644 --- a/source3/passdb/pass_check.c +++ b/source3/passdb/pass_check.c @@ -32,7 +32,7 @@ static char this_salt[100]=""; static char this_crypted[100]=""; -#ifdef HAVE_PAM +#ifdef WITH_PAM /******************************************************************* check on PAM authentication ********************************************************************/ @@ -136,6 +136,10 @@ static BOOL pam_auth(char *user,char *password) #ifdef WITH_AFS + +#include <afs/stds.h> +#include <afs/kautils.h> + /******************************************************************* check on AFS authentication ********************************************************************/ @@ -158,6 +162,7 @@ static BOOL afs_auth(char *user,char *password) &reason) == 0) { return(True); } + DEBUG(1,("AFS authentication for \"%s\" failed (%s)\n", user, reason)); return(False); } #endif @@ -165,6 +170,9 @@ static BOOL afs_auth(char *user,char *password) #ifdef WITH_DFS +#include <dce/dce_error.h> +#include <dce/sec_login.h> + /***************************************************************** This new version of the DFS_AUTH code was donated by Karsten Muuss <muuss@or.uni-bonn.de>. It fixes the following problems with the @@ -195,6 +203,7 @@ static BOOL dfs_auth(char *user,char *password) sec_passwd_rec_t passwd_rec; sec_login_auth_src_t auth_src = sec_login_auth_src_network; unsigned char dce_errstr[dce_c_error_string_len]; + gid_t egid; if (dcelogin_atmost_once) return(False); @@ -322,14 +331,16 @@ static BOOL dfs_auth(char *user,char *password) * back to being root on error though. JRA. */ - if (setregid(-1, pw->pw_gid) != 0) { + egid = getegid(); + + if (set_effective_gid(pw->pw_gid) != 0) { DEBUG(0,("Can't set egid to %d (%s)\n", pw->pw_gid, strerror(errno))); return False; } - if (setreuid(-1, pw->pw_uid) != 0) { - setgid(0); + if (set_effective_uid(pw->pw_uid) != 0) { + set_effective_gid(egid); DEBUG(0,("Can't set euid to %d (%s)\n", pw->pw_uid, strerror(errno))); return False; @@ -340,24 +351,17 @@ static BOOL dfs_auth(char *user,char *password) &my_dce_sec_context, &err) == 0) { dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); DEBUG(0,("DCE Setup Identity for %s failed: %s\n", user,dce_errstr)); - return(False); + goto err; } sec_login_get_pwent(my_dce_sec_context, (sec_login_passwd_t*)&pw, &err); if (err != error_status_ok ) { dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); - - return(False); + goto err; } passwd_rec.version_number = sec_passwd_c_version_none; @@ -370,24 +374,16 @@ static BOOL dfs_auth(char *user,char *password) &auth_src, &err); if (err != error_status_ok ) { dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n", user,dce_errstr)); - - return(False); + goto err; } sec_login_certify_identity(my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); DEBUG(0,("DCE certify identity failed: %s\n", dce_errstr)); - - return(False); + goto err; } if (auth_src != sec_login_auth_src_network) { @@ -401,10 +397,7 @@ static BOOL dfs_auth(char *user,char *password) user,dce_errstr)); sec_login_purge_context(&my_dce_sec_context, &err); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - return(False); + goto err; } sec_login_get_pwent(my_dce_sec_context, @@ -412,11 +405,7 @@ static BOOL dfs_auth(char *user,char *password) if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0,("DCE can't get pwent. %s\n", dce_errstr)); - - /* Go back to root, JRA. */ - setuid(0); - setgid(0); - return(False); + goto err; } DEBUG(0,("DCE login succeeded for principal %s on pid %d\n", @@ -434,21 +423,24 @@ static BOOL dfs_auth(char *user,char *password) sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); - /* Go back to root, JRA. */ - setuid(0); - setgid(0); DEBUG(0,("DCE can't get expiration. %s\n", dce_errstr)); - - return(False); + goto err; } - setuid(0); - setgid(0); + set_effective_uid(0); + set_effective_gid(0); DEBUG(0,("DCE context expires: %s",asctime(localtime(&expire_time)))); dcelogin_atmost_once = 1; return (True); + +err: + + /* Go back to root, JRA. */ + set_effective_uid(0); + set_effective_gid(egid); + return(False); } void dfs_unlogin(void) @@ -467,6 +459,9 @@ void dfs_unlogin(void) #endif #ifdef KRB5_AUTH + +#include <krb5.h> + /******************************************************************* check on Kerberos authentication ********************************************************************/ @@ -614,6 +609,7 @@ static char *osf1_bigcrypt(char *password,char *salt1) StrnCpy(salt,salt1,2); StrnCpy(result,salt1,2); + result[2]='\0'; for (i=0; i<parts;i++) { p1 = crypt(p2,salt); @@ -680,7 +676,7 @@ core of password checking routine static BOOL password_check(char *password) { -#ifdef HAVE_PAM +#ifdef WITH_PAM /* This falls through if the password check fails - if HAVE_CRYPT is not defined this causes an error msg saying Warning - no crypt available @@ -691,23 +687,23 @@ static BOOL password_check(char *password) Hence we make a direct return to avoid a second chance!!! */ return (pam_auth(this_user,password)); -#endif +#endif /* WITH_PAM */ #ifdef WITH_AFS if (afs_auth(this_user,password)) return(True); -#endif +#endif /* WITH_AFS */ #ifdef WITH_DFS if (dfs_auth(this_user,password)) return(True); -#endif +#endif /* WITH_DFS */ #ifdef KRB5_AUTH if (krb5_auth(this_user,password)) return(True); -#endif +#endif /* KRB5_AUTH */ #ifdef KRB4_AUTH if (krb4_auth(this_user,password)) return(True); -#endif +#endif /* KRB4_AUTH */ #ifdef OSF1_ENH_SEC { @@ -718,26 +714,42 @@ static BOOL password_check(char *password) } return ret; } -#endif +#endif /* OSF1_ENH_SEC */ #ifdef ULTRIX_AUTH return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0); -#endif +#endif /* ULTRIX_AUTH */ #ifdef LINUX_BIGCRYPT return(linux_bigcrypt(password,this_salt,this_crypted)); -#endif +#endif /* LINUX_BIGCRYPT */ + +#if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS) + + /* + * Some systems have bigcrypt in the C library but might not + * actually use it for the password hashes (HPUX 10.20) is + * a noteable example. So we try bigcrypt first, followed + * by crypt. + */ + + if(strcmp(bigcrypt(password,this_salt),this_crypted) == 0) + return True; + else + return (strcmp((char *)crypt(password,this_salt),this_crypted) == 0); +#else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ #ifdef HAVE_BIGCRYPT return(strcmp(bigcrypt(password,this_salt),this_crypted) == 0); -#endif +#endif /* HAVE_BIGCRYPT */ #ifndef HAVE_CRYPT DEBUG(1,("Warning - no crypt available\n")); return(False); -#else +#else /* HAVE_CRYPT */ return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0); -#endif +#endif /* HAVE_CRYPT */ +#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ } @@ -753,13 +765,12 @@ BOOL pass_check(char *user,char *password, int pwlen, struct passwd *pwd, { pstring pass2; int level = lp_passwordlevel(); - const struct passwd *pass; + struct passwd *pass; if (password) password[pwlen] = 0; #if DEBUG_PASSWORD - DEBUG(100,("checking user=[%s] pass=",user)); - dump_data(100, password, strlen(password)); + DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); #endif if (!password) { @@ -785,12 +796,76 @@ BOOL pass_check(char *user,char *password, int pwlen, struct passwd *pwd, return(False); } +#ifdef HAVE_GETSPNAM + { + struct spwd *spass; + + /* many shadow systems require you to be root to get + the password, in most cases this should already be + the case when this function is called, except + perhaps for IPC password changing requests */ + + spass = getspnam(pass->pw_name); + if (spass && spass->sp_pwdp) { + pstrcpy(pass->pw_passwd,spass->sp_pwdp); + } + } +#elif defined(IA_UINFO) + { + /* Need to get password with SVR4.2's ia_ functions + instead of get{sp,pw}ent functions. Required by + UnixWare 2.x, tested on version + 2.1. (tangent@cyberport.com) */ + uinfo_t uinfo; + if (ia_openinfo(pass->pw_name, &uinfo) != -1) { + ia_get_logpwd(uinfo, &(pass->pw_passwd)); + } + } +#endif + +#ifdef HAVE_GETPRPWNAM + { + struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); + if (pr_pw && pr_pw->ufld.fd_encrypt) + pstrcpy(pass->pw_passwd,pr_pw->ufld.fd_encrypt); + } +#endif + +#ifdef OSF1_ENH_SEC + { + struct pr_passwd *mypasswd; + DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n", + user)); + mypasswd = getprpwnam (user); + if (mypasswd) { + fstrcpy(pass->pw_name,mypasswd->ufld.fd_name); + fstrcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt); + } else { + DEBUG(5,("OSF1_ENH_SEC: No entry for user %s in protected database !\n", + user)); + } + } +#endif + +#ifdef ULTRIX_AUTH + { + AUTHORIZATION *ap = getauthuid(pass->pw_uid); + if (ap) { + fstrcpy(pass->pw_passwd, ap->a_password); + endauthent(); + } + } +#endif + /* extract relevant info */ fstrcpy(this_user,pass->pw_name); fstrcpy(this_salt,pass->pw_passwd); + +#if defined(HAVE_TRUNCATED_SALT) /* crypt on some platforms (HPUX in particular) won't work with more than 2 salt characters. */ this_salt[2] = 0; +#endif fstrcpy(this_crypted,pass->pw_passwd); diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 6579d14351..c0a20f3420 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -24,7 +24,16 @@ #include "nterr.h" extern int DEBUGLEVEL; + +/* + * This is set on startup - it defines the SID for this + * machine, and therefore the SAM database for which it is + * responsible. + */ + extern DOM_SID global_sam_sid; +extern pstring global_myname; +extern fstring global_myworkgroup; /* * NOTE. All these functions are abstracted into a structure @@ -42,41 +51,36 @@ extern DOM_SID global_sam_sid; * functions in a first pass, as struct sam_passwd contains more * information, needed by the NT Domain support. * - * an API writer is expected to create either one set (struct smb_passwd) or - * the other (struct sam_passwd) OR both, and optionally also to write display - * info routines * (struct sam_disp_info). functions which the API writer - * chooses NOT to write must be wrapped in conversion functions (pwdb_x_to_y) - * such that API users can call any function and still get valid results. - * - * the password API does NOT fill in the gaps if you set an API function - * to NULL: it will deliberately attempt to call the NULL function. + * a full example set of derivative functions are listed below. an API + * writer is expected to cut/paste these into their module, replace + * either one set (struct smb_passwd) or the other (struct sam_passwd) + * OR both, and optionally also to write display info routines + * (struct sam_disp_info). lkcl * */ -static struct smb_passdb_ops *pwdb_ops; +static struct passdb_ops *pdb_ops; /*************************************************************** - Initialise the password db operations. + Initialize the password db operations. ***************************************************************/ -BOOL initialise_password_db(void) +BOOL initialize_password_db(void) { - if (pwdb_ops) + if (pdb_ops) { return True; } #ifdef WITH_NISPLUS - pwdb_ops = nisplus_initialise_password_db(); + pdb_ops = nisplus_initialize_password_db(); #elif defined(WITH_LDAP) - pwdb_ops = ldap_initialise_password_db(); -#elif defined(HAVE_MYSQL_H) && defined(WITH_MYSQLSAM) - pwdb_ops = mysql_initialise_password_db(); -#elif defined(USE_SMBPASS_DB) - pwdb_ops = file_initialise_password_db(); + pdb_ops = ldap_initialize_password_db(); +#else + pdb_ops = file_initialize_password_db(); #endif - return (pwdb_ops != NULL); + return (pdb_ops != NULL); } /* @@ -84,16 +88,25 @@ BOOL initialise_password_db(void) */ /************************************************************************ + Utility function to search smb passwd by rid. +*************************************************************************/ + +struct smb_passwd *iterate_getsmbpwrid(uint32 user_rid) +{ + return iterate_getsmbpwuid(pdb_user_rid_to_uid(user_rid)); +} + +/************************************************************************ Utility function to search smb passwd by uid. use this if your database does not have search facilities. *************************************************************************/ -struct smb_passwd *iterate_getsmbpwuid(uid_t unix_uid) +struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid) { struct smb_passwd *pwd = NULL; void *fp = NULL; - DEBUG(10, ("search by unix_uid: %x\n", (int)unix_uid)); + DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid)); /* Open the smb password database - not for update. */ fp = startsmbpwent(False); @@ -104,13 +117,12 @@ struct smb_passwd *iterate_getsmbpwuid(uid_t unix_uid) return NULL; } - while ((pwd = getsmbpwent(fp)) != NULL && pwd->unix_uid != unix_uid) - { - } + while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid) + ; if (pwd != NULL) { - DEBUG(10, ("found by unix_uid: %x\n", (int)unix_uid)); + DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid)); } endsmbpwent(fp); @@ -122,7 +134,7 @@ struct smb_passwd *iterate_getsmbpwuid(uid_t unix_uid) does not have search facilities. *************************************************************************/ -struct smb_passwd *iterate_getsmbpwnam(const char *name) +struct smb_passwd *iterate_getsmbpwnam(char *name) { struct smb_passwd *pwd = NULL; void *fp = NULL; @@ -138,10 +150,8 @@ struct smb_passwd *iterate_getsmbpwnam(const char *name) return NULL; } - while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->unix_name, name)) - { - DEBUG(10, ("iterate: %s 0x%x\n", pwd->unix_name, pwd->unix_uid)); - } + while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name)) + ; if (pwd != NULL) { @@ -165,7 +175,7 @@ struct smb_passwd *iterate_getsmbpwnam(const char *name) void *startsmbpwent(BOOL update) { - return pwdb_ops->startsmbpwent(update); + return pdb_ops->startsmbpwent(update); } /*************************************************************** @@ -180,17 +190,7 @@ void *startsmbpwent(BOOL update) void endsmbpwent(void *vp) { - pwdb_ops->endsmbpwent(vp); -} - -SMB_BIG_UINT getsmbpwpos(void *vp) -{ - return pwdb_ops->getsmbpwpos(vp); -} - -BOOL setsmbpwpos(void *vp, SMB_BIG_UINT tok) -{ - return pwdb_ops->setsmbpwpos(vp, tok); + pdb_ops->endsmbpwent(vp); } /************************************************************************* @@ -199,7 +199,7 @@ BOOL setsmbpwpos(void *vp, SMB_BIG_UINT tok) struct smb_passwd *getsmbpwent(void *vp) { - return pwdb_smb_map_names(pwdb_ops->getsmbpwent(vp)); + return pdb_ops->getsmbpwent(vp); } /************************************************************************ @@ -208,12 +208,7 @@ struct smb_passwd *getsmbpwent(void *vp) BOOL add_smbpwd_entry(struct smb_passwd *newpwd) { - struct smb_passwd *mapped = pwdb_smb_map_names(newpwd); - if (mapped) - { - return pwdb_ops->add_smbpwd_entry(mapped); - } - return False; + return pdb_ops->add_smbpwd_entry(newpwd); } /************************************************************************ @@ -227,121 +222,985 @@ BOOL add_smbpwd_entry(struct smb_passwd *newpwd) BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override) { - struct smb_passwd *mapped = pwdb_smb_map_names(pwd); - if (mapped) - { - return pwdb_ops->mod_smbpwd_entry(mapped, override); - } - return False; + return pdb_ops->mod_smbpwd_entry(pwd, override); } /************************************************************************ Routine to search smb passwd by name. *************************************************************************/ -struct smb_passwd *getsmbpwnam(const char *name) +struct smb_passwd *getsmbpwnam(char *name) { - return pwdb_smb_map_names(pwdb_ops->getsmbpwnam(name)); + return pdb_ops->getsmbpwnam(name); +} + +/************************************************************************ + Routine to search smb passwd by user rid. +*************************************************************************/ + +struct smb_passwd *getsmbpwrid(uint32 user_rid) +{ + return pdb_ops->getsmbpwrid(user_rid); } /************************************************************************ Routine to search smb passwd by uid. *************************************************************************/ -struct smb_passwd *getsmbpwuid(uid_t unix_uid) +struct smb_passwd *getsmbpwuid(uid_t smb_userid) { - return pwdb_smb_map_names(pwdb_ops->getsmbpwuid(unix_uid)); + return pdb_ops->getsmbpwuid(smb_userid); +} + +/* + * Functions that manupulate a struct sam_passwd. + */ + +/************************************************************************ + Utility function to search sam passwd by name. use this if your database + does not have search facilities. +*************************************************************************/ + +struct sam_passwd *iterate_getsam21pwnam(char *name) +{ + struct sam_passwd *pwd = NULL; + void *fp = NULL; + + DEBUG(10, ("search by name: %s\n", name)); + + /* Open the smb password database - not for update. */ + fp = startsmbpwent(False); + + if (fp == NULL) + { + DEBUG(0, ("unable to open sam password database.\n")); + return NULL; + } + + while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name)) + { + DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid)); + } + + if (pwd != NULL) + { + DEBUG(10, ("found by name: %s\n", name)); + } + + endsmbpwent(fp); + return pwd; +} + +/************************************************************************ + Utility function to search sam passwd by rid. use this if your database + does not have search facilities. + + search capability by both rid and uid are needed as the rid <-> uid + mapping may be non-monotonic. + +*************************************************************************/ + +struct sam_passwd *iterate_getsam21pwrid(uint32 rid) +{ + struct sam_passwd *pwd = NULL; + void *fp = NULL; + + DEBUG(10, ("search by rid: %x\n", rid)); + + /* Open the smb password file - not for update. */ + fp = startsmbpwent(False); + + if (fp == NULL) + { + DEBUG(0, ("unable to open sam password database.\n")); + return NULL; + } + + while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid) + { + DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid)); + } + + if (pwd != NULL) + { + DEBUG(10, ("found by user_rid: %x\n", rid)); + } + + endsmbpwent(fp); + return pwd; +} + +/************************************************************************ + Utility function to search sam passwd by uid. use this if your database + does not have search facilities. + + search capability by both rid and uid are needed as the rid <-> uid + mapping may be non-monotonic. + +*************************************************************************/ + +struct sam_passwd *iterate_getsam21pwuid(uid_t uid) +{ + struct sam_passwd *pwd = NULL; + void *fp = NULL; + + DEBUG(10, ("search by uid: %x\n", (int)uid)); + + /* Open the smb password file - not for update. */ + fp = startsmbpwent(False); + + if (fp == NULL) + { + DEBUG(0, ("unable to open sam password database.\n")); + return NULL; + } + + while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid) + ; + + if (pwd != NULL) + { + DEBUG(10, ("found by smb_userid: %x\n", (int)uid)); + } + + endsmbpwent(fp); + return pwd; +} + +/************************************************************************* + Routine to return a display info structure, by rid + *************************************************************************/ +struct sam_disp_info *getsamdisprid(uint32 rid) +{ + return pdb_ops->getsamdisprid(rid); +} + +/************************************************************************* + Routine to return the next entry in the sam passwd list. + *************************************************************************/ + +struct sam_passwd *getsam21pwent(void *vp) +{ + return pdb_ops->getsam21pwent(vp); +} + + +/************************************************************************ + Routine to search sam passwd by name. +*************************************************************************/ + +struct sam_passwd *getsam21pwnam(char *name) +{ + return pdb_ops->getsam21pwnam(name); +} + +/************************************************************************ + Routine to search sam passwd by rid. +*************************************************************************/ + +struct sam_passwd *getsam21pwrid(uint32 rid) +{ + return pdb_ops->getsam21pwrid(rid); +} + + +/********************************************************** + ********************************************************** + + utility routines which are likely to be useful to all password + databases + + ********************************************************** + **********************************************************/ + +/************************************************************* + initialises a struct sam_disp_info. + **************************************************************/ + +static void pdb_init_dispinfo(struct sam_disp_info *user) +{ + if (user == NULL) return; + memset((char *)user, '\0', sizeof(*user)); } /************************************************************* initialises a struct smb_passwd. **************************************************************/ -void pwdb_init_smb(struct smb_passwd *user) + +void pdb_init_smb(struct smb_passwd *user) { if (user == NULL) return; - bzero(user, sizeof(*user)); + memset((char *)user, '\0', sizeof(*user)); user->pass_last_set_time = (time_t)-1; - user->unix_uid = (uid_t)-1; - user->user_rid = 0xffffffff; } /************************************************************* - fills in missing details. one set of details _must_ exist. + initialises a struct sam_passwd. + **************************************************************/ +void pdb_init_sam(struct sam_passwd *user) +{ + if (user == NULL) return; + memset((char *)user, '\0', sizeof(*user)); + user->logon_time = (time_t)-1; + user->logoff_time = (time_t)-1; + user->kickoff_time = (time_t)-1; + user->pass_last_set_time = (time_t)-1; + user->pass_can_change_time = (time_t)-1; + user->pass_must_change_time = (time_t)-1; +} + +/************************************************************************* + Routine to return the next entry in the sam passwd list. + *************************************************************************/ + +struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user) +{ + static struct sam_disp_info disp_info; + + if (user == NULL) return NULL; + + pdb_init_dispinfo(&disp_info); + + disp_info.smb_name = user->smb_name; + disp_info.full_name = user->full_name; + disp_info.user_rid = user->user_rid; + + return &disp_info; +} + +/************************************************************* + converts a sam_passwd structure to a smb_passwd structure. + **************************************************************/ + +struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user) +{ + static struct smb_passwd pw_buf; + + if (user == NULL) return NULL; + + pdb_init_smb(&pw_buf); + + pw_buf.smb_userid = user->smb_userid; + pw_buf.smb_name = user->smb_name; + pw_buf.smb_passwd = user->smb_passwd; + pw_buf.smb_nt_passwd = user->smb_nt_passwd; + pw_buf.acct_ctrl = user->acct_ctrl; + pw_buf.pass_last_set_time = user->pass_last_set_time; + + return &pw_buf; +} + + +/************************************************************* + converts a smb_passwd structure to a sam_passwd structure. **************************************************************/ -struct smb_passwd *pwdb_smb_map_names(struct smb_passwd *smb) + +struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user) { - DOM_NAME_MAP gmep; - BOOL found = False; - DOM_SID sid; - static fstring unix_name; - static fstring nt_name; + static struct sam_passwd pw_buf; + + if (user == NULL) return NULL; + + pdb_init_sam(&pw_buf); + + pw_buf.smb_userid = user->smb_userid; + pw_buf.smb_name = user->smb_name; + pw_buf.smb_passwd = user->smb_passwd; + pw_buf.smb_nt_passwd = user->smb_nt_passwd; + pw_buf.acct_ctrl = user->acct_ctrl; + pw_buf.pass_last_set_time = user->pass_last_set_time; + + return &pw_buf; +} + +/********************************************************** + Encode the account control bits into a string. + length = length of string to encode into (including terminating + null). length *MUST BE MORE THAN 2* ! + **********************************************************/ + +char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length) +{ + static fstring acct_str; + size_t i = 0; + + acct_str[i++] = '['; + + if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N'; + if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D'; + if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H'; + if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T'; + if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U'; + if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M'; + if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W'; + if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S'; + if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L'; + if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X'; + if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I'; + + for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; } - if (smb == NULL) + i = length - 2; + acct_str[i++] = ']'; + acct_str[i++] = '\0'; + + return acct_str; +} + +/********************************************************** + Decode the account control bits from a string. + + this function breaks coding standards minimum line width of 80 chars. + reason: vertical line-up code clarity - all case statements fit into + 15 lines, which is more important. + **********************************************************/ + +uint16 pdb_decode_acct_ctrl(const char *p) +{ + uint16 acct_ctrl = 0; + BOOL finished = False; + + /* + * Check if the account type bits have been encoded after the + * NT password (in the form [NDHTUWSLXI]). + */ + + if (*p != '[') return 0; + + for (p++; *p && !finished; p++) { - DEBUG(10,("pwdb_smb_map_names: NULL\n")); - return NULL; + switch (*p) + { + case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ } + case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ } + case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ } + case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ } + case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ } + case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ } + case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ } + case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } + case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } + case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ } + case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ } + case ' ': { break; } + case ':': + case '\n': + case '\0': + case ']': + default: { finished = True; } + } } - DEBUG(10,("pwdb_smb_map_names: unix %s nt %s unix %d nt%d\n", - smb->unix_name != NULL ? smb->unix_name : "NULL", - smb->nt_name != NULL ? smb->nt_name : "NULL", - smb->unix_uid, smb->user_rid)); + return acct_ctrl; +} + +/******************************************************************* + gets password-database-format time from a string. + ********************************************************************/ - if (smb->unix_name == NULL && smb->nt_name == NULL && - smb->unix_uid == (uid_t)-1 && smb->user_rid == 0xffffffff) +static time_t get_time_from_string(const char *p) +{ + int i; + + for (i = 0; i < 8; i++) { - return NULL; + if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF))) + break; + } + if (i == 8) + { + /* + * p points at 8 characters of hex digits - + * read into a time_t as the seconds since + * 1970 that the password was last changed. + */ + return (time_t)strtol(p, NULL, 16); } - if (smb->unix_name != NULL && smb->nt_name != NULL && - smb->unix_uid != (uid_t)-1 && smb->user_rid != 0xffffffff) + return (time_t)-1; +} + +/******************************************************************* + gets password last set time + ********************************************************************/ + +time_t pdb_get_last_set_time(const char *p) +{ + if (*p && StrnCaseCmp(p, "LCT-", 4)) { - return smb; + return get_time_from_string(p + 4); } + return (time_t)-1; +} - if (!found && smb->unix_name != NULL) + +/******************************************************************* + sets password-database-format time in a string. + ********************************************************************/ +static void set_time_in_string(char *p, int max_len, char *type, time_t t) +{ + slprintf(p, max_len, ":%s-%08X:", type, (uint32)t); +} + +/******************************************************************* + sets logon time + ********************************************************************/ +void pdb_set_logon_time(char *p, int max_len, time_t t) +{ + set_time_in_string(p, max_len, "LNT", t); +} + +/******************************************************************* + sets logoff time + ********************************************************************/ +void pdb_set_logoff_time(char *p, int max_len, time_t t) +{ + set_time_in_string(p, max_len, "LOT", t); +} + +/******************************************************************* + sets kickoff time + ********************************************************************/ +void pdb_set_kickoff_time(char *p, int max_len, time_t t) +{ + set_time_in_string(p, max_len, "KOT", t); +} + +/******************************************************************* + sets password can change time + ********************************************************************/ +void pdb_set_can_change_time(char *p, int max_len, time_t t) +{ + set_time_in_string(p, max_len, "CCT", t); +} + +/******************************************************************* + sets password last set time + ********************************************************************/ +void pdb_set_must_change_time(char *p, int max_len, time_t t) +{ + set_time_in_string(p, max_len, "MCT", t); +} + +/******************************************************************* + sets password last set time + ********************************************************************/ +void pdb_set_last_set_time(char *p, int max_len, time_t t) +{ + set_time_in_string(p, max_len, "LCT", t); +} + + +/************************************************************* + Routine to set 32 hex password characters from a 16 byte array. +**************************************************************/ +void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl) +{ + if (pwd != NULL) { - found = lookupsmbpwnam(smb->unix_name, &gmep); + int i; + for (i = 0; i < 16; i++) + { + slprintf(&p[i*2], 3, "%02X", pwd[i]); + } } - if (!found && smb->unix_uid != (uid_t)-1) + else { - found = lookupsmbpwuid(smb->unix_uid , &gmep); + if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ)) + { + safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33); + } + else + { + safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33); + } } +} +/************************************************************* + Routine to get the 32 hex characters and turn them + into a 16 byte array. +**************************************************************/ +BOOL pdb_gethexpwd(char *p, unsigned char *pwd) +{ + int i; + unsigned char lonybble, hinybble; + char *hexchars = "0123456789ABCDEF"; + char *p1, *p2; - if (!found) + for (i = 0; i < 32; i += 2) { - sid_copy(&sid, &global_sam_sid); - sid_append_rid(&sid, smb->user_rid); + 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); +} + +/******************************************************************* + Group and User RID username mapping function + ********************************************************************/ - if (!found && smb->user_rid != 0xffffffff) +BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid) +{ + struct passwd *pw = Get_Pwnam(user_name, False); + + if (u_rid == NULL || g_rid == NULL || user_name == NULL) { - found = lookupsmbpwsid (&sid , &gmep); + return False; } - if (!found && smb->nt_name != NULL) + + if (!pw) { - found = lookupsmbpwntnam(smb->nt_name, &gmep); + DEBUG(1,("Username %s is invalid on this system\n", user_name)); + return False; } - if (!found) + if (user_in_list(user_name, lp_domain_guest_users())) { - return NULL; + *u_rid = DOMAIN_USER_RID_GUEST; } - - if (!sid_front_equal(&global_sam_sid, &gmep.sid)) + else if (user_in_list(user_name, lp_domain_admin_users())) { - fstring sid_str; - sid_to_string(sid_str, &gmep.sid); - DEBUG(0,("UNIX User %s Primary Group is in the wrong domain! %s\n", - smb->unix_name, sid_str)); - return NULL; + *u_rid = DOMAIN_USER_RID_ADMIN; + } + else + { + /* turn the unix UID into a Domain RID. this is what the posix + sub-system does (adds 1000 to the uid) */ + *u_rid = pdb_uid_to_user_rid(pw->pw_uid); + } + + /* absolutely no idea what to do about the unix GID to Domain RID mapping */ + *g_rid = pdb_gid_to_group_rid(pw->pw_gid); + + return True; +} + +/**************************************************************************** + Read the machine SID from a file. +****************************************************************************/ + +static BOOL read_sid_from_file(int fd, char *sid_file) +{ + fstring fline; + + memset(fline, '\0', sizeof(fline)); + + if(read(fd, fline, sizeof(fline) -1 ) < 0) { + DEBUG(0,("unable to read file %s. Error was %s\n", + sid_file, strerror(errno) )); + return False; + } + + /* + * Convert to the machine SID. + */ + + fline[sizeof(fline)-1] = '\0'; + if(!string_to_sid( &global_sam_sid, fline)) { + DEBUG(0,("unable to generate machine SID.\n")); + return False; + } + + return True; +} + +/**************************************************************************** + Generate the global machine sid. Look for the MACHINE.SID file first, if + not found then look in smb.conf and use it to create the MACHINE.SID file. +****************************************************************************/ +BOOL pdb_generate_sam_sid(void) +{ + int fd; + char *p; + pstring sid_file; + fstring sid_string; + SMB_STRUCT_STAT st; + BOOL overwrite_bad_sid = False; + + generate_wellknown_sids(); + + pstrcpy(sid_file, lp_smb_passwd_file()); + p = strrchr(sid_file, '/'); + if(p != NULL) { + *++p = '\0'; + } + + if (!directory_exist(sid_file, NULL)) { + if (mkdir(sid_file, 0700) != 0) { + DEBUG(0,("can't create private directory %s : %s\n", + sid_file, strerror(errno))); + return False; + } + } + + pstrcat(sid_file, "MACHINE.SID"); + + if((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) { + DEBUG(0,("unable to open or create file %s. Error was %s\n", + sid_file, strerror(errno) )); + return False; + } + + /* + * Check if the file contains data. + */ + + if(sys_fstat( fd, &st) < 0) { + DEBUG(0,("unable to stat file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + if(st.st_size > 0) { + /* + * We have a valid SID - read it. + */ + if(!read_sid_from_file( fd, sid_file)) { + DEBUG(0,("unable to read file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + /* + * JRA. Reversed the sense of this test now that I have + * actually done this test *personally*. One more reason + * to never trust third party information you have not + * independently verified.... sigh. JRA. + */ + + if(global_sam_sid.num_auths > 0 && global_sam_sid.sub_auths[0] == 0x21) { + /* + * Fix and re-write... + */ + overwrite_bad_sid = True; + global_sam_sid.sub_auths[0] = 21; + DEBUG(5,("pdb_generate_sam_sid: Old (incorrect) sid id_auth of hex 21 \ +detected - re-writing to be decimal 21 instead.\n" )); + sid_to_string(sid_string, &global_sam_sid); + if(sys_lseek(fd, (SMB_OFF_T)0, SEEK_SET) != 0) { + DEBUG(0,("unable to seek file file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + } else { + close(fd); + return True; + } + } else { + /* + * The file contains no data - we need to generate our + * own sid. + * Generate the new sid data & turn it into a string. + */ + int i; + uchar raw_sid_data[12]; + DOM_SID mysid; + + memset((char *)&mysid, '\0', sizeof(DOM_SID)); + mysid.sid_rev_num = 1; + mysid.id_auth[5] = 5; + mysid.num_auths = 0; + mysid.sub_auths[mysid.num_auths++] = 21; + + generate_random_buffer( raw_sid_data, 12, True); + for( i = 0; i < 3; i++) + mysid.sub_auths[mysid.num_auths++] = IVAL(raw_sid_data, i*4); + + sid_to_string(sid_string, &mysid); + } + + fstrcat(sid_string, "\n"); + + /* + * Ensure our new SID is valid. + */ + + if(!string_to_sid( &global_sam_sid, sid_string)) { + DEBUG(0,("unable to generate machine SID.\n")); + return False; + } + + /* + * Do an exclusive blocking lock on the file. + */ + + if(!do_file_lock( fd, 60, F_WRLCK)) { + DEBUG(0,("unable to lock file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + if(!overwrite_bad_sid) { + /* + * At this point we have a blocking lock on the SID + * file - check if in the meantime someone else wrote + * SID data into the file. If so - they were here first, + * use their data. + */ + + if(sys_fstat( fd, &st) < 0) { + DEBUG(0,("unable to stat file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + + if(st.st_size > 0) { + /* + * Unlock as soon as possible to reduce + * contention on the exclusive lock. + */ + do_file_lock( fd, 60, F_UNLCK); + + /* + * We have a valid SID - read it. + */ + + if(!read_sid_from_file( fd, sid_file)) { + DEBUG(0,("unable to read file %s. Error was %s\n", + sid_file, strerror(errno) )); + close(fd); + return False; + } + close(fd); + return True; + } + } + + /* + * The file is still empty and we have an exlusive lock on it, + * or we're fixing an earlier mistake. + * Write out out SID data into the file. + */ + + /* + * Use chmod here as some (strange) UNIX's don't + * have fchmod. JRA. + */ + + if(chmod(sid_file, 0644) < 0) { + DEBUG(0,("unable to set correct permissions on file %s. \ +Error was %s\n", sid_file, strerror(errno) )); + do_file_lock( fd, 60, F_UNLCK); + close(fd); + return False; + } + + if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) { + DEBUG(0,("unable to write file %s. Error was %s\n", + sid_file, strerror(errno) )); + do_file_lock( fd, 60, F_UNLCK); + close(fd); + return False; + } + + /* + * Unlock & exit. + */ + + do_file_lock( fd, 60, F_UNLCK); + close(fd); + return True; +} + +/******************************************************************* + Converts NT user RID to a UNIX uid. + ********************************************************************/ + +uid_t pdb_user_rid_to_uid(uint32 user_rid) +{ + return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER); +} + +/******************************************************************* + Converts NT user RID to a UNIX gid. + ********************************************************************/ + +gid_t pdb_user_rid_to_gid(uint32 user_rid) +{ + return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER); +} + +/******************************************************************* + converts UNIX uid to an NT User RID. + ********************************************************************/ + +uint32 pdb_uid_to_user_rid(uid_t uid) +{ + return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE); +} + +/******************************************************************* + converts NT Group RID to a UNIX uid. + ********************************************************************/ + +uint32 pdb_gid_to_group_rid(gid_t gid) +{ + return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE); +} + +/******************************************************************* + Decides if a RID is a well known RID. + ********************************************************************/ + +static BOOL pdb_rid_is_well_known(uint32 rid) +{ + return (rid < 1000); +} + +/******************************************************************* + Decides if a RID is a user or group RID. + ********************************************************************/ + +BOOL pdb_rid_is_user(uint32 rid) +{ + /* lkcl i understand that NT attaches an enumeration to a RID + * such that it can be identified as either a user, group etc + * type. there are 5 such categories, and they are documented. + */ + if(pdb_rid_is_well_known(rid)) { + /* + * The only well known user RIDs are DOMAIN_USER_RID_ADMIN + * and DOMAIN_USER_RID_GUEST. + */ + if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST) + return True; + } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) { + return True; + } + return False; +} + +/******************************************************************* + Convert a rid into a name. Used in the lookup SID rpc. + ********************************************************************/ + +BOOL lookup_local_rid(uint32 rid, char *name, uint8 *psid_name_use) +{ + + BOOL is_user = pdb_rid_is_user(rid); + + DEBUG(5,("lookup_local_rid: looking up %s RID %u.\n", is_user ? "user" : + "group", (unsigned int)rid)); + + if(is_user) { + if(rid == DOMAIN_USER_RID_ADMIN) { + pstring admin_users; + char *p = admin_users; + pstrcpy( admin_users, lp_domain_admin_users()); + if(!next_token(&p, name, NULL, sizeof(fstring))) + fstrcpy(name, "Administrator"); + } else if (rid == DOMAIN_USER_RID_GUEST) { + pstring guest_users; + char *p = guest_users; + pstrcpy( guest_users, lp_domain_guest_users()); + if(!next_token(&p, name, NULL, sizeof(fstring))) + fstrcpy(name, "Guest"); + } else { + uid_t uid = pdb_user_rid_to_uid(rid); + struct passwd *pass = sys_getpwuid(uid); + + *psid_name_use = SID_NAME_USER; + + DEBUG(5,("lookup_local_rid: looking up uid %u %s\n", (unsigned int)uid, + pass ? "succeeded" : "failed" )); + + if(!pass) { + slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); + return True; + } + + fstrcpy(name, pass->pw_name); + + DEBUG(5,("lookup_local_rid: found user %s for rid %u\n", name, + (unsigned int)rid )); + } + + } else { + gid_t gid = pdb_user_rid_to_gid(rid); + struct group *gr = getgrgid(gid); + + *psid_name_use = SID_NAME_ALIAS; + + DEBUG(5,("lookup_local_rid: looking up gid %u %s\n", (unsigned int)gid, + gr ? "succeeded" : "failed" )); + + if(!gr) { + slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid); + return True; + } + + fstrcpy( name, gr->gr_name); + + DEBUG(5,("lookup_local_rid: found group %s for rid %u\n", name, + (unsigned int)rid )); + } + + return True; +} + +/******************************************************************* + Convert a name into a SID. Used in the lookup name rpc. + ********************************************************************/ + +BOOL lookup_local_name(char *domain, char *user, DOM_SID *psid, uint8 *psid_name_use) +{ + extern DOM_SID global_sid_World_Domain; + struct passwd *pass = NULL; + DOM_SID local_sid; + + sid_copy(&local_sid, &global_sam_sid); + + if(!strequal(global_myname, domain) && !strequal(global_myworkgroup, domain)) + return False; + + /* + * Special case for MACHINE\Everyone. Map to the world_sid. + */ + + if(strequal(user, "Everyone")) { + sid_copy( psid, &global_sid_World_Domain); + sid_append_rid(psid, 0); + *psid_name_use = SID_NAME_ALIAS; + return True; + } + + (void)map_username(user); + + if(!(pass = Get_Pwnam(user, False))) { + /* + * Maybe it was a group ? + */ + struct group *grp = getgrnam(user); + + if(!grp) + return False; + + sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); + *psid_name_use = SID_NAME_ALIAS; + } else { + + sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid)); + *psid_name_use = SID_NAME_USER; } - fstrcpy(unix_name, gmep.unix_name); - fstrcpy(nt_name , gmep.nt_name ); - if (smb->unix_name == NULL ) smb->unix_name = unix_name; - if (smb->nt_name == NULL ) smb->nt_name = nt_name ; - if (smb->unix_uid == (uid_t)-1 ) smb->unix_uid = (uid_t)gmep.unix_id; - if (smb->user_rid == 0xffffffff) sid_split_rid(&gmep.sid, &smb->user_rid); + sid_copy( psid, &local_sid); - return smb; + return True; } diff --git a/source3/passdb/passgrp.c b/source3/passdb/passgrp.c index 41b01a1a49..f578d9a20e 100644 --- a/source3/passdb/passgrp.c +++ b/source3/passdb/passgrp.c @@ -34,7 +34,7 @@ extern int DEBUGLEVEL; * */ -static struct passgrp_ops *pwgrp_ops = NULL; +static struct passgrp_ops *pwgrp_ops; /*************************************************************** Initialise the passgrp operations. @@ -50,10 +50,8 @@ BOOL initialise_passgrp_db(void) #ifdef WITH_NISPLUS pwgrp_ops = nisplus_initialise_password_grp(); #elif defined(WITH_LDAP) - pwgrp_ops = ldap_initialise_password_grp(); -#elif defined(USE_SMBUNIX_DB) - pwgrp_ops = unix_initialise_password_grp(); -#elif defined(USE_SMBPASS_DB) + pwgrp_ops = ldap_initialize_password_grp(); +#else pwgrp_ops = file_initialise_password_grp(); #endif @@ -72,30 +70,8 @@ struct smb_passwd *iterate_getsmbgrprid(uint32 user_rid, uint32 **grps, int *num_grps, uint32 **alss, int *num_alss) { - struct smb_passwd *pwd = NULL; - void *fp = NULL; - - DEBUG(10, ("search by user_rid: 0x%x\n", user_rid)); - - /* Open the smb password database - not for update. */ - fp = startsmbgrpent(False); - - if (fp == NULL) - { - DEBUG(0, ("unable to open smb passgrp database.\n")); - return NULL; - } - - while ((pwd = getsmbgrpent(fp, grps, num_grps, alss, num_alss)) != NULL && pwd->user_rid != user_rid) - ; - - if (pwd != NULL) - { - DEBUG(10, ("found by user_rid: 0x%x\n", user_rid)); - } - - endsmbgrpent(fp); - return pwd; + return iterate_getsmbgrpuid(pwdb_user_rid_to_uid(user_rid), + grps, num_grps, alss, num_alss); } /************************************************************************ @@ -103,14 +79,14 @@ struct smb_passwd *iterate_getsmbgrprid(uint32 user_rid, does not have search facilities. *************************************************************************/ -struct smb_passwd *iterate_getsmbgrpuid(uid_t unix_uid, +struct smb_passwd *iterate_getsmbgrpuid(uid_t smb_userid, uint32 **grps, int *num_grps, uint32 **alss, int *num_alss) { struct smb_passwd *pwd = NULL; void *fp = NULL; - DEBUG(10, ("search by unix_uid: %x\n", (int)unix_uid)); + DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid)); /* Open the smb password database - not for update. */ fp = startsmbgrpent(False); @@ -121,12 +97,12 @@ struct smb_passwd *iterate_getsmbgrpuid(uid_t unix_uid, return NULL; } - while ((pwd = getsmbgrpent(fp, grps, num_grps, alss, num_alss)) != NULL && pwd->unix_uid != unix_uid) + while ((pwd = getsmbgrpent(fp, grps, num_grps, alss, num_alss)) != NULL && pwd->smb_userid != smb_userid) ; if (pwd != NULL) { - DEBUG(10, ("found by unix_uid: %x\n", (int)unix_uid)); + DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid)); } endsmbgrpent(fp); @@ -138,14 +114,12 @@ struct smb_passwd *iterate_getsmbgrpuid(uid_t unix_uid, does not have search facilities. *************************************************************************/ -struct smb_passwd *iterate_getsmbgrpntnam(const char *nt_name, +struct smb_passwd *iterate_getsmbgrpnam(char *name, uint32 **grps, int *num_grps, uint32 **alss, int *num_alss) { struct smb_passwd *pwd = NULL; - fstring name; void *fp = NULL; - fstrcpy(name, nt_name); DEBUG(10, ("search by name: %s\n", name)); @@ -158,7 +132,7 @@ struct smb_passwd *iterate_getsmbgrpntnam(const char *nt_name, return NULL; } - while ((pwd = getsmbgrpent(fp, grps, num_grps, alss, num_alss)) != NULL && !strequal(pwd->nt_name, name)) + while ((pwd = getsmbgrpent(fp, grps, num_grps, alss, num_alss)) != NULL && !strequal(pwd->smb_name, name)) ; if (pwd != NULL) @@ -216,11 +190,11 @@ struct smb_passwd *getsmbgrpent(void *vp, Routine to search smb passwd by name. *************************************************************************/ -struct smb_passwd *getsmbgrpntnam(char *name, +struct smb_passwd *getsmbgrpnam(char *name, uint32 **grps, int *num_grps, uint32 **alss, int *num_alss) { - return pwgrp_ops->getsmbgrpntnam(name, grps, num_grps, alss, num_alss); + return pwgrp_ops->getsmbgrpnam(name, grps, num_grps, alss, num_alss); } /************************************************************************ @@ -238,10 +212,10 @@ struct smb_passwd *getsmbgrprid(uint32 user_rid, Routine to search smb passwd by uid. *************************************************************************/ -struct smb_passwd *getsmbgrpuid(uid_t unix_uid, +struct smb_passwd *getsmbgrpuid(uid_t smb_userid, uint32 **grps, int *num_grps, uint32 **alss, int *num_alss) { - return pwgrp_ops->getsmbgrpuid(unix_uid, grps, num_grps, alss, num_alss); + return pwgrp_ops->getsmbgrpuid(smb_userid, grps, num_grps, alss, num_alss); } diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index e3c6a5da44..4cfac6d948 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -21,10 +21,12 @@ #ifdef USE_SMBPASS_DB -static int pw_file_lock_depth = 0; extern int DEBUGLEVEL; +extern pstring samlogon_user; +extern BOOL sam_logon_in_ssb; static char s_readbuf[1024]; +static int pw_file_lock_depth; /*************************************************************** Start to enumerate the smbpasswd list. Returns a void pointer @@ -33,8 +35,37 @@ static char s_readbuf[1024]; static void *startsmbfilepwent(BOOL update) { - return startfileent(lp_smb_passwd_file(), s_readbuf, sizeof(s_readbuf), - &pw_file_lock_depth, update); + FILE *fp = NULL; + char *pfile = lp_smb_passwd_file(); + + if (!*pfile) { + DEBUG(0, ("startsmbfilepwent: No SMB password file set\n")); + return (NULL); + } + DEBUG(10, ("startsmbfilepwent: opening file %s\n", pfile)); + + fp = sys_fopen(pfile, update ? "r+b" : "rb"); + + if (fp == NULL) { + DEBUG(0, ("startsmbfilepwent: unable to open file %s\n", pfile)); + return NULL; + } + + /* Set a buffer to do more efficient reads */ + setvbuf(fp, s_readbuf, _IOFBF, sizeof(s_readbuf)); + + if (!pw_file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, &pw_file_lock_depth)) + { + DEBUG(0, ("startsmbfilepwent: unable to lock file %s\n", pfile)); + fclose(fp); + return NULL; + } + + /* Make sure it is only rw by the owner */ + chmod(pfile, 0600); + + /* We have a lock on the file. */ + return (void *)fp; } /*************************************************************** @@ -43,216 +74,361 @@ static void *startsmbfilepwent(BOOL update) static void endsmbfilepwent(void *vp) { - endfileent(vp, &pw_file_lock_depth); + FILE *fp = (FILE *)vp; + + pw_file_unlock(fileno(fp), &pw_file_lock_depth); + fclose(fp); + DEBUG(7, ("endsmbfilepwent: closed password file.\n")); } /************************************************************************* - Return the current position in the smbpasswd list as an SMB_BIG_UINT. - This must be treated as an opaque token. -*************************************************************************/ - -static SMB_BIG_UINT getsmbfilepwpos(void *vp) + Routine to return the next entry in the smbpasswd list. + *************************************************************************/ +static struct smb_passwd *getsmbfilepwent(void *vp) { - return getfilepwpos(vp); -} + /* Static buffers we will return. */ + static struct smb_passwd pw_buf; + static pstring user_name; + static unsigned char smbpwd[16]; + static unsigned char smbntpwd[16]; + FILE *fp = (FILE *)vp; + char linebuf[256]; + unsigned char c; + unsigned char *p; + long uidval; + size_t linebuf_len; -/************************************************************************* - Set the current position in the smbpasswd list from an SMB_BIG_UINT. - This must be treated as an opaque token. -*************************************************************************/ + if(fp == NULL) { + DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n")); + return NULL; + } -static BOOL setsmbfilepwpos(void *vp, SMB_BIG_UINT tok) -{ - return setfilepwpos(vp, tok); + pdb_init_smb(&pw_buf); + + pw_buf.acct_ctrl = ACB_NORMAL; + + /* + * Scan the file, a line at a time and check if the name matches. + */ + while (!feof(fp)) { + linebuf[0] = '\0'; + + fgets(linebuf, 256, fp); + if (ferror(fp)) { + return NULL; + } + + /* + * Check if the string is terminated with a newline - if not + * then we must keep reading and discard until we get one. + */ + linebuf_len = strlen(linebuf); + if (linebuf[linebuf_len - 1] != '\n') { + c = '\0'; + while (!ferror(fp) && !feof(fp)) { + c = fgetc(fp); + if (c == '\n') + break; + } + } else + linebuf[linebuf_len - 1] = '\0'; + +#ifdef DEBUG_PASSWORD + DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf)); +#endif + if ((linebuf[0] == 0) && feof(fp)) { + DEBUG(4, ("getsmbfilepwent: end of file reached\n")); + break; + } + /* + * The line we have should be of the form :- + * + * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently + * ignored.... + * + * or, + * + * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored.... + * + * if Windows NT compatible passwords are also present. + * [Account type] is an ascii encoding of the type of account. + * LCT-(8 hex digits) is the time_t value of the last change time. + */ + + if (linebuf[0] == '#' || linebuf[0] == '\0') { + DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n")); + continue; + } + p = (unsigned char *) strchr(linebuf, ':'); + if (p == NULL) { + DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n")); + continue; + } + /* + * As 256 is shorter than a pstring we don't need to check + * length here - if this ever changes.... + */ + strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); + user_name[PTR_DIFF(p, linebuf)] = '\0'; + + /* Get smb uid. */ + + p++; /* Go past ':' */ + + if(*p == '-') { + DEBUG(0, ("getsmbfilepwent: uids in the smbpasswd file must not be negative.\n")); + continue; + } + + if (!isdigit(*p)) { + DEBUG(0, ("getsmbfilepwent: malformed password entry (uid not number)\n")); + continue; + } + + uidval = atoi((char *) p); + + while (*p && isdigit(*p)) + p++; + + if (*p != ':') { + DEBUG(0, ("getsmbfilepwent: malformed password entry (no : after uid)\n")); + continue; + } + + pw_buf.smb_name = user_name; + pw_buf.smb_userid = uidval; + + /* + * Now get the password value - this should be 32 hex digits + * which are the ascii representations of a 16 byte string. + * Get two at a time and put them into the password. + */ + + /* Skip the ':' */ + p++; + + if (*p == '*' || *p == 'X') { + /* Password deliberately invalid - end here. */ + DEBUG(10, ("getsmbfilepwent: entry invalidated for user %s\n", user_name)); + pw_buf.smb_nt_passwd = NULL; + pw_buf.smb_passwd = NULL; + pw_buf.acct_ctrl |= ACB_DISABLED; + return &pw_buf; + } + + if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { + DEBUG(0, ("getsmbfilepwent: malformed password entry (passwd too short)\n")); + continue; + } + + if (p[32] != ':') { + DEBUG(0, ("getsmbfilepwent: malformed password entry (no terminating :)\n")); + continue; + } + + if (!strncasecmp((char *) p, "NO PASSWORD", 11)) { + pw_buf.smb_passwd = NULL; + pw_buf.acct_ctrl |= ACB_PWNOTREQ; + } else { + if (!pdb_gethexpwd((char *)p, smbpwd)) { + DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n")); + continue; + } + pw_buf.smb_passwd = smbpwd; + } + + /* + * Now check if the NT compatible password is + * available. + */ + pw_buf.smb_nt_passwd = NULL; + + p += 33; /* Move to the first character of the line after + the lanman password. */ + if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { + if (*p != '*' && *p != 'X') { + if(pdb_gethexpwd((char *)p,smbntpwd)) + pw_buf.smb_nt_passwd = smbntpwd; + } + p += 33; /* Move to the first character of the line after + the NT password. */ + } + + DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n", + user_name, uidval)); + + if (*p == '[') + { + pw_buf.acct_ctrl = pdb_decode_acct_ctrl((char*)p); + + /* Must have some account type set. */ + if(pw_buf.acct_ctrl == 0) + pw_buf.acct_ctrl = ACB_NORMAL; + + /* Now try and get the last change time. */ + if(*p == ']') + p++; + if(*p == ':') { + p++; + if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) { + int i; + p += 4; + for(i = 0; i < 8; i++) { + if(p[i] == '\0' || !isxdigit(p[i])) + break; + } + if(i == 8) { + /* + * p points at 8 characters of hex digits - + * read into a time_t as the seconds since + * 1970 that the password was last changed. + */ + pw_buf.pass_last_set_time = (time_t)strtol((char *)p, NULL, 16); + } + } + } + } else { + /* 'Old' style file. Fake up based on user name. */ + /* + * Currently trust accounts are kept in the same + * password file as 'normal accounts'. If this changes + * we will have to fix this code. JRA. + */ + if(pw_buf.smb_name[strlen(pw_buf.smb_name) - 1] == '$') { + pw_buf.acct_ctrl &= ~ACB_NORMAL; + pw_buf.acct_ctrl |= ACB_WSTRUST; + } + } + + return &pw_buf; + } + + DEBUG(5,("getsmbfilepwent: end of file reached.\n")); + return NULL; } /************************************************************************* Routine to return the next entry in the smbpasswd list. - - this function is non-static as it is called (exclusively and only) - from getsamfile21pwent(). + this function is a nice, messy combination of reading: + - the smbpasswd file + - the unix password database + - smb.conf options (not done at present). *************************************************************************/ -struct smb_passwd *getsmbfilepwent(void *vp) + +static struct sam_passwd *getsmbfile21pwent(void *vp) { - /* Static buffers we will return. */ - static struct smb_passwd pw_buf; - static pstring unix_name; - static unsigned char smbpwd[16]; - static unsigned char smbntpwd[16]; - char linebuf[256]; - char *p; - int uidval; - size_t linebuf_len; - - if (vp == NULL) + struct smb_passwd *pw_buf = getsmbfilepwent(vp); + static struct sam_passwd user; + struct passwd *pwfile; + + static pstring full_name; + static pstring home_dir; + static pstring home_drive; + static pstring logon_script; + static pstring profile_path; + static pstring acct_desc; + static pstring workstations; + + DEBUG(5,("getsmbfile21pwent\n")); + + if (pw_buf == NULL) return NULL; + + pwfile = sys_getpwnam(pw_buf->smb_name); + if (pwfile == NULL) { - DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n")); + DEBUG(0,("getsmbfile21pwent: smbpasswd database is corrupt!\n")); + DEBUG(0,("getsmbfile21pwent: username %s not in unix passwd database!\n", pw_buf->smb_name)); return NULL; } - pwdb_init_smb(&pw_buf); + pdb_init_sam(&user); + + pstrcpy(samlogon_user, pw_buf->smb_name); - pw_buf.acct_ctrl = ACB_NORMAL; + if (samlogon_user[strlen(samlogon_user)-1] != '$') + { + /* XXXX hack to get standard_sub_basic() to use sam logon username */ + /* possibly a better way would be to do a become_user() call */ + sam_logon_in_ssb = True; + + user.smb_userid = pw_buf->smb_userid; + user.smb_grpid = pwfile->pw_gid; + + user.user_rid = pdb_uid_to_user_rid (user.smb_userid); + user.group_rid = pdb_gid_to_group_rid(user.smb_grpid ); - /* - * Scan the file, a line at a time. - */ - while ((linebuf_len = getfileline(vp, linebuf, sizeof(linebuf))) > 0) + pstrcpy(full_name , pwfile->pw_gecos ); + pstrcpy(logon_script , lp_logon_script ()); + pstrcpy(profile_path , lp_logon_path ()); + pstrcpy(home_drive , lp_logon_drive ()); + pstrcpy(home_dir , lp_logon_home ()); + pstrcpy(acct_desc , ""); + pstrcpy(workstations , ""); + + sam_logon_in_ssb = False; + } + else { - /* - * The line we have should be of the form :- - * - * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently - * ignored.... - * - * or, - * - * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored.... - * - * if Windows NT compatible passwords are also present. - * [Account type] is an ascii encoding of the type of account. - * LCT-(8 hex digits) is the time_t value of the last change time. - */ - - /* - * As 256 is shorter than a pstring we don't need to check - * length here - if this ever changes.... - */ - p = strncpyn(unix_name, linebuf, sizeof(unix_name), ':'); - - if (p == NULL) - { - DEBUG(0,("getsmbfilepwent: no ':' separator found\n")); - continue; - } - - /* Go past ':' */ - p++; - - /* Get smb uid. */ - - p = Atoic( p, &uidval, ":"); - - pw_buf.unix_name = unix_name; - pw_buf.unix_uid = uidval; - - /* - * Now get the password value - this should be 32 hex digits - * which are the ascii representations of a 16 byte string. - * Get two at a time and put them into the password. - */ - - /* Skip the ':' */ - p++; - - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) - { - DEBUG(0, ("getsmbfilepwent: malformed password entry (passwd too short)\n")); - continue; - } - - if (p[32] != ':') - { - DEBUG(0, ("getsmbfilepwent: malformed password entry (no terminating :)\n")); - continue; - } - - if (!strncasecmp( p, "NO PASSWORD", 11)) - { - pw_buf.smb_passwd = NULL; - pw_buf.acct_ctrl |= ACB_PWNOTREQ; - } - else - { - if (!pwdb_gethexpwd(p, (char *)smbpwd, NULL)) - { - DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n")); - continue; - } - pw_buf.smb_passwd = smbpwd; - } - - /* - * Now check if the NT compatible password is - * available. - */ - pw_buf.smb_nt_passwd = NULL; - - /* Move to the first character of the line after the lanman password. */ - p += 33; - if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) - { - if (*p != '*' && *p != 'X') - { - if(pwdb_gethexpwd(p,(char *)smbntpwd, NULL)) - { - pw_buf.smb_nt_passwd = smbntpwd; - } - } - /* Move to the first character of the line after the NT password. */ - p += 33; - } - - DEBUG(5,("getsmbfilepwent: returning passwd entry for unix user %s, unix uid %d\n", - unix_name, uidval)); - - if (*p == '[') - { - pw_buf.acct_ctrl = pwdb_decode_acct_ctrl((char*)p); - - /* Must have some account type set. */ - if (pw_buf.acct_ctrl == 0) - { - pw_buf.acct_ctrl = ACB_NORMAL; - } - - /* Now try and get the last change time. */ - while (*p != ']' && *p != ':') - { - p++; - } - if (*p == ']') - { - p++; - } - if (*p == ':') - { - p++; - pw_buf.pass_last_set_time = pwdb_get_last_set_time(p); - } - } - else - { - /* 'Old' style file. Fake up based on user name. */ - /* - * Currently trust accounts are kept in the same - * password file as 'normal accounts'. If this changes - * we will have to fix this code. JRA. - */ - if (pw_buf.unix_name[strlen(pw_buf.unix_name) - 1] == '$') - { - pw_buf.acct_ctrl &= ~ACB_NORMAL; - pw_buf.acct_ctrl |= ACB_WSTRUST; - } - } - - if (*p == '*' || *p == 'X') - { - /* Password deliberately invalid - end here. */ - DEBUG(10, ("getsmbfilepwent: entry invalidated for unix user %s\n", unix_name)); - pw_buf.smb_nt_passwd = NULL; - pw_buf.smb_passwd = NULL; - pw_buf.acct_ctrl |= ACB_DISABLED; - } - - DEBUG(6,("unixuser:%s uid:%d acb:%x\n", - pw_buf.unix_name, pw_buf.unix_uid, pw_buf.acct_ctrl)); - - return &pw_buf; + user.smb_userid = pw_buf->smb_userid; + user.smb_grpid = pwfile->pw_gid; + + user.user_rid = pdb_uid_to_user_rid (user.smb_userid); + user.group_rid = DOMAIN_GROUP_RID_USERS; /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ + + pstrcpy(full_name , ""); + pstrcpy(logon_script , ""); + pstrcpy(profile_path , ""); + pstrcpy(home_drive , ""); + pstrcpy(home_dir , ""); + pstrcpy(acct_desc , ""); + pstrcpy(workstations , ""); } - DEBUG(5,("getsmbfilepwent: end of file reached.\n")); - return NULL; + user.smb_name = pw_buf->smb_name; + user.full_name = full_name; + user.home_dir = home_dir; + user.dir_drive = home_drive; + user.logon_script = logon_script; + user.profile_path = profile_path; + user.acct_desc = acct_desc; + user.workstations = workstations; + + user.unknown_str = NULL; /* don't know, yet! */ + user.munged_dial = NULL; /* "munged" dial-back telephone number */ + + user.smb_nt_passwd = pw_buf->smb_nt_passwd; + user.smb_passwd = pw_buf->smb_passwd; + + 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 */ + + return &user; +} + +/************************************************************************* + Return the current position in the smbpasswd list as an SMB_BIG_UINT. + This must be treated as an opaque token. +*************************************************************************/ + +static SMB_BIG_UINT getsmbfilepwpos(void *vp) +{ + return (SMB_BIG_UINT)sys_ftell((FILE *)vp); +} + +/************************************************************************* + Set the current position in the smbpasswd list from an SMB_BIG_UINT. + This must be treated as an opaque token. +*************************************************************************/ + +static BOOL setsmbfilepwpos(void *vp, SMB_BIG_UINT tok) +{ + return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET); } /************************************************************************ @@ -287,8 +463,8 @@ static BOOL add_smbfilepwd_entry(struct smb_passwd *newpwd) */ while ((pwd = getsmbfilepwent(fp)) != NULL) { - if (strequal(newpwd->unix_name, pwd->unix_name)) { - DEBUG(0, ("add_smbfilepwd_entry: entry with unix name %s already exists\n", pwd->unix_name)); + if (strequal(newpwd->smb_name, pwd->smb_name)) { + DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name)); endsmbfilepwent(fp); return False; } @@ -305,21 +481,21 @@ static BOOL add_smbfilepwd_entry(struct smb_passwd *newpwd) if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1) { DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \ -Error was %s\n", newpwd->unix_name, pfile, strerror(errno))); +Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); endsmbfilepwent(fp); return False; } - new_entry_length = strlen(newpwd->unix_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2; + new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2; if((new_entry = (char *)malloc( new_entry_length )) == NULL) { DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \ -Error was %s\n", newpwd->unix_name, pfile, strerror(errno))); +Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); endsmbfilepwent(fp); return False; } - slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->unix_name, (unsigned)newpwd->unix_uid); + slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid); p = &new_entry[strlen(new_entry)]; if(newpwd->smb_passwd != NULL) { @@ -355,7 +531,7 @@ Error was %s\n", newpwd->unix_name, pfile, strerror(errno))); /* Add the account encoding and the last change time. */ slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n", - pwdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)time(NULL)); + pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)time(NULL)); #ifdef DEBUG_PASSWORD DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d entry_len %d made line |%s|", @@ -364,13 +540,13 @@ Error was %s\n", newpwd->unix_name, pfile, strerror(errno))); if ((wr_len = write(fd, new_entry, strlen(new_entry))) != strlen(new_entry)) { DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \ -Error was %s\n", wr_len, newpwd->unix_name, pfile, strerror(errno))); +Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno))); /* Remove the entry we just wrote. */ if(sys_ftruncate(fd, offpos) == -1) { DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \ Error was %s. Password file may be corrupt ! Please examine by hand !\n", - newpwd->unix_name, strerror(errno))); + newpwd->smb_name, strerror(errno))); } endsmbfilepwent(fp); @@ -395,7 +571,7 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n", static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) { /* Static buffers we will return. */ - static pstring unix_name; + static pstring user_name; char linebuf[256]; char readbuf[1024]; @@ -416,17 +592,6 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) int wr_len; int fd; -#ifdef DEBUG_PASSWORD - DEBUG(100,("mod_smbfilepwd_entry: password entries\n")); - if (pwd->smb_passwd != NULL) - { - dump_data(100, pwd->smb_passwd, 16); - } - if (pwd->smb_nt_passwd != NULL) - { - dump_data(100, pwd->smb_nt_passwd, 16); - } -#endif if (!*pfile) { DEBUG(0, ("No SMB password file set\n")); return False; @@ -444,7 +609,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) lockfd = fileno(fp); - if (!file_lock(lockfd, F_WRLCK, 5, &pw_file_lock_depth)) { + if (!pw_file_lock(lockfd, F_WRLCK, 5, &pw_file_lock_depth)) { DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile)); fclose(fp); return False; @@ -464,7 +629,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) fgets(linebuf, sizeof(linebuf), fp); if (ferror(fp)) { - file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &pw_file_lock_depth); fclose(fp); return False; } @@ -524,16 +689,16 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) * As 256 is shorter than a pstring we don't need to check * length here - if this ever changes.... */ - strncpy(unix_name, linebuf, PTR_DIFF(p, linebuf)); - unix_name[PTR_DIFF(p, linebuf)] = '\0'; - if (strequal(unix_name, pwd->unix_name)) { + strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); + user_name[PTR_DIFF(p, linebuf)] = '\0'; + if (strequal(user_name, pwd->smb_name)) { found_entry = True; break; } } if (!found_entry) { - file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &pw_file_lock_depth); fclose(fp); return False; } @@ -545,7 +710,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) if (!isdigit(*p)) { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (uid not number)\n")); - file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &pw_file_lock_depth); fclose(fp); return False; } @@ -554,7 +719,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) p++; if (*p != ':') { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no : after uid)\n")); - file_unlock(lockfd, &pw_file_lock_depth); + pw_file_unlock(lockfd, &pw_file_lock_depth); fclose(fp); return False; } @@ -571,28 +736,28 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) if (!override && (*p == '*' || *p == 'X')) { /* Password deliberately invalid - end here. */ - DEBUG(10, ("mod_smbfilepwd_entry: entry invalidated for unix user %s\n", unix_name)); - file_unlock(lockfd, &pw_file_lock_depth); + DEBUG(10, ("mod_smbfilepwd_entry: entry invalidated for user %s\n", user_name)); + pw_file_unlock(lockfd, &pw_file_lock_depth); fclose(fp); return False; } if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n")); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return (False); } if (p[32] != ':') { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n")); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } if (!override && (*p == '*' || *p == 'X')) { - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } @@ -603,14 +768,14 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) the lanman password. */ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n")); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return (False); } if (p[32] != ':') { DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n")); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } @@ -648,7 +813,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) * acct ctrl field. Encode the given acct ctrl * bits into it. */ - fstrcpy(encode_bits, pwdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN)); + fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN)); } else { /* * If using the old format and the ACB_DISABLED or @@ -738,7 +903,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) if(wr_len > sizeof(linebuf)) { DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1)); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return (False); } @@ -756,7 +921,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) { DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile)); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } @@ -764,50 +929,89 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) /* Sanity check - ensure the areas we are writing are framed by ':' */ if (read(fd, linebuf, wr_len+1) != wr_len+1) { DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile)); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) { DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile)); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) { DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile)); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } if (write(fd, ascii_p16, wr_len) != wr_len) { DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile)); - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } - file_unlock(lockfd,&pw_file_lock_depth); + pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return True; } -static struct smb_passdb_ops file_ops = { +/* + * Stub functions - implemented in terms of others. + */ + +static BOOL mod_smbfile21pwd_entry(struct sam_passwd* pwd, BOOL override) +{ + return mod_smbfilepwd_entry(pdb_sam_to_smb(pwd), override); +} + +static BOOL add_smbfile21pwd_entry(struct sam_passwd *newpwd) +{ + return add_smbfilepwd_entry(pdb_sam_to_smb(newpwd)); +} + +static struct sam_disp_info *getsmbfiledispnam(char *name) +{ + return pdb_sam_to_dispinfo(getsam21pwnam(name)); +} + +static struct sam_disp_info *getsmbfiledisprid(uint32 rid) +{ + return pdb_sam_to_dispinfo(getsam21pwrid(rid)); +} + +static struct sam_disp_info *getsmbfiledispent(void *vp) +{ + return pdb_sam_to_dispinfo(getsam21pwent(vp)); +} + +static struct passdb_ops file_ops = { startsmbfilepwent, endsmbfilepwent, getsmbfilepwpos, setsmbfilepwpos, iterate_getsmbpwnam, /* In passdb.c */ iterate_getsmbpwuid, /* In passdb.c */ + iterate_getsmbpwrid, /* In passdb.c */ getsmbfilepwent, add_smbfilepwd_entry, - mod_smbfilepwd_entry + mod_smbfilepwd_entry, + getsmbfile21pwent, + iterate_getsam21pwnam, + iterate_getsam21pwuid, + iterate_getsam21pwrid, + add_smbfile21pwd_entry, + mod_smbfile21pwd_entry, + getsmbfiledispnam, + getsmbfiledisprid, + getsmbfiledispent }; -struct smb_passdb_ops *file_initialise_password_db(void) +struct passdb_ops *file_initialize_password_db(void) { return &file_ops; } diff --git a/source3/passdb/smbpasschange.c b/source3/passdb/smbpasschange.c index a0d9b1b143..9d0aecf8b8 100644 --- a/source3/passdb/smbpasschange.c +++ b/source3/passdb/smbpasschange.c @@ -25,23 +25,24 @@ /************************************************************* add a new user to the local smbpasswd file *************************************************************/ -static BOOL add_new_user(char *user_name, uid_t uid, - uint16 acb_info, - uchar *new_p16, uchar *new_nt_p16) +static BOOL add_new_user(char *user_name, uid_t uid, BOOL trust_account, + BOOL disable_user, BOOL set_no_password, + uchar *new_p16, uchar *new_nt_p16) { struct smb_passwd new_smb_pwent; - pwdb_init_smb(&new_smb_pwent); - /* Create a new smb passwd entry and set it to the given password. */ - new_smb_pwent.unix_uid = uid; - new_smb_pwent.nt_name = user_name; + new_smb_pwent.smb_userid = uid; + new_smb_pwent.smb_name = user_name; new_smb_pwent.smb_passwd = NULL; new_smb_pwent.smb_nt_passwd = NULL; - new_smb_pwent.acct_ctrl = acb_info; + new_smb_pwent.acct_ctrl = (trust_account ? ACB_WSTRUST : ACB_NORMAL); - if (IS_BITS_CLR_ALL(acb_info, ACB_DISABLED | ACB_PWNOTREQ)) - { + if(disable_user) { + new_smb_pwent.acct_ctrl |= ACB_DISABLED; + } else if (set_no_password) { + new_smb_pwent.acct_ctrl |= ACB_PWNOTREQ; + } else { new_smb_pwent.smb_passwd = new_p16; new_smb_pwent.smb_nt_passwd = new_nt_p16; } @@ -51,93 +52,83 @@ static BOOL add_new_user(char *user_name, uid_t uid, /************************************************************* -change a password entry in the local smbpasswd file. - -when modifying an account, set acb_mask to those bits that -require changing (to zero or one) and set acb_info to the -value required in those bits. all bits NOT set in acb_mask -will NOT be modified. - -when _adding_ an account, acb_mask must be set to 0xFFFF and -it is ignored, btw :-) - +change a password entry in the local smbpasswd file *************************************************************/ -BOOL local_password_change(char *user_name, - BOOL add_user, - uint16 acb_info, uint16 acb_mask, - char *new_passwd, - char *err_str, size_t err_str_len, - char *msg_str, size_t msg_str_len) + +BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user, + BOOL enable_user, BOOL disable_user, BOOL set_no_password, + char *new_passwd, + char *err_str, size_t err_str_len, + char *msg_str, size_t msg_str_len) { - const struct passwd *pwd; + struct passwd *pwd; + void *vp; struct smb_passwd *smb_pwent; - static struct smb_passwd new_pwent; - static uchar new_p16[16]; - static uchar new_nt_p16[16]; - fstring unix_name; - uid_t unix_uid; + uchar new_p16[16]; + uchar new_nt_p16[16]; *err_str = '\0'; *msg_str = '\0'; - pwd = Get_Pwnam(user_name, False); + pwd = sys_getpwnam(user_name); /* - * Check for a trust account. + * Check for a local account. */ - if ((acb_info & acb_mask) != acb_info) - { - slprintf(err_str, err_str_len - 1, "programmer error: acb_info (%x) requests bits to be set outside of acb_mask (%x) range\n", acb_info, acb_mask); - } - - if (pwd == NULL) - { - if (!IS_BITS_SET_ALL(acb_info, ACB_NORMAL)) - { - slprintf(err_str, err_str_len - 1, "User %s does not \ -exist in system password file (usually /etc/passwd). \ -Cannot add trust account without a valid system user.\n", user_name); - } - else - { - slprintf(err_str, err_str_len - 1, "User %s does not \ -exist in system password file (usually /etc/passwd).\n", user_name); - } + if(!pwd) { + slprintf(err_str, err_str_len - 1, "User %s does not \ +exist in system password file (usually /etc/passwd). Cannot add \ +account without a valid local system user.\n", user_name); return False; } - unix_uid = pwd->pw_uid; - fstrcpy(unix_name, pwd->pw_name); - /* Calculate the MD4 hash (NT compatible) of the new password. */ nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16); + /* + * Open the smbpaswd file. + */ + vp = startsmbpwent(True); + if (!vp && errno == ENOENT) { + FILE *fp; + slprintf(msg_str,msg_str_len-1, + "smbpasswd file did not exist - attempting to create it.\n"); + fp = sys_fopen(lp_smb_passwd_file(), "w"); + if (fp) { + fprintf(fp, "# Samba SMB password file\n"); + fclose(fp); + vp = startsmbpwent(True); + } + } + + if (!vp) { + slprintf(err_str, err_str_len-1, "Cannot open file %s. Error was %s\n", + lp_smb_passwd_file(), strerror(errno) ); + return False; + } + /* Get the smb passwd entry for this user */ smb_pwent = getsmbpwnam(user_name); - if (smb_pwent == NULL) - { - if (!add_user) - { + if (smb_pwent == NULL) { + if(add_user == False) { slprintf(err_str, err_str_len-1, - "Failed to find entry for user %s.\n", unix_name); + "Failed to find entry for user %s.\n", pwd->pw_name); + endsmbpwent(vp); return False; } - if (add_new_user(user_name, unix_uid, acb_info, - new_p16, new_nt_p16)) - { + if (add_new_user(user_name, pwd->pw_uid, trust_account, disable_user, + set_no_password, new_p16, new_nt_p16)) { slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name); + endsmbpwent(vp); return True; - } - else - { + } else { slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name); + endsmbpwent(vp); return False; } - } - else - { + } else { /* the entry already existed */ add_user = False; } @@ -147,25 +138,44 @@ exist in system password file (usually /etc/passwd).\n", user_name); * and the valid last change time. */ - memcpy(&new_pwent, smb_pwent, sizeof(new_pwent)); - new_pwent.nt_name = user_name; - new_pwent.acct_ctrl &= ~acb_mask; - new_pwent.acct_ctrl |= (acb_info & acb_mask); - new_pwent.smb_passwd = NULL; - new_pwent.smb_nt_passwd = NULL; - - if (IS_BITS_CLR_ALL(acb_info, ACB_DISABLED | ACB_PWNOTREQ)) - { - new_pwent.smb_passwd = new_p16; - new_pwent.smb_nt_passwd = new_nt_p16; + if(disable_user) { + smb_pwent->acct_ctrl |= ACB_DISABLED; + } else if (enable_user) { + if(smb_pwent->smb_passwd == NULL) { + smb_pwent->smb_passwd = new_p16; + smb_pwent->smb_nt_passwd = new_nt_p16; + } + smb_pwent->acct_ctrl &= ~ACB_DISABLED; + } else if (set_no_password) { + smb_pwent->acct_ctrl |= ACB_PWNOTREQ; + /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */ + smb_pwent->smb_passwd = NULL; + smb_pwent->smb_nt_passwd = NULL; + } else { + /* + * If we're dealing with setting a completely empty user account + * ie. One with a password of 'XXXX', but not set disabled (like + * an account created from scratch) then if the old password was + * 'XX's then getsmbpwent will have set the ACB_DISABLED flag. + * We remove that as we're giving this user their first password + * and the decision hasn't really been made to disable them (ie. + * don't create them disabled). JRA. + */ + if((smb_pwent->smb_passwd == NULL) && (smb_pwent->acct_ctrl & ACB_DISABLED)) + smb_pwent->acct_ctrl &= ~ACB_DISABLED; + smb_pwent->acct_ctrl &= ~ACB_PWNOTREQ; + smb_pwent->smb_passwd = new_p16; + smb_pwent->smb_nt_passwd = new_nt_p16; } - if (!mod_smbpwd_entry(&new_pwent, True)) - { + if(mod_smbpwd_entry(smb_pwent,True) == False) { slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", - unix_name); + pwd->pw_name); + endsmbpwent(vp); return False; } + endsmbpwent(vp); + return True; } diff --git a/source3/passdb/smbpassfile.c b/source3/passdb/smbpassfile.c index 7a73bf5932..bbe24131b8 100644 --- a/source3/passdb/smbpassfile.c +++ b/source3/passdb/smbpassfile.c @@ -22,8 +22,51 @@ extern int DEBUGLEVEL; BOOL global_machine_password_needs_changing = False; -static int mach_passwd_lock_depth = 0; -static FILE *mach_passwd_fp = NULL; + +/*************************************************************** + Lock an fd. Abandon after waitsecs seconds. +****************************************************************/ + +BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth) +{ + if (fd < 0) + return False; + + if(*plock_depth == 0) { + if (!do_file_lock(fd, secs, type)) { + DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n", + strerror(errno))); + return False; + } + } + + (*plock_depth)++; + + return True; +} + +/*************************************************************** + Unlock an fd. Abandon after waitsecs seconds. +****************************************************************/ + +BOOL pw_file_unlock(int fd, int *plock_depth) +{ + BOOL ret=True; + + if(*plock_depth == 1) + ret = do_file_lock(fd, 5, F_UNLCK); + + if (*plock_depth > 0) + (*plock_depth)--; + + if(!ret) + DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n", + strerror(errno))); + return ret; +} + +static int mach_passwd_lock_depth; +static FILE *mach_passwd_fp; /************************************************************************ Routine to get the name for a trust account file. @@ -43,7 +86,7 @@ static void get_trust_account_file_name( char *domain, char *name, char *mac_fil if ((int)(sizeof(pstring) - mac_file_len - strlen(domain) - strlen(name) - 6) < 0) { - DEBUG(0,("get_trust_account_file_name: path %s too long to add trust details.\n", + DEBUG(0,("trust_password_lock: path %s too long to add trust details.\n", mac_file)); return; } @@ -52,8 +95,6 @@ static void get_trust_account_file_name( char *domain, char *name, char *mac_fil pstrcat(mac_file, "."); pstrcat(mac_file, name); pstrcat(mac_file, ".mac"); - - DEBUG(5,("trust_account_file_name: %s\n", mac_file)); } /************************************************************************ @@ -82,7 +123,7 @@ BOOL trust_password_lock( char *domain, char *name, BOOL update) chmod(mac_file, 0600); - if(!file_lock(fileno(mach_passwd_fp), (update ? F_WRLCK : F_RDLCK), + if(!pw_file_lock(fileno(mach_passwd_fp), (update ? F_WRLCK : F_RDLCK), 60, &mach_passwd_lock_depth)) { DEBUG(0,("trust_password_lock: cannot lock file %s\n", mac_file)); @@ -101,7 +142,7 @@ BOOL trust_password_lock( char *domain, char *name, BOOL update) BOOL trust_password_unlock(void) { - BOOL ret = file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth); + BOOL ret = pw_file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth); if(mach_passwd_lock_depth == 0) fclose(mach_passwd_fp); return ret; @@ -158,7 +199,7 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t if(strlen(linebuf) != 45) { DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \ -- was %d, should be 45).\n", strlen(linebuf))); +- was %d, should be 45).\n", (int)strlen(linebuf))); #ifdef DEBUG_PASSWORD DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf)); #endif @@ -169,7 +210,7 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t * Get the hex password. */ - if (!pwdb_gethexpwd((char *)linebuf, (char *)ret_pwd, NULL) || linebuf[32] != ':' || + if (!pdb_gethexpwd((char *)linebuf, ret_pwd) || linebuf[32] != ':' || strncmp(&linebuf[33], "TLC-", 4)) { DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n")); #ifdef DEBUG_PASSWORD @@ -240,17 +281,17 @@ BOOL trust_get_passwd( unsigned char trust_passwd[16], char *domain, char *mynam time_t lct; /* - * Get the trust account password. + * Get the machine account password. */ if(!trust_password_lock( domain, myname, False)) { - DEBUG(0,("trust_get_passwd: unable to open the trust account password file for \ -trust %s in domain %s.\n", myname, domain )); + DEBUG(0,("domain_client_validate: unable to open the machine account password file for \ +machine %s in domain %s.\n", myname, domain )); return False; } if(get_trust_account_password( trust_passwd, &lct) == False) { - DEBUG(0,("trust_get_passwd: unable to read the trust account password for \ -trust %s in domain %s.\n", myname, domain )); + DEBUG(0,("domain_client_validate: unable to read the machine account password for \ +machine %s in domain %s.\n", myname, domain )); trust_password_unlock(); return False; } @@ -258,7 +299,7 @@ trust %s in domain %s.\n", myname, domain )); trust_password_unlock(); /* - * Here we check the last change time to see if the trust + * Here we check the last change time to see if the machine * password needs changing. JRA. */ @@ -268,36 +309,3 @@ trust %s in domain %s.\n", myname, domain )); } return True; } - -/********************************************************* -record Trust Account password. -**********************************************************/ -BOOL create_trust_account_file(char *domain, char *name, uchar pass[16]) -{ - /* - * Create the machine account password file. - */ - - if (!trust_password_lock( domain, name, True)) - { - DEBUG(0,("unable to open the trust account password file for \ -account %s in domain %s.\n", name, domain)); - return False; - } - - /* - * Write the old machine account password. - */ - - if (!set_trust_account_password( pass)) - { - DEBUG(0,("unable to write the trust account password for \ -%s in domain %s.\n", name, domain)); - trust_password_unlock(); - return False; - } - - trust_password_unlock(); - - return True; -} diff --git a/source3/passdb/smbpassgroup.c b/source3/passdb/smbpassgroup.c index 8991cad978..4636c08c94 100644 --- a/source3/passdb/smbpassgroup.c +++ b/source3/passdb/smbpassgroup.c @@ -19,7 +19,7 @@ #include "includes.h" -#ifdef USE_SMBGROUP_DB +#ifdef USE_SMBPASS_DB static int grp_file_lock_depth = 0; extern int DEBUGLEVEL; @@ -32,7 +32,7 @@ extern int DEBUGLEVEL; static void *startsmbfilegrpent(BOOL update) { static char s_readbuf[1024]; - return startfileent(lp_smb_passgrp_file(), s_readbuf, sizeof(s_readbuf), + return startfilepwent(lp_smb_passgrp_file(), s_readbuf, sizeof(s_readbuf), &grp_file_lock_depth, update); } @@ -42,7 +42,7 @@ static void *startsmbfilegrpent(BOOL update) static void endsmbfilegrpent(void *vp) { - endfileent(vp, &grp_file_lock_depth); + endfilepwent(vp, &grp_file_lock_depth); } /************************************************************************* @@ -77,8 +77,9 @@ static struct smb_passwd *getsmbfilegrpent(void *vp, static pstring user_name; struct passwd *pwfile; pstring linebuf; - char *p; + unsigned char *p; int uidval; + size_t linebuf_len; if (vp == NULL) { @@ -91,12 +92,12 @@ static struct smb_passwd *getsmbfilegrpent(void *vp, /* * Scan the file, a line at a time. */ - while (getfileline(vp, linebuf, sizeof(linebuf)) > 0) + while ((linebuf_len = getfileline(vp, linebuf, sizeof(linebuf))) > 0) { /* * The line we have should be of the form :- * - * username:uid:aliasrid1,aliasrid2..:domainrid1,domainrid2..: + * username:uid:domainrid1,domainrid2..:aliasrid1,aliasrid2..: */ /* @@ -105,12 +106,6 @@ static struct smb_passwd *getsmbfilegrpent(void *vp, */ p = strncpyn(user_name, linebuf, sizeof(user_name), ':'); - if (p == NULL) - { - DEBUG(0,("getsmbfilegrpent: no ':' separator found\n")); - continue; - } - /* Go past ':' */ p++; @@ -119,42 +114,48 @@ static struct smb_passwd *getsmbfilegrpent(void *vp, p = Atoic((char *) p, &uidval, ":"); pw_buf.smb_name = user_name; - pw_buf.unix_uid = uidval; + pw_buf.smb_userid = uidval; /* - * Now get a list of alias RIDs + * Now get the password value - this should be 32 hex digits + * which are the ascii representations of a 16 byte string. + * Get two at a time and put them into the password. */ /* Skip the ':' */ p++; - if (als_rids != NULL && num_alss != NULL) + if (grp_rids != NULL && num_grps != NULL) { int i; - p = get_numlist(p, als_rids, num_alss); + p = get_numlist(p, grp_rids, num_grps); if (p == NULL) { DEBUG(0,("getsmbfilegrpent: invalid line\n")); return NULL; } + for (i = 0; i < (*num_grps); i++) + { + (*grp_rids)[i] = pwdb_gid_to_group_rid((*grp_rids)[i]); + } } - /* - * Now get a list of group RIDs - */ - /* Skip the ':' */ p++; - if (grp_rids != NULL && num_grps != NULL) + if (als_rids != NULL && num_alss != NULL) { int i; - p = get_numlist(p, grp_rids, num_grps); + p = get_numlist(p, als_rids, num_alss); if (p == NULL) { DEBUG(0,("getsmbfilegrpent: invalid line\n")); return NULL; } + for (i = 0; i < (*num_alss); i++) + { + (*als_rids)[i] = pwdb_gid_to_alias_rid((*als_rids)[i]); + } } pwfile = Get_Pwnam(pw_buf.smb_name, False); @@ -191,5 +192,5 @@ struct passgrp_ops *file_initialise_password_grp(void) #else /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */ - void smbpassgroup_dummy_function(void) { } /* stop some compilers complaining */ + void smbpass_dummy_function(void) { } /* stop some compilers complaining */ #endif /* USE_SMBPASS_DB */ |