Converted to call lib/wins_srv.c:wins_srv_ip() instead of lp_wins_server()
[Samba.git] / source3 / passdb / smbpassfile.c
blobc915c8365a8b4c26903db82dc17ab5f911dcca02
1 /*
2 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
4 *
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)
8 * any later version.
9 *
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
13 * more details.
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
25 * database. JRA.
28 #include "includes.h"
30 extern int DEBUGLEVEL;
31 extern pstring global_myname;
33 BOOL global_machine_password_needs_changing = False;
35 /***************************************************************
36 Lock an fd. Abandon after waitsecs seconds.
37 ****************************************************************/
39 BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
41 if (fd < 0)
42 return False;
44 if(*plock_depth == 0) {
45 if (!do_file_lock(fd, secs, type)) {
46 DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
47 strerror(errno)));
48 return False;
52 (*plock_depth)++;
54 return True;
57 /***************************************************************
58 Unlock an fd. Abandon after waitsecs seconds.
59 ****************************************************************/
61 BOOL pw_file_unlock(int fd, int *plock_depth)
63 BOOL ret=True;
65 if(*plock_depth == 1)
66 ret = do_file_lock(fd, 5, F_UNLCK);
68 if (*plock_depth > 0)
69 (*plock_depth)--;
71 if(!ret)
72 DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
73 strerror(errno)));
74 return ret;
77 static int mach_passwd_lock_depth;
78 static FILE *mach_passwd_fp;
80 /************************************************************************
81 Routine to get the name for an old trust account file.
82 ************************************************************************/
84 static void get_trust_account_file_name( char *domain, char *name, char *mac_file)
86 unsigned int mac_file_len;
87 char *p;
89 pstrcpy(mac_file, lp_smb_passwd_file());
90 p = strrchr(mac_file, '/');
91 if(p != NULL)
92 *++p = '\0';
94 mac_file_len = strlen(mac_file);
96 if ((int)(sizeof(pstring) - mac_file_len - strlen(domain) - strlen(name) - 6) < 0)
98 DEBUG(0,("trust_password_lock: path %s too long to add trust details.\n",
99 mac_file));
100 return;
103 pstrcat(mac_file, domain);
104 pstrcat(mac_file, ".");
105 pstrcat(mac_file, name);
106 pstrcat(mac_file, ".mac");
109 /************************************************************************
110 Routine to lock the old trust account password file for a domain.
111 As this is a function to migrate to the new secrets.tdb, we never
112 create the file here, only open it.
113 ************************************************************************/
115 static BOOL trust_password_file_lock(char *domain, char *name)
117 pstring mac_file;
119 if(mach_passwd_lock_depth == 0) {
120 int fd;
122 get_trust_account_file_name( domain, name, mac_file);
124 if ((fd = sys_open(mac_file, O_RDWR, 0)) == -1)
125 return False;
127 if((mach_passwd_fp = fdopen(fd, "w+b")) == NULL) {
128 DEBUG(0,("trust_password_lock: cannot open file %s - Error was %s.\n",
129 mac_file, strerror(errno) ));
130 return False;
133 if(!pw_file_lock(fileno(mach_passwd_fp), F_WRLCK, 60, &mach_passwd_lock_depth)) {
134 DEBUG(0,("trust_password_lock: cannot lock file %s\n", mac_file));
135 fclose(mach_passwd_fp);
136 return False;
141 return True;
144 /************************************************************************
145 Routine to unlock the old trust account password file for a domain.
146 ************************************************************************/
148 static BOOL trust_password_file_unlock(void)
150 BOOL ret = pw_file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth);
151 if(mach_passwd_lock_depth == 0)
152 fclose(mach_passwd_fp);
153 return ret;
156 /************************************************************************
157 Routine to delete the old trust account password file for a domain.
158 Note that this file must be locked as it is truncated before the
159 delete. This is to ensure it only gets deleted by one smbd.
160 ************************************************************************/
162 static BOOL trust_password_file_delete( char *domain, char *name )
164 pstring mac_file;
165 int ret;
167 get_trust_account_file_name( domain, name, mac_file);
168 if(sys_ftruncate(fileno(mach_passwd_fp),(SMB_OFF_T)0) == -1) {
169 DEBUG(0,("trust_password_file_delete: Failed to truncate file %s (%s)\n",
170 mac_file, strerror(errno) ));
172 ret = unlink( mac_file );
173 return (ret != -1);
176 /************************************************************************
177 Routine to get the old trust account password for a domain - to convert
178 to the new secrets.tdb entry.
179 The user of this function must have locked the trust password file.
180 ************************************************************************/
182 static BOOL get_trust_account_password_from_file( unsigned char *ret_pwd, time_t *pass_last_set_time)
184 char linebuf[256];
185 char *p;
186 int i;
187 SMB_STRUCT_STAT st;
188 linebuf[0] = '\0';
190 *pass_last_set_time = (time_t)0;
191 memset(ret_pwd, '\0', 16);
193 if(sys_fstat(fileno(mach_passwd_fp), &st) == -1) {
194 DEBUG(0,("get_trust_account_password: Failed to stat file. Error was %s.\n",
195 strerror(errno) ));
196 return False;
200 * If size is zero, another smbd has migrated this file
201 * to the secrets.tdb file, and we are in a race condition.
202 * Just ignore the file.
205 if (st.st_size == 0)
206 return False;
208 if(sys_fseek( mach_passwd_fp, (SMB_OFF_T)0, SEEK_SET) == -1) {
209 DEBUG(0,("get_trust_account_password: Failed to seek to start of file. Error was %s.\n",
210 strerror(errno) ));
211 return False;
214 fgets(linebuf, sizeof(linebuf), mach_passwd_fp);
215 if(ferror(mach_passwd_fp)) {
216 DEBUG(0,("get_trust_account_password: Failed to read password. Error was %s.\n",
217 strerror(errno) ));
218 return False;
221 if(linebuf[strlen(linebuf)-1] == '\n')
222 linebuf[strlen(linebuf)-1] = '\0';
225 * The length of the line read
226 * must be 45 bytes ( <---XXXX 32 bytes-->:TLC-12345678
229 if(strlen(linebuf) != 45) {
230 DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \
231 - was %d, should be 45).\n", (int)strlen(linebuf)));
232 #ifdef DEBUG_PASSWORD
233 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
234 #endif
235 return False;
239 * Get the hex password.
242 if (!pdb_gethexpwd((char *)linebuf, ret_pwd) || linebuf[32] != ':' ||
243 strncmp(&linebuf[33], "TLC-", 4)) {
244 DEBUG(0,("get_trust_account_password: Malformed trust password file (incorrect format).\n"));
245 #ifdef DEBUG_PASSWORD
246 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
247 #endif
248 return False;
252 * Get the last changed time.
254 p = &linebuf[37];
256 for(i = 0; i < 8; i++) {
257 if(p[i] == '\0' || !isxdigit((int)p[i])) {
258 DEBUG(0,("get_trust_account_password: Malformed trust password file (no timestamp).\n"));
259 #ifdef DEBUG_PASSWORD
260 DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
261 #endif
262 return False;
267 * p points at 8 characters of hex digits -
268 * read into a time_t as the seconds since
269 * 1970 that the password was last changed.
272 *pass_last_set_time = (time_t)strtol(p, NULL, 16);
274 return True;
277 /************************************************************************
278 form a key for fetching a domain trust password
279 ************************************************************************/
281 static char *trust_keystr(char *domain)
283 static fstring keystr;
284 slprintf(keystr,sizeof(keystr),"%s/%s", SECRETS_MACHINE_ACCT_PASS, domain);
285 return keystr;
288 /************************************************************************
289 Migrate an old DOMAIN.MACINE.mac password file to the tdb secrets db.
290 ************************************************************************/
292 static void migrate_from_old_password_file(char *domain)
294 struct machine_acct_pass pass;
296 if (!trust_password_file_lock(domain, global_myname))
297 return;
299 if (!get_trust_account_password_from_file( pass.hash, &pass.mod_time)) {
300 trust_password_file_unlock();
301 return;
304 trust_password_file_delete(domain, global_myname);
306 secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass));
308 trust_password_file_unlock();
309 return;
312 /************************************************************************
313 Routine to delete the trust account password file for a domain.
314 ************************************************************************/
316 BOOL trust_password_delete(char *domain)
318 return secrets_delete(trust_keystr(domain));