* Mass Ave, Cambridge, MA 02139, USA.
*/
+/*
+ * This file also contains migration code to move from an old
+ * trust account password file stored in the file :
+ * ${SAMBA_HOME}/private/{domain}.{netbiosname}.mac
+ * into a record stored in the tdb ${SAMBA_HOME}/private/secrets.tdb
+ * database. JRA.
+ */
+
#include "includes.h"
extern int DEBUGLEVEL;
+extern pstring global_myname;
BOOL global_machine_password_needs_changing = False;
+
+
static int mach_passwd_lock_depth;
static FILE *mach_passwd_fp;
+/***************************************************************
+ Lock an fd. Abandon after waitsecs seconds.
+****************************************************************/
+
+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;
+}
+
+/***************************************************************
+ Unlock an fd. Abandon after waitsecs seconds.
+****************************************************************/
+
+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;
+}
+
/************************************************************************
- Routine to get the name for a trust account file.
+ Routine to get the name for an old 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';
+ pstrcpy(mac_file, lp_private_dir());
+ if (mac_file[strlen(mac_file)-1] != '/')
+ pstrcat (mac_file, "/");
mac_file_len = strlen(mac_file);
}
/************************************************************************
- Routine to lock the trust account password file for a domain.
+ Routine to lock the old trust account password file for a domain.
+ As this is a function to migrate to the new secrets.tdb, we never
+ create the file here, only open it.
************************************************************************/
-BOOL trust_password_lock( char *domain, char *name, BOOL update)
+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((mach_passwd_fp = sys_fopen(mac_file, "r+b")) == NULL) {
- if(errno == ENOENT && update) {
- mach_passwd_fp = sys_fopen(mac_file, "w+b");
- }
+ if ((fd = sys_open(mac_file, O_RDWR, 0)) == -1)
+ return False;
- if(mach_passwd_fp == NULL) {
+ 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;
- }
}
- chmod(mac_file, 0600);
-
- if(!file_lock(fileno(mach_passwd_fp), (update ? F_WRLCK : F_RDLCK),
- 60, &mach_passwd_lock_depth))
- {
+ 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;
}
/************************************************************************
- Routine to unlock the trust account password file for a domain.
+ Routine to unlock the old trust account password file for a domain.
************************************************************************/
-BOOL trust_password_unlock(void)
+static BOOL trust_password_file_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;
}
/************************************************************************
- Routine to delete the trust account password file for a domain.
+ Routine to delete the old trust account password file for a domain.
+ Note that this file must be locked as it is truncated before the
+ delete. This is to ensure it only gets deleted by one smbd.
************************************************************************/
-BOOL trust_password_delete( char *domain, char *name )
+static BOOL trust_password_file_delete( char *domain, char *name )
{
pstring mac_file;
+ int ret;
get_trust_account_file_name( domain, name, mac_file);
- return (unlink( mac_file ) == 0);
+ 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);
}
/************************************************************************
- Routine to get the trust account password for a domain.
+ Routine to get the old trust account password for a domain - to convert
+ to the new secrets.tdb entry.
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)
+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 size is zero, another smbd has migrated this file
+ * to the secrets.tdb file, and we are in a race condition.
+ * Just ignore the file.
+ */
+
+ 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) ));
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
* 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
}
/************************************************************************
- Routine to get the trust account password for a domain.
- The user of this function must have locked the trust password file.
+ Migrate an old DOMAIN.MACINE.mac password file to the tdb secrets db.
************************************************************************/
-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)
+BOOL migrate_from_old_password_file(char *domain)
{
- time_t lct;
+ struct machine_acct_pass pass;
- /*
- * Get the trust account password.
- */
- if(!trust_password_lock( domain, myname, False)) {
- DEBUG(0,("domain_client_validate: unable to open the trust account password file for \
-trust %s in domain %s.\n", myname, domain ));
- return False;
- }
+ if (!trust_password_file_lock(domain, global_myname))
+ return True;
- if(get_trust_account_password( trust_passwd, &lct) == False) {
- DEBUG(0,("domain_client_validate: unable to read the trust account password for \
-trust %s in domain %s.\n", myname, domain ));
- trust_password_unlock();
- return False;
- }
+ if (!get_trust_account_password_from_file( pass.hash, &pass.mod_time)) {
+ trust_password_file_unlock();
+ return False;
+ }
- trust_password_unlock();
+ if (!secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass)))
+ return False;
- /*
- * Here we check the last change time to see if the trust
- * password needs changing. JRA.
- */
+ trust_password_file_delete(domain, global_myname);
+ trust_password_file_unlock();
- if(time(NULL) > lct + lp_machine_password_timeout())
- {
- global_machine_password_needs_changing = True;
- }
- return True;
+ return True;
}