2 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 675
17 * Mass Ave, Cambridge, MA 02139, USA.
21 * This file also contains migration code to move from an old
22 * trust account password file stored in the file :
23 * ${SAMBA_HOME}/private/{domain}.{netbiosname}.mac
24 * into a record stored in the tdb ${SAMBA_HOME}/private/secrets.tdb
30 extern int DEBUGLEVEL
;
31 extern pstring global_myname
;
33 BOOL global_machine_password_needs_changing
= False
;
36 static int mach_passwd_lock_depth
;
37 static FILE *mach_passwd_fp
;
39 /***************************************************************
40 Lock an fd. Abandon after waitsecs seconds.
41 ****************************************************************/
43 static BOOL
pw_file_lock(int fd
, int type
, int secs
, int *plock_depth
)
48 if(*plock_depth
== 0) {
49 if (!do_file_lock(fd
, secs
, type
)) {
50 DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
61 /***************************************************************
62 Unlock an fd. Abandon after waitsecs seconds.
63 ****************************************************************/
65 static BOOL
pw_file_unlock(int fd
, int *plock_depth
)
70 ret
= do_file_lock(fd
, 5, F_UNLCK
);
76 DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
81 /************************************************************************
82 Routine to get the name for an old trust account file.
83 ************************************************************************/
85 static void get_trust_account_file_name( char *domain
, char *name
, char *mac_file
)
87 unsigned int mac_file_len
;
89 pstrcpy(mac_file
, lp_private_dir());
90 if (mac_file
[strlen(mac_file
)-1] != '/')
91 pstrcat (mac_file
, "/");
93 mac_file_len
= strlen(mac_file
);
95 if ((int)(sizeof(pstring
) - mac_file_len
- strlen(domain
) - strlen(name
) - 6) < 0)
97 DEBUG(0,("trust_password_lock: path %s too long to add trust details.\n",
102 pstrcat(mac_file
, domain
);
103 pstrcat(mac_file
, ".");
104 pstrcat(mac_file
, name
);
105 pstrcat(mac_file
, ".mac");
108 /************************************************************************
109 Routine to lock the old trust account password file for a domain.
110 As this is a function to migrate to the new secrets.tdb, we never
111 create the file here, only open it.
112 ************************************************************************/
114 static BOOL
trust_password_file_lock(char *domain
, char *name
)
118 if(mach_passwd_lock_depth
== 0) {
121 get_trust_account_file_name( domain
, name
, mac_file
);
123 if ((fd
= sys_open(mac_file
, O_RDWR
, 0)) == -1)
126 if((mach_passwd_fp
= fdopen(fd
, "w+b")) == NULL
) {
127 DEBUG(0,("trust_password_lock: cannot open file %s - Error was %s.\n",
128 mac_file
, strerror(errno
) ));
132 if(!pw_file_lock(fileno(mach_passwd_fp
), F_WRLCK
, 60, &mach_passwd_lock_depth
)) {
133 DEBUG(0,("trust_password_lock: cannot lock file %s\n", mac_file
));
134 fclose(mach_passwd_fp
);
143 /************************************************************************
144 Routine to unlock the old trust account password file for a domain.
145 ************************************************************************/
147 static BOOL
trust_password_file_unlock(void)
149 BOOL ret
= pw_file_unlock(fileno(mach_passwd_fp
), &mach_passwd_lock_depth
);
150 if(mach_passwd_lock_depth
== 0)
151 fclose(mach_passwd_fp
);
155 /************************************************************************
156 Routine to delete the old trust account password file for a domain.
157 Note that this file must be locked as it is truncated before the
158 delete. This is to ensure it only gets deleted by one smbd.
159 ************************************************************************/
161 static BOOL
trust_password_file_delete( char *domain
, char *name
)
166 get_trust_account_file_name( domain
, name
, mac_file
);
167 if(sys_ftruncate(fileno(mach_passwd_fp
),(SMB_OFF_T
)0) == -1) {
168 DEBUG(0,("trust_password_file_delete: Failed to truncate file %s (%s)\n",
169 mac_file
, strerror(errno
) ));
171 ret
= unlink( mac_file
);
175 /************************************************************************
176 Routine to get the old trust account password for a domain - to convert
177 to the new secrets.tdb entry.
178 The user of this function must have locked the trust password file.
179 ************************************************************************/
181 static BOOL
get_trust_account_password_from_file( unsigned char *ret_pwd
, time_t *pass_last_set_time
)
189 *pass_last_set_time
= (time_t)0;
190 memset(ret_pwd
, '\0', 16);
192 if(sys_fstat(fileno(mach_passwd_fp
), &st
) == -1) {
193 DEBUG(0,("get_trust_account_password: Failed to stat file. Error was %s.\n",
199 * If size is zero, another smbd has migrated this file
200 * to the secrets.tdb file, and we are in a race condition.
201 * Just ignore the file.
207 if(sys_fseek( mach_passwd_fp
, (SMB_OFF_T
)0, SEEK_SET
) == -1) {
208 DEBUG(0,("get_trust_account_password: Failed to seek to start of file. Error was %s.\n",
213 fgets(linebuf
, sizeof(linebuf
), mach_passwd_fp
);
214 if(ferror(mach_passwd_fp
)) {
215 DEBUG(0,("get_trust_account_password: Failed to read password. Error was %s.\n",
220 if(linebuf
[strlen(linebuf
)-1] == '\n')
221 linebuf
[strlen(linebuf
)-1] = '\0';
224 * The length of the line read
225 * must be 45 bytes ( <---XXXX 32 bytes-->:TLC-12345678
228 if(strlen(linebuf
) != 45) {
229 DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \
230 - was %d, should be 45).\n", (int)strlen(linebuf
)));
231 #ifdef DEBUG_PASSWORD
232 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf
));
238 * Get the hex password.
241 if (!pdb_gethexpwd((char *)linebuf
, ret_pwd
) || linebuf
[32] != ':' ||
242 strncmp(&linebuf
[33], "TLC-", 4)) {
243 DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n"));
244 #ifdef DEBUG_PASSWORD
245 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf
));
251 * Get the last changed time.
255 for(i
= 0; i
< 8; i
++) {
256 if(p
[i
] == '\0' || !isxdigit((int)p
[i
])) {
257 DEBUG(0,("get_trust_account_password: Malformed trust password file (no timestamp).\n"));
258 #ifdef DEBUG_PASSWORD
259 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf
));
266 * p points at 8 characters of hex digits -
267 * read into a time_t as the seconds since
268 * 1970 that the password was last changed.
271 *pass_last_set_time
= (time_t)strtol(p
, NULL
, 16);
276 /************************************************************************
277 form a key for fetching a domain trust password
278 ************************************************************************/
280 static char *trust_keystr(char *domain
)
282 static fstring keystr
;
283 slprintf(keystr
,sizeof(keystr
),"%s/%s", SECRETS_MACHINE_ACCT_PASS
, domain
);
287 /************************************************************************
288 Migrate an old DOMAIN.MACINE.mac password file to the tdb secrets db.
289 ************************************************************************/
291 static void migrate_from_old_password_file(char *domain
)
293 struct machine_acct_pass pass
;
295 if (!trust_password_file_lock(domain
, global_myname
))
298 if (!get_trust_account_password_from_file( pass
.hash
, &pass
.mod_time
)) {
299 trust_password_file_unlock();
303 trust_password_file_delete(domain
, global_myname
);
305 secrets_store(trust_keystr(domain
), (void *)&pass
, sizeof(pass
));
307 trust_password_file_unlock();
311 /************************************************************************
312 Routine to delete the trust account password file for a domain.
313 ************************************************************************/
315 BOOL
trust_password_delete(char *domain
)
317 return secrets_delete(trust_keystr(domain
));