#include "includes.h"
extern pstring global_myname;
static int mach_passwd_lock_depth;
static FILE *mach_passwd_fp;
static 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;
}
static 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 void get_trust_account_file_name( char *domain, char *name, char *mac_file)
{
unsigned int mac_file_len;
get_private_directory(mac_file);
pstrcat(mac_file, "/");
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");
}
static BOOL trust_password_file_lock(char *domain, char *name)
{
pstring mac_file;
if(mach_passwd_lock_depth == 0) {
int fd;
get_trust_account_file_name( domain, name, mac_file);
if ((fd = sys_open(mac_file, O_RDWR, 0)) == -1)
return False;
if((mach_passwd_fp = fdopen(fd, "w+b")) == NULL) {
DEBUG(0,("trust_password_lock: cannot open file %s - Error was %s.\n",
mac_file, strerror(errno) ));
return False;
}
if(!pw_file_lock(fileno(mach_passwd_fp), F_WRLCK, 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;
}
static BOOL trust_password_file_unlock(void)
{
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;
}
static BOOL trust_password_file_delete( char *domain, char *name )
{
pstring mac_file;
int ret;
get_trust_account_file_name( domain, name, mac_file);
if(sys_ftruncate(fileno(mach_passwd_fp),(SMB_OFF_T)0) == -1) {
DEBUG(0,("trust_password_file_delete: Failed to truncate file %s (%s)\n",
mac_file, strerror(errno) ));
}
ret = unlink( mac_file );
return (ret != -1);
}
static BOOL get_trust_account_password_from_file( unsigned char *ret_pwd, time_t *pass_last_set_time)
{
char linebuf[256];
char *p;
int i;
SMB_STRUCT_STAT st;
linebuf[0] = '\0';
*pass_last_set_time = (time_t)0;
memset(ret_pwd, '\0', 16);
if(sys_fstat(fileno(mach_passwd_fp), &st) == -1) {
DEBUG(0,("get_trust_account_password: Failed to stat file. Error was %s.\n",
strerror(errno) ));
return False;
}
if (st.st_size == 0)
return False;
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';
if(strlen(linebuf) != 45) {
DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \
- was %d, should be 45).\n", (int)strlen(linebuf)));
#ifdef DEBUG_PASSWORD
DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
#endif
return False;
}
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
DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
#endif
return False;
}
p = &linebuf[37];
for(i = 0; i < 8; i++) {
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;
}
}
*pass_last_set_time = (time_t)strtol(p, NULL, 16);
return True;
}
BOOL migrate_from_old_password_file(char *domain)
{
struct machine_acct_pass pass;
if (!trust_password_file_lock(domain, global_myname))
return True;
if (!get_trust_account_password_from_file( pass.hash, &pass.mod_time)) {
trust_password_file_unlock();
return False;
}
if (!secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass)))
return False;
trust_password_file_delete(domain, global_myname);
trust_password_file_unlock();
return True;
}