nmbd.c: Fix for always overwriting log despite append setting.
smb.h: Addition of last time password changed entry to account info.
smbpass.c: Changes to support last time changed field in smbpasswd file.
smbpasswd.c: Changes to support last time changed field in smbpasswd file.
util.c: Fix for always overwriting log despite append setting.
Jeremy.
BOOL setsmbpwpos(void *vp, unsigned long tok);
struct smb_passwd *getsmbpwnam(char *name);
struct smb_passwd *getsmbpwuid(unsigned int uid);
+char *encode_acct_ctrl(uint16 acct_ctrl);
BOOL add_smbpwd_entry(struct smb_passwd *newpwd);
BOOL mod_smbpwd_entry(struct smb_passwd* pwd);
unsigned char *smb_nt_passwd; /* Null if no password */
/* Other fields / flags may be added later */
uint16 acct_ctrl;
+ time_t last_change_time;
};
struct cli_state {
{
if (!dbf) {
int oldumask = umask(022);
- dbf = fopen(debugf,"w");
+ if(append_log)
+ dbf = fopen(debugf,"a");
+ else
+ dbf = fopen(debugf,"w");
umask(oldumask);
if (dbf) {
setbuf(dbf,NULL);
}
}
+ reopen_logs();
+
DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
DEBUG(1,("Copyright Andrew Tridgell 1994-1997\n"));
}
pw_buf.acct_ctrl = ACB_NORMAL;
+ pw_buf.last_change_time = (time_t)-1;
/*
* Scan the file, a line at a time and check if the name matches.
/*
* The line we have should be of the form :-
*
- * username:uid:[32hex bytes]:....other flags presently
+ * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
* ignored....
*
* or,
*
- * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
+ * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
*
* if Windows NT compatible passwords are also present.
+ * [Account type] is an ascii encoding of the type of account.
+ * LCT-(8 hex digits) is the time_t value of the last change time.
*/
if (linebuf[0] == '#' || linebuf[0] == '\0') {
if(pw_buf.acct_ctrl == 0)
pw_buf.acct_ctrl = ACB_NORMAL;
+ /* Now try and get the last change time. */
+ if(*p == ']')
+ p++;
+ if(*p == ':') {
+ p++;
+ if(*p && StrnCaseCmp( p, "LCT-", 4)) {
+ int i;
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i]))
+ break;
+ }
+ if(i == 8) {
+ /*
+ * p points at 8 characters of hex digits -
+ * read into a time_t as the seconds since
+ * 1970 that the password was last changed.
+ */
+ pw_buf.last_change_time = (time_t)strtol(p, NULL, 16);
+ }
+ }
+ }
} else {
/* 'Old' style file. Fake up based on user name. */
/*
return get_smbpwd_entry(NULL, uid);
}
+/**********************************************************
+ Encode the account control bits into a string.
+**********************************************************/
+
+char *encode_acct_ctrl(uint16 acct_ctrl)
+{
+ static fstring acct_str;
+ char *p = acct_str;
+
+ *p++ = '[';
+
+ if(acct_ctrl & ACB_HOMDIRREQ)
+ *p++ = 'H';
+ if(acct_ctrl & ACB_TEMPDUP)
+ *p++ = 'T';
+ if(acct_ctrl & ACB_NORMAL)
+ *p++ = 'U';
+ if(acct_ctrl & ACB_MNS)
+ *p++ = 'M';
+ if(acct_ctrl & ACB_WSTRUST)
+ *p++ = 'W';
+ if(acct_ctrl & ACB_SVRTRUST)
+ *p++ = 'S';
+ if(acct_ctrl & ACB_AUTOLOCK)
+ *p++ = 'L';
+ if(acct_ctrl & ACB_PWNOEXP)
+ *p++ = 'X';
+ if(acct_ctrl & ACB_DOMTRUST)
+ *p++ = 'I';
+
+ *p++ = ']';
+ *p = '\0';
+ return acct_str;
+}
+
/************************************************************************
Routine to add an entry to the smbpasswd file.
*************************************************************************/
return False;
}
- new_entry_length = strlen(pwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + 2;
+ new_entry_length = strlen(pwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + 5 + 1 + 13 + 2;
if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
DEBUG(0, ("add_smbpwd_entry(malloc): Failed to add entry for user %s to file %s. \
p += 32;
*p++ = ':';
- sprintf((char *)p,"\n");
+
+ /* Add the account encoding and the last change time. */
+ sprintf((char *)p, "%s:LCT-%08X:\n", encode_acct_ctrl(pwd->acct_ctrl),
+ (uint32)time(NULL));
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("add_smbpwd_entry(%d): new_entry_len %d entry_len %d made line |%s|\n",
+ DEBUG(100, ("add_smbpwd_entry(%d): new_entry_len %d entry_len %d made line |%s|",
fd, new_entry_length, strlen(new_entry), new_entry));
#endif
char linebuf[256];
char readbuf[16 * 1024];
unsigned char c;
- char ascii_p16[66];
+ fstring ascii_p16;
+ fstring encode_bits;
unsigned char *p = NULL;
long linebuf_len = 0;
FILE *fp;
int lockfd;
char *pfile = lp_smb_passwd_file();
BOOL found_entry = False;
+ BOOL got_last_change_time = False;
long pwd_seekpos = 0;
return False;
}
+ /*
+ * Now check if the account info and the password last
+ * change time is available.
+ */
+ p += 33; /* Move to the first character of the line after
+ the NT password. */
+
+ if (*p == '[') {
+
+ /*
+ * Note that here we are assuming that the account
+ * info in the pwd struct matches the account info
+ * here in the file. It better..... JRA.
+ */
+
+ i = 0;
+ p++;
+ while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']'))
+ encode_bits[i++] = *p++;
+
+ encode_bits[i] = '\0';
+
+ /* Go past the ']' */
+ if(linebuf_len > PTR_DIFF(p, linebuf))
+ p++;
+
+ if((linebuf_len > PTR_DIFF(p, linebuf)) && (*p == ':')) {
+ p++;
+
+ /* We should be pointing at the TLC entry. */
+ if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && StrnCaseCmp( p, "LCT-", 4)) {
+
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i]))
+ break;
+ }
+ if(i == 8) {
+ /*
+ * p points at 8 characters of hex digits -
+ * read into a time_t as the seconds since
+ * 1970 that the password was last changed.
+ */
+ got_last_change_time = True;
+ } /* i == 8 */
+ } /* *p && StrnCaseCmp() */
+ } /* p == ':' */
+ } /* p == '[' */
+
/* Entry is correctly formed. */
/*
strcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
}
+ /* Add on the account info bits and the time of last
+ password change. */
+
+ pwd->last_change_time = time(NULL);
+
+ if(got_last_change_time) {
+ sprintf(&ascii_p16[strlen(ascii_p16)], ":[%s]:TLC-%08X",
+ encode_bits, (uint32)pwd->last_change_time );
+ wr_len = strlen(ascii_p16);
+ }
+
#ifdef DEBUG_PASSWORD
DEBUG(100,("mod_smbpwd_entry: "));
dump_data(100, ascii_p16, wr_len);
p->subcount = 0;
p->curpos = p->format;
if (i > n) {
+ p->neededlen = i;
i = n = 0;
- p->errcode = NERR_BufTooSmall;
+ p->errcode = ERROR_MORE_DATA;
}
else
p->errcode = NERR_Success;
static struct smb_passwd *
_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd,
- BOOL *got_valid_nt_entry, long *pwd_seekpos)
+ BOOL *got_valid_nt_entry, BOOL *got_valid_last_change_time, long *pwd_seekpos)
{
/* Static buffers we will return. */
static struct smb_passwd pw_buf;
long linebuf_len;
pw_buf.acct_ctrl = ACB_NORMAL;
+ *got_valid_last_change_time = False;
+ *got_valid_nt_entry = False;
+ *valid_old_pwd = False;
/*
* Scan the file, a line at a time and check if the name matches.
/* Must have some account type set. */
if(pw_buf.acct_ctrl == 0)
pw_buf.acct_ctrl = ACB_NORMAL;
-
+
+ /* Now try and get the last change time. */
+ if(*p == ']')
+ p++;
+ if(*p == ':') {
+ p++;
+ if(*p && StrnCaseCmp( p, "LCT-", 4)) {
+ int i;
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i]))
+ break;
+ }
+ if(i == 8) {
+ /*
+ * p points at 8 characters of hex digits -
+ * read into a time_t as the seconds since
+ * 1970 that the password was last changed.
+ */
+ pw_buf.last_change_time = (time_t)strtol(p, NULL, 16);
+ *got_valid_last_change_time = True;
+ } /* i == 8 */
+ } /* *p && StrnCaseCmp() */
+ } /* *p == ':' */
+
} else {
/* 'Old' style file. Fake up based on user name. */
/*
return NULL;
}
-/**********************************************************
- Encode the account control bits into a string.
-**********************************************************/
-
-char *encode_acct_ctrl(uint16 acct_ctrl)
-{
- static fstring acct_str;
- char *p = acct_str;
-
- *p++ = '[';
-
- if(acct_ctrl & ACB_HOMDIRREQ)
- *p++ = 'H';
- if(acct_ctrl & ACB_TEMPDUP)
- *p++ = 'T';
- if(acct_ctrl & ACB_NORMAL)
- *p++ = 'U';
- if(acct_ctrl & ACB_MNS)
- *p++ = 'M';
- if(acct_ctrl & ACB_WSTRUST)
- *p++ = 'W';
- if(acct_ctrl & ACB_SVRTRUST)
- *p++ = 'S';
- if(acct_ctrl & ACB_AUTOLOCK)
- *p++ = 'L';
- if(acct_ctrl & ACB_PWNOEXP)
- *p++ = 'X';
- if(acct_ctrl & ACB_DOMTRUST)
- *p++ = 'I';
-
- *p++ = ']';
- *p = '\0';
- return acct_str;
-}
-
/**********************************************************
Allocate an unused uid in the smbpasswd file to a new
machine account.
BOOL got_valid_nt_entry = False;
long seekpos;
int pwfd;
- char ascii_p16[66];
+ pstring ascii_p16;
char c;
int ch;
int ret, i, err, writelen;
char *remote_machine = NULL;
BOOL add_user = False;
BOOL got_new_pass = False;
+ BOOL got_valid_last_change_time = False;
BOOL machine_account = False;
BOOL disable_user = False;
BOOL set_no_password = False;
/* Get the smb passwd entry for this user */
smb_pwent = _my_get_smbpwnam(fp, user_name, &valid_old_pwd,
- &got_valid_nt_entry, &seekpos);
+ &got_valid_nt_entry, &got_valid_last_change_time, &seekpos);
if (smb_pwent == NULL) {
if(add_user == False) {
fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n",
new_entry_length = strlen(user_name) + 1 + 15 + 1 +
32 + 1 + 32 + 1 + sizeof(fstring) +
+ 1 + 13 +
1 + strlen(pwd->pw_dir) + 1 +
strlen(pwd->pw_shell) + 1;
if((new_entry = (char *)malloc( new_entry_length )) == 0) {
}
p += 32;
*p++ = ':';
- sprintf(p, "%s:%s:%s\n", encode_acct_ctrl(acct_ctrl),
- pwd->pw_dir, pwd->pw_shell);
+ sprintf(p, "%s:TLC-%08X:%s:%s\n", encode_acct_ctrl(acct_ctrl),
+ (uint32)time(NULL), pwd->pw_dir, pwd->pw_shell);
if(write(fd, new_entry, strlen(new_entry)) != strlen(new_entry)) {
fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \
Error was %s\n", prog_name, pwd->pw_name, pfile, strerror(errno));
}
/*
- * We are root - just write the new password.
+ * We are root - just write the new password
+ * and the valid last change time.
*/
/* Create the 32 byte representation of the new p16 */
}
}
}
+ ascii_p16[65] = ':';
+ ascii_p16[66] = '\0';
+ if(got_valid_last_change_time) {
+ strcpy(&ascii_p16[66], encode_acct_ctrl(smb_pwent->acct_ctrl));
+ sprintf(&ascii_p16[strlen(ascii_p16)], ":TLC-%08X", (uint32)time(NULL));
+ }
+
/*
* Do an atomic write into the file at the position defined by
* seekpos.
fclose(fp);
exit(1);
}
- writelen = (got_valid_nt_entry) ? 65 : 32;
+ writelen = (got_valid_nt_entry) ?
+ ( got_valid_last_change_time ? strlen(ascii_p16) : 65) : 32;
if (write(pwfd, ascii_p16, writelen) != writelen) {
err = errno;
fprintf(stderr, "%s: write fail in file %s.\n",