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.
22 extern int DEBUGLEVEL;
24 BOOL global_machine_password_needs_changing = False;
25 static int mach_passwd_lock_depth = 0;
26 static FILE *mach_passwd_fp = NULL;
28 /************************************************************************
29 Routine to get the name for a trust account file.
30 ************************************************************************/
32 static void get_trust_account_file_name( char *domain, char *name, char *mac_file)
34 unsigned int mac_file_len;
37 pstrcpy(mac_file, lp_smb_passwd_file());
38 p = strrchr(mac_file, '/');
42 mac_file_len = strlen(mac_file);
44 if ((int)(sizeof(pstring) - mac_file_len - strlen(domain) - strlen(name) - 6) < 0)
46 DEBUG(0,("get_trust_account_file_name: path %s too long to add trust details.\n",
51 pstrcat(mac_file, domain);
52 pstrcat(mac_file, ".");
53 pstrcat(mac_file, name);
54 pstrcat(mac_file, ".mac");
56 DEBUG(5,("trust_account_file_name: %s\n", mac_file));
59 /************************************************************************
60 Routine to lock the trust account password file for a domain.
61 ************************************************************************/
63 BOOL trust_password_lock( char *domain, char *name, BOOL update)
67 if(mach_passwd_lock_depth == 0) {
69 get_trust_account_file_name( domain, name, mac_file);
71 if((mach_passwd_fp = sys_fopen(mac_file, "r+b")) == NULL) {
72 if(errno == ENOENT && update) {
73 mach_passwd_fp = sys_fopen(mac_file, "w+b");
76 if(mach_passwd_fp == NULL) {
77 DEBUG(0,("trust_password_lock: cannot open file %s - Error was %s.\n",
78 mac_file, strerror(errno) ));
83 chmod(mac_file, 0600);
85 if(!file_lock(fileno(mach_passwd_fp), (update ? F_WRLCK : F_RDLCK),
86 60, &mach_passwd_lock_depth))
88 DEBUG(0,("trust_password_lock: cannot lock file %s\n", mac_file));
89 fclose(mach_passwd_fp);
98 /************************************************************************
99 Routine to unlock the trust account password file for a domain.
100 ************************************************************************/
102 BOOL trust_password_unlock(void)
104 BOOL ret = file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth);
105 if(mach_passwd_lock_depth == 0)
106 fclose(mach_passwd_fp);
110 /************************************************************************
111 Routine to delete the trust account password file for a domain.
112 ************************************************************************/
114 BOOL trust_password_delete( char *domain, char *name )
118 get_trust_account_file_name( domain, name, mac_file);
119 return (unlink( mac_file ) == 0);
122 /************************************************************************
123 Routine to get the trust account password for a domain.
124 The user of this function must have locked the trust password file.
125 ************************************************************************/
127 BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_time)
135 *pass_last_set_time = (time_t)0;
136 memset(ret_pwd, '\0', 16);
138 if(sys_fseek( mach_passwd_fp, (SMB_OFF_T)0, SEEK_SET) == -1) {
139 DEBUG(0,("get_trust_account_password: Failed to seek to start of file. Error was %s.\n",
144 fgets(linebuf, sizeof(linebuf), mach_passwd_fp);
145 if(ferror(mach_passwd_fp)) {
146 DEBUG(0,("get_trust_account_password: Failed to read password. Error was %s.\n",
151 if(linebuf[strlen(linebuf)-1] == '\n')
152 linebuf[strlen(linebuf)-1] = '\0';
155 * The length of the line read
156 * must be 45 bytes ( <---XXXX 32 bytes-->:TLC-12345678
159 if(strlen(linebuf) != 45) {
160 DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \
161 - was %d, should be 45).\n", strlen(linebuf)));
162 #ifdef DEBUG_PASSWORD
163 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
169 * Get the hex password.
172 if (!pwdb_gethexpwd((char *)linebuf, (char *)ret_pwd, NULL) || linebuf[32] != ':' ||
173 strncmp(&linebuf[33], "TLC-", 4)) {
174 DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n"));
175 #ifdef DEBUG_PASSWORD
176 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
182 * Get the last changed time.
186 for(i = 0; i < 8; i++) {
187 if(p[i] == '\0' || !isxdigit((int)p[i])) {
188 DEBUG(0,("get_trust_account_password: Malformed trust password file (no timestamp).\n"));
189 #ifdef DEBUG_PASSWORD
190 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
197 * p points at 8 characters of hex digits -
198 * read into a time_t as the seconds since
199 * 1970 that the password was last changed.
202 *pass_last_set_time = (time_t)strtol(p, NULL, 16);
207 /************************************************************************
208 Routine to get the trust account password for a domain.
209 The user of this function must have locked the trust password file.
210 ************************************************************************/
212 BOOL set_trust_account_password( unsigned char *md4_new_pwd)
217 if(sys_fseek( mach_passwd_fp, (SMB_OFF_T)0, SEEK_SET) == -1) {
218 DEBUG(0,("set_trust_account_password: Failed to seek to start of file. Error was %s.\n",
223 for (i = 0; i < 16; i++)
224 slprintf(&linebuf[(i*2)], sizeof(linebuf) - (i*2) - 1, "%02X", md4_new_pwd[i]);
226 slprintf(&linebuf[32], 32, ":TLC-%08X\n", (unsigned)time(NULL));
228 if(fwrite( linebuf, 1, 46, mach_passwd_fp)!= 46) {
229 DEBUG(0,("set_trust_account_password: Failed to write file. Warning - the trust \
230 account is now invalid. Please recreate. Error was %s.\n", strerror(errno) ));
234 fflush(mach_passwd_fp);
238 BOOL trust_get_passwd( unsigned char trust_passwd[16], char *domain, char *myname)
243 * Get the trust account password.
245 if(!trust_password_lock( domain, myname, False)) {
246 DEBUG(0,("trust_get_passwd: unable to open the trust account password file for \
247 trust %s in domain %s.\n", myname, domain ));
251 if(get_trust_account_password( trust_passwd, &lct) == False) {
252 DEBUG(0,("trust_get_passwd: unable to read the trust account password for \
253 trust %s in domain %s.\n", myname, domain ));
254 trust_password_unlock();
258 trust_password_unlock();
261 * Here we check the last change time to see if the trust
262 * password needs changing. JRA.
265 if(time(NULL) > lct + lp_machine_password_timeout())
267 global_machine_password_needs_changing = True;
272 /*********************************************************
273 record Trust Account password.
274 **********************************************************/
275 BOOL create_trust_account_file(char *domain, char *name, uchar pass[16])
278 * Create the machine account password file.
281 if (!trust_password_lock( domain, name, True))
283 DEBUG(0,("unable to open the trust account password file for \
284 account %s in domain %s.\n", name, domain));
289 * Write the old machine account password.
292 if (!set_trust_account_password( pass))
294 DEBUG(0,("unable to write the trust account password for \
295 %s in domain %s.\n", name, domain));
296 trust_password_unlock();
300 trust_password_unlock();