1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-29 21:47:30 +03:00
samba-mirror/source/passdb/smbpassfile.c

269 lines
7.8 KiB
C
Raw Normal View History

/*
* Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
* Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 675
* Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
extern int DEBUGLEVEL;
BOOL global_machine_password_needs_changing = False;
static int mach_passwd_lock_depth;
static FILE *mach_passwd_fp;
/************************************************************************
Routine to get the name for a trust account file.
************************************************************************/
static void get_trust_account_file_name( char *domain, char *name, char *mac_file)
{
unsigned int mac_file_len;
char *p;
pstrcpy(mac_file, lp_smb_passwd_file());
p = strrchr(mac_file, '/');
if(p != NULL)
*++p = '\0';
mac_file_len = strlen(mac_file);
if ((int)(sizeof(pstring) - mac_file_len - strlen(domain) - strlen(name) - 6) < 0)
{
DEBUG(0,("trust_password_lock: path %s too long to add trust details.\n",
mac_file));
return;
}
pstrcat(mac_file, domain);
pstrcat(mac_file, ".");
pstrcat(mac_file, name);
pstrcat(mac_file, ".mac");
}
/************************************************************************
Routine to lock the trust account password file for a domain.
************************************************************************/
BOOL trust_password_lock( char *domain, char *name, BOOL update)
{
pstring mac_file;
if(mach_passwd_lock_depth == 0) {
get_trust_account_file_name( domain, name, mac_file);
if((mach_passwd_fp = sys_fopen(mac_file, "r+b")) == NULL) {
if(errno == ENOENT && update) {
mach_passwd_fp = sys_fopen(mac_file, "w+b");
}
if(mach_passwd_fp == NULL) {
DEBUG(0,("trust_password_lock: cannot open file %s - Error was %s.\n",
mac_file, strerror(errno) ));
return False;
}
}
chmod(mac_file, 0600);
- group database API. oops and oh dear, the threat has been carried out: the pre-alpha "domain group" etc parameters have disappeared. - interactive debug detection - re-added mem_man (andrew's memory management, detects memory corruption) - american spellings of "initialise" replaced with english spelling of "initialise". - started on "lookup_name()" and "lookup_sid()" functions. proper ones. - moved lots of functions around. created some modules of commonly used code. e.g the password file locking code, which is used in groupfile.c and aliasfile.c and smbpass.c - moved RID_TYPE_MASK up another bit. this is really unfortunate, but there is no other "fast" way to identify users from groups from aliases. i do not believe that this code saves us anything (the multipliers) and puts us at a disadvantage (reduces the useable rid space). the designers of NT aren't silly: if they can get away with a user- interface-speed LsaLookupNames / LsaLookupSids, then so can we. i spoke with isaac at the cifs conference, the only time for example that they do a security context check is on file create. certainly not on individual file reads / writes, which would drastically hit their performance and ours, too. - renamed myworkgroup to global_sam_name, amongst other things, when used in the rpc code. there is also a global_member_name, as we are always responsible for a SAM database, the scope of which is limited by the role of the machine (e.g if a member of a workgroup, your SAM is for _local_ logins only, and its name is the name of your server. you even still have a SID. see LsaQueryInfoPolicy, levels 3 and 5). - updated functionality of groupname.c to be able to cope with names like DOMAIN\group and SERVER\alias. used this code to be able to do aliases as well as groups. this code may actually be better off being used in username mapping, too. - created a connect to serverlist function in clientgen.c and used it in password.c - initialisation in server.c depends on the role of the server. well, it does now. - rpctorture. smbtorture. EXERCISE EXTREME CAUTION.
-
if(!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));
fclose(mach_passwd_fp);
return False;
}
}
return True;
}
/************************************************************************
Routine to unlock the trust account password file for a domain.
************************************************************************/
BOOL trust_password_unlock(void)
{
- group database API. oops and oh dear, the threat has been carried out: the pre-alpha "domain group" etc parameters have disappeared. - interactive debug detection - re-added mem_man (andrew's memory management, detects memory corruption) - american spellings of "initialise" replaced with english spelling of "initialise". - started on "lookup_name()" and "lookup_sid()" functions. proper ones. - moved lots of functions around. created some modules of commonly used code. e.g the password file locking code, which is used in groupfile.c and aliasfile.c and smbpass.c - moved RID_TYPE_MASK up another bit. this is really unfortunate, but there is no other "fast" way to identify users from groups from aliases. i do not believe that this code saves us anything (the multipliers) and puts us at a disadvantage (reduces the useable rid space). the designers of NT aren't silly: if they can get away with a user- interface-speed LsaLookupNames / LsaLookupSids, then so can we. i spoke with isaac at the cifs conference, the only time for example that they do a security context check is on file create. certainly not on individual file reads / writes, which would drastically hit their performance and ours, too. - renamed myworkgroup to global_sam_name, amongst other things, when used in the rpc code. there is also a global_member_name, as we are always responsible for a SAM database, the scope of which is limited by the role of the machine (e.g if a member of a workgroup, your SAM is for _local_ logins only, and its name is the name of your server. you even still have a SID. see LsaQueryInfoPolicy, levels 3 and 5). - updated functionality of groupname.c to be able to cope with names like DOMAIN\group and SERVER\alias. used this code to be able to do aliases as well as groups. this code may actually be better off being used in username mapping, too. - created a connect to serverlist function in clientgen.c and used it in password.c - initialisation in server.c depends on the role of the server. well, it does now. - rpctorture. smbtorture. EXERCISE EXTREME CAUTION.
-
BOOL ret = file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth);
if(mach_passwd_lock_depth == 0)
fclose(mach_passwd_fp);
return ret;
}
/************************************************************************
Routine to delete the trust account password file for a domain.
************************************************************************/
BOOL trust_password_delete( char *domain, char *name )
{
pstring mac_file;
get_trust_account_file_name( domain, name, mac_file);
return (unlink( mac_file ) == 0);
}
/************************************************************************
Routine to get the trust account password for a domain.
The user of this function must have locked the trust password file.
************************************************************************/
BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_time)
{
char linebuf[256];
char *p;
int i;
linebuf[0] = '\0';
*pass_last_set_time = (time_t)0;
memset(ret_pwd, '\0', 16);
if(sys_fseek( mach_passwd_fp, (SMB_OFF_T)0, SEEK_SET) == -1) {
DEBUG(0,("get_trust_account_password: Failed to seek to start of file. Error was %s.\n",
strerror(errno) ));
return False;
}
fgets(linebuf, sizeof(linebuf), mach_passwd_fp);
if(ferror(mach_passwd_fp)) {
DEBUG(0,("get_trust_account_password: Failed to read password. Error was %s.\n",
strerror(errno) ));
return False;
}
if(linebuf[strlen(linebuf)-1] == '\n')
linebuf[strlen(linebuf)-1] = '\0';
/*
* The length of the line read
* must be 45 bytes ( <---XXXX 32 bytes-->:TLC-12345678
*/
if(strlen(linebuf) != 45) {
DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \
- was %d, should be 45).\n", strlen(linebuf)));
#ifdef DEBUG_PASSWORD
DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
#endif
return False;
}
/*
* Get the hex password.
*/
- group database API. oops and oh dear, the threat has been carried out: the pre-alpha "domain group" etc parameters have disappeared. - interactive debug detection - re-added mem_man (andrew's memory management, detects memory corruption) - american spellings of "initialise" replaced with english spelling of "initialise". - started on "lookup_name()" and "lookup_sid()" functions. proper ones. - moved lots of functions around. created some modules of commonly used code. e.g the password file locking code, which is used in groupfile.c and aliasfile.c and smbpass.c - moved RID_TYPE_MASK up another bit. this is really unfortunate, but there is no other "fast" way to identify users from groups from aliases. i do not believe that this code saves us anything (the multipliers) and puts us at a disadvantage (reduces the useable rid space). the designers of NT aren't silly: if they can get away with a user- interface-speed LsaLookupNames / LsaLookupSids, then so can we. i spoke with isaac at the cifs conference, the only time for example that they do a security context check is on file create. certainly not on individual file reads / writes, which would drastically hit their performance and ours, too. - renamed myworkgroup to global_sam_name, amongst other things, when used in the rpc code. there is also a global_member_name, as we are always responsible for a SAM database, the scope of which is limited by the role of the machine (e.g if a member of a workgroup, your SAM is for _local_ logins only, and its name is the name of your server. you even still have a SID. see LsaQueryInfoPolicy, levels 3 and 5). - updated functionality of groupname.c to be able to cope with names like DOMAIN\group and SERVER\alias. used this code to be able to do aliases as well as groups. this code may actually be better off being used in username mapping, too. - created a connect to serverlist function in clientgen.c and used it in password.c - initialisation in server.c depends on the role of the server. well, it does now. - rpctorture. smbtorture. EXERCISE EXTREME CAUTION.
-
if (!pwdb_gethexpwd((char *)linebuf, (char *)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
DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
#endif
return False;
}
/*
* Get the last changed time.
*/
p = &linebuf[37];
for(i = 0; i < 8; i++) {
configure: Changes for extra headers. configure.in: Source for header changes. client/clitar.c: Fixed isXXX macros & debugs for gcc pedantic compile. include/config.h.in: Added MEMSET, BZERO, MEMORY, RPCSVC_YPCLNT, STRINGS headers. include/includes.h: Headers for the above. include/smb.h: Made SIGNAL_CAST POSIX by default void (*)(int). lib/access.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/charset.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/debug.c: Fixed signal functs. lib/kanji.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/smbrun.c: Fixed isXXX macros & debugs for gcc pedantic compile. lib/util.c: Fixed isXXX macros & debugs for gcc pedantic compile. libsmb/namequery.c: Fixed isXXX macros & debugs for gcc pedantic compile. locking/shmem.c: Fixed isXXX macros & debugs for gcc pedantic compile. locking/shmem_sysv.c: Fixed error messages in sysV stuff. nmbd/asyncdns.c: Fixed signal functs. nmbd/nmbd.c: Fixed isXXX macros & debugs for gcc pedantic compile. passdb/passdb.c: Fixed isXXX macros & debugs for gcc pedantic compile. passdb/smbpassfile.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/chgpasswd.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/ipc.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/nttrans.c: Fixed fsp code path. smbd/password.c: fixed HAVE_YP_GET_DEFAULT_DOMAIN problem. smbd/printing.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/reply.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/server.c: Fixed isXXX macros & debugs for gcc pedantic compile. smbd/trans2.c: Fixed core dump bug. smbd/uid.c: Fixed isXXX macros & debugs for gcc pedantic compile. Jeremy.
-
if(p[i] == '\0' || !isxdigit((int)p[i])) {
DEBUG(0,("get_trust_account_password: Malformed trust password file (no timestamp).\n"));
#ifdef DEBUG_PASSWORD
DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
#endif
return False;
}
}
/*
* p points at 8 characters of hex digits -
* read into a time_t as the seconds since
* 1970 that the password was last changed.
*/
*pass_last_set_time = (time_t)strtol(p, NULL, 16);
return True;
}
/************************************************************************
Routine to get the trust account password for a domain.
The user of this function must have locked the trust password file.
************************************************************************/
BOOL set_trust_account_password( unsigned char *md4_new_pwd)
{
char linebuf[64];
int i;
if(sys_fseek( mach_passwd_fp, (SMB_OFF_T)0, SEEK_SET) == -1) {
DEBUG(0,("set_trust_account_password: Failed to seek to start of file. Error was %s.\n",
strerror(errno) ));
return False;
}
for (i = 0; i < 16; i++)
slprintf(&linebuf[(i*2)], sizeof(linebuf) - (i*2) - 1, "%02X", md4_new_pwd[i]);
slprintf(&linebuf[32], 32, ":TLC-%08X\n", (unsigned)time(NULL));
if(fwrite( linebuf, 1, 46, mach_passwd_fp)!= 46) {
DEBUG(0,("set_trust_account_password: Failed to write file. Warning - the trust \
account is now invalid. Please recreate. Error was %s.\n", strerror(errno) ));
return False;
}
fflush(mach_passwd_fp);
return True;
}
BOOL trust_get_passwd( unsigned char trust_passwd[16], char *domain, char *myname)
{
time_t lct;
/*
* Get the machine account password.
*/
if(!trust_password_lock( domain, myname, False)) {
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,("domain_client_validate: unable to read the machine account password for \
machine %s in domain %s.\n", myname, domain ));
trust_password_unlock();
return False;
}
trust_password_unlock();
/*
* Here we check the last change time to see if the machine
* password needs changing. JRA.
*/
if(time(NULL) > lct + lp_machine_password_timeout())
{
global_machine_password_needs_changing = True;
}
return True;
}