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;
26 /***************************************************************
27 Signal function to tell us we timed out.
28 ****************************************************************/
29 static void gotalarm_sig(void)
34 /***************************************************************
35 Lock or unlock a fd for a known lock type. Abandon after waitsecs
37 ****************************************************************/
38 BOOL do_file_lock(int fd, int waitsecs, int type)
44 signal(SIGALRM, SIGNAL_CAST gotalarm_sig);
47 lock.l_whence = SEEK_SET;
53 ret = fcntl(fd, F_SETLKW, &lock);
55 signal(SIGALRM, SIGNAL_CAST SIG_DFL);
58 DEBUG(0, ("do_file_lock: failed to %s file.\n",
59 type == F_UNLCK ? "unlock" : "lock"));
66 static int pw_file_lock_depth;
68 /***************************************************************
69 Lock an fd. Abandon after waitsecs seconds.
70 ****************************************************************/
71 BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
78 if(pw_file_lock_depth == 0) {
79 if (!do_file_lock(fd, secs, type)) {
80 DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
89 /***************************************************************
90 Unlock an fd. Abandon after waitsecs seconds.
91 ****************************************************************/
92 BOOL pw_file_unlock(int fd, int *plock_depth)
97 ret = do_file_lock(fd, 5, F_UNLCK);
102 DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
107 static int mach_passwd_lock_depth;
108 static FILE *mach_passwd_fp;
110 /************************************************************************
111 Routine to get the name for a trust account file.
112 ************************************************************************/
113 static void get_trust_account_file_name( char *domain, char *name, char *mac_file)
115 unsigned int mac_file_len;
118 pstrcpy(mac_file, lp_smb_passwd_file());
119 p = strrchr(mac_file, '/');
123 mac_file_len = strlen(mac_file);
125 if ((int)(sizeof(pstring) - mac_file_len - strlen(domain) - strlen(name) - 6) < 0)
127 DEBUG(0,("trust_password_lock: path %s too long to add trust details.\n",
132 pstrcat(mac_file, domain);
133 pstrcat(mac_file, ".");
134 pstrcat(mac_file, name);
135 pstrcat(mac_file, ".mac");
138 /************************************************************************
139 Routine to lock the trust account password file for a domain.
140 ************************************************************************/
141 BOOL trust_password_lock( char *domain, char *name, BOOL update)
145 if(mach_passwd_lock_depth == 0) {
147 get_trust_account_file_name( domain, name, mac_file);
149 if((mach_passwd_fp = fopen(mac_file, "r+b")) == NULL) {
150 if(errno == ENOENT && update) {
151 mach_passwd_fp = fopen(mac_file, "w+b");
154 if(mach_passwd_fp == NULL) {
155 DEBUG(0,("trust_password_lock: cannot open file %s - Error was %s.\n",
156 mac_file, strerror(errno) ));
161 chmod(mac_file, 0600);
163 if(!pw_file_lock(fileno(mach_passwd_fp), (update ? F_WRLCK : F_RDLCK),
164 60, &mach_passwd_lock_depth))
166 DEBUG(0,("trust_password_lock: cannot lock file %s\n", mac_file));
167 fclose(mach_passwd_fp);
176 /************************************************************************
177 Routine to unlock the trust account password file for a domain.
178 ************************************************************************/
179 BOOL trust_password_unlock(void)
181 BOOL ret = pw_file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth);
182 if(mach_passwd_lock_depth == 0)
183 fclose(mach_passwd_fp);
187 /************************************************************************
188 Routine to delete the trust account password file for a domain.
189 ************************************************************************/
190 BOOL trust_password_delete( char *domain, char *name )
194 get_trust_account_file_name( domain, name, mac_file);
195 return (unlink( mac_file ) == 0);
198 /************************************************************************
199 Routine to get the trust account password for a domain.
200 The user of this function must have locked the trust password file.
201 ************************************************************************/
202 BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_time)
210 *pass_last_set_time = (time_t)0;
211 memset(ret_pwd, '\0', 16);
213 if(fseek( mach_passwd_fp, 0L, SEEK_SET) == -1) {
214 DEBUG(0,("get_trust_account_password: Failed to seek to start of file. Error was %s.\n",
219 fgets(linebuf, sizeof(linebuf), mach_passwd_fp);
220 if(ferror(mach_passwd_fp)) {
221 DEBUG(0,("get_trust_account_password: Failed to read password. Error was %s.\n",
227 * The length of the line read
228 * must be 45 bytes ( <---XXXX 32 bytes-->:TLC-12345678
231 if(strlen(linebuf) != 45) {
232 DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length).\n"));
233 #ifdef DEBUG_PASSWORD
234 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
240 * Get the hex password.
243 if (!pdb_gethexpwd((char *)linebuf, (char *)ret_pwd) || linebuf[32] != ':' ||
244 strncmp(&linebuf[33], "TLC-", 4)) {
245 DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n"));
246 #ifdef DEBUG_PASSWORD
247 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
253 * Get the last changed time.
257 for(i = 0; i < 8; i++) {
258 if(p[i] == '\0' || !isxdigit(p[i])) {
259 DEBUG(0,("get_trust_account_password: Malformed trust password file (no timestamp).\n"));
260 #ifdef DEBUG_PASSWORD
261 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
268 * p points at 8 characters of hex digits -
269 * read into a time_t as the seconds since
270 * 1970 that the password was last changed.
273 *pass_last_set_time = (time_t)strtol(p, NULL, 16);
278 /************************************************************************
279 Routine to get the trust account password for a domain.
280 The user of this function must have locked the trust password file.
281 ************************************************************************/
282 BOOL set_trust_account_password( unsigned char *md4_new_pwd)
287 if(fseek( mach_passwd_fp, 0L, SEEK_SET) == -1) {
288 DEBUG(0,("set_trust_account_password: Failed to seek to start of file. Error was %s.\n",
293 for (i = 0; i < 16; i++)
294 slprintf(&linebuf[(i*2)], sizeof(linebuf) - (i*2) - 1, "%02X", md4_new_pwd[i]);
296 slprintf(&linebuf[32], 32, ":TLC-%08X\n", (unsigned)time(NULL));
298 if(fwrite( linebuf, 1, 45, mach_passwd_fp)!= 45) {
299 DEBUG(0,("set_trust_account_password: Failed to write file. Warning - the trust \
300 account is now invalid. Please recreate. Error was %s.\n", strerror(errno) ));
304 fflush(mach_passwd_fp);