From dc36d8768aa13000c48b520f09f6678ea9ffbf28 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Sep 1998 22:33:13 +0000 Subject: [PATCH] Integration of Anders Blomdell 's smbpasswd changes. Not exactly the same as his code - several changes. Jeremy. (This used to be commit e96747a8e3b9ea5a79c4258e55d7e8f3bf0bf193) --- source3/include/proto.h | 2 +- source3/include/smb.h | 6 ++ source3/passdb/ldap.c | 2 +- source3/passdb/nispass.c | 2 +- source3/passdb/passdb.c | 50 ++++++------ source3/passdb/smbpass.c | 144 +++++++++++++++++++++------------- source3/script/addtosmbpass | 6 +- source3/script/mksmbpasswd.sh | 2 +- source3/smbd/oplock.c | 39 ++++++++- source3/utils/smbpasswd.c | 138 ++++++++++++++++++++------------ 10 files changed, 254 insertions(+), 137 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index cbd4f07b2f3..fd77c45ee35 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1101,7 +1101,7 @@ void pdb_init_smb(struct smb_passwd *user); void pdb_init_sam(struct sam_passwd *user); struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user); struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user); -char *pdb_encode_acct_ctrl(uint16 acct_ctrl); +char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length); uint16 pdb_decode_acct_ctrl(char *p); BOOL pdb_gethexpwd(char *p, char *pwd); BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid); diff --git a/source3/include/smb.h b/source3/include/smb.h index 842aeb57be0..bec14ddd137 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1601,6 +1601,12 @@ extern int unix_ERR_code; __FILE__, __LINE__)), smb_panic("assert failed"))) #define SMB_ASSERT_ARRAY(a,n) SMB_ASSERT((sizeof(a)/sizeof((a)[0])) >= (n)) +/* + * Size of new password account encoding string. DO NOT CHANGE. + */ + +#define NEW_PW_FORMAT_SPACE_PADDED_LEN 14 + #endif /* _SMB_H */ #include "ntdomain.h" diff --git a/source3/passdb/ldap.c b/source3/passdb/ldap.c index e27b4fbea7b..80ba6be3a79 100644 --- a/source3/passdb/ldap.c +++ b/source3/passdb/ldap.c @@ -576,7 +576,7 @@ static BOOL modadd_ldappwd_entry(struct smb_passwd *newpwd, int flag) make_a_mod(&mods, ldap_state, "rid", rid); make_a_mod(&mods, ldap_state, "pwdLastSet", lst); - make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl)); + make_a_mod(&mods, ldap_state, "userAccountControl", pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN)); switch(flag) { diff --git a/source3/passdb/nispass.c b/source3/passdb/nispass.c index 04c1c23b2e6..4a2a7723d64 100644 --- a/source3/passdb/nispass.c +++ b/source3/passdb/nispass.c @@ -376,7 +376,7 @@ static BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd) slprintf(smb_grpid, sizeof(smb_grpid), "%u", newpwd->smb_grpid); slprintf(group_rid, sizeof(group_rid), "0x%x", newpwd->group_rid); - safe_strcpy(acb, pdb_encode_acct_ctrl(newpwd->acct_ctrl), sizeof(acb)); + safe_strcpy(acb, pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), sizeof(acb)); set_single_attribute(&new_obj, NPF_NAME , newpwd->smb_name , strlen(newpwd->smb_name) , 0); set_single_attribute(&new_obj, NPF_UID , uid , strlen(uid) , 0); diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 02f30b24c87..6633088245a 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -491,26 +491,35 @@ struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user) /********************************************************** Encode the account control bits into a string. + length = length of string to encode into (including terminating + null). length *MUST BE MORE THAN 2* ! **********************************************************/ -char *pdb_encode_acct_ctrl(uint16 acct_ctrl) + +char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length) { static fstring acct_str; - char *p = acct_str; - - *p++ = '['; + size_t i = 0; + + acct_str[i++] = '['; + + if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N'; + if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D'; + if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H'; + if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T'; + if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U'; + if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M'; + if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W'; + if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S'; + if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L'; + if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X'; + if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I'; + + for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; } + + i = length - 2; + acct_str[i++] = ']'; + acct_str[i++] = '\0'; - 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; } @@ -538,15 +547,8 @@ uint16 pdb_decode_acct_ctrl(char *p) { switch (*p) { -#if 0 - /* - * Hmmm. Don't allow these to be set/read independently - * of the actual password fields. We don't want a mismatch. - * JRA. - */ case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ } case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ } -#endif case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ } case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ } case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ } @@ -556,7 +558,7 @@ uint16 pdb_decode_acct_ctrl(char *p) case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ } case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ } - + case ' ': case ':': case '\n': case '\0': diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index a2b648b2fd2..cff049dcd5f 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -264,7 +264,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp) p++; if(*p == ':') { p++; - if(*p && StrnCaseCmp((char *)p, "LCT-", 4)) { + if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) { int i; p += 4; for(i = 0; i < 8; i++) { @@ -473,7 +473,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); return False; } - new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + 5 + 1 + 13 + 2; + new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2; if((new_entry = (char *)malloc( new_entry_length )) == NULL) { DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \ @@ -518,8 +518,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); /* Add the account encoding and the last change time. */ slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n", - pdb_encode_acct_ctrl(newpwd->acct_ctrl), - (uint32)time(NULL)); + pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)time(NULL)); #ifdef DEBUG_PASSWORD DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d entry_len %d made line |%s|", @@ -538,9 +537,11 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n", } endsmbfilepwent(fp); + free(new_entry); return False; } + free(new_entry); endsmbfilepwent(fp); return True; } @@ -654,7 +655,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) * * or, * - * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... + * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored. * * if Windows NT compatible passwords are also present. */ @@ -772,11 +773,31 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) if (*p == '[') { i = 0; - p++; + encode_bits[i++] = *p++; while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']')) encode_bits[i++] = *p++; - encode_bits[i] = '\0'; + encode_bits[i++] = ']'; + encode_bits[i++] = '\0'; + + if(i == NEW_PW_FORMAT_SPACE_PADDED_LEN) { + /* + * We are using a new format, space padded + * acct ctrl field. Encode the given acct ctrl + * bits into it. + */ + fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN)); + } else { + /* + * If using the old format and the ACB_DISABLED or + * ACB_PWNOTREQ are set then set the lanman and NT passwords to NULL + * here as we have no space to encode the change. + */ + if(pwd->acct_ctrl & (ACB_DISABLED|ACB_PWNOTREQ)) { + pwd->smb_passwd = NULL; + pwd->smb_nt_passwd = NULL; + } + } /* Go past the ']' */ if(linebuf_len > PTR_DIFF(p, linebuf)) @@ -785,8 +806,8 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) 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((char *)p, "LCT-", 4)) { + /* We should be pointing at the LCT entry. */ + if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) { p += 4; for(i = 0; i < 8; i++) { @@ -807,6 +828,58 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) /* Entry is correctly formed. */ + /* Create the 32 byte representation of the new p16 */ + if(pwd->smb_passwd != NULL) { + for (i = 0; i < 16; i++) { + slprintf(&ascii_p16[i*2], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_passwd[i]); + } + } else { + if(pwd->acct_ctrl & ACB_PWNOTREQ) + fstrcpy(ascii_p16, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + else + fstrcpy(ascii_p16, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } + + /* Add on the NT md4 hash */ + ascii_p16[32] = ':'; + wr_len = 66; + if (pwd->smb_nt_passwd != NULL) { + for (i = 0; i < 16; i++) { + slprintf(&ascii_p16[(i*2)+33], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_nt_passwd[i]); + } + } else { + if(pwd->acct_ctrl & ACB_PWNOTREQ) + fstrcpy(&ascii_p16[33], "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); + else + fstrcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } + ascii_p16[65] = ':'; + + /* Add on the account info bits and the time of last + password change. */ + + pwd->pass_last_set_time = time(NULL); + + if(got_pass_last_set_time) { + slprintf(&ascii_p16[strlen(ascii_p16)], + sizeof(ascii_p16)-(strlen(ascii_p16)+1), + "%s:LCT-%08X:", + encode_bits, (uint32)pwd->pass_last_set_time ); + wr_len = strlen(ascii_p16); + } + +#ifdef DEBUG_PASSWORD + DEBUG(100,("mod_smbfilepwd_entry: ")); + dump_data(100, ascii_p16, wr_len); +#endif + + if(wr_len > sizeof(linebuf)) { + DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1)); + pw_file_unlock(lockfd,&pw_file_lock_depth); + fclose(fp); + return (False); + } + /* * Do an atomic write into the file at the position defined by * seekpos. @@ -825,65 +898,28 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) return False; } - /* Sanity check - ensure the character is a ':' */ - if (read(fd, &c, 1) != 1) { + /* Sanity check - ensure the areas we are writing are framed by ':' */ + if (read(fd, linebuf, wr_len+1) != wr_len+1) { DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile)); pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } - if (c != ':') { + if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) { DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile)); pw_file_unlock(lockfd,&pw_file_lock_depth); fclose(fp); return False; } - /* Create the 32 byte representation of the new p16 */ - if(pwd->smb_passwd != NULL) { - for (i = 0; i < 16; i++) { - slprintf(&ascii_p16[i*2], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_passwd[i]); - } - } else { - if(pwd->acct_ctrl & ACB_PWNOTREQ) - fstrcpy(ascii_p16, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); - else - fstrcpy(ascii_p16, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) { + DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile)); + pw_file_unlock(lockfd,&pw_file_lock_depth); + fclose(fp); + return False; } - /* Add on the NT md4 hash */ - ascii_p16[32] = ':'; - wr_len = 65; - if (pwd->smb_nt_passwd != NULL) { - for (i = 0; i < 16; i++) { - slprintf(&ascii_p16[(i*2)+33], sizeof(fstring) - 1, "%02X", (uchar) pwd->smb_nt_passwd[i]); - } - } else { - if(pwd->acct_ctrl & ACB_PWNOTREQ) - fstrcpy(&ascii_p16[33], "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX"); - else - fstrcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); - } - - /* Add on the account info bits and the time of last - password change. */ - - pwd->pass_last_set_time = time(NULL); - - if(got_pass_last_set_time) { - slprintf(&ascii_p16[strlen(ascii_p16)], - sizeof(ascii_p16)-(strlen(ascii_p16)+1), - ":[%s]:TLC-%08X:", - encode_bits, (uint32)pwd->pass_last_set_time ); - wr_len = strlen(ascii_p16); - } - -#ifdef DEBUG_PASSWORD - DEBUG(100,("mod_smbfilepwd_entry: ")); - dump_data(100, ascii_p16, wr_len); -#endif - if (write(fd, ascii_p16, wr_len) != wr_len) { DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile)); pw_file_unlock(lockfd,&pw_file_lock_depth); diff --git a/source3/script/addtosmbpass b/source3/script/addtosmbpass index 42af518397c..5a41022a270 100644 --- a/source3/script/addtosmbpass +++ b/source3/script/addtosmbpass @@ -48,11 +48,11 @@ BEGIN { } END { fmt = "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:"; - fmt = fmt "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n"; + fmt = fmt "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:[U]:LCT-00000000:%s:\n"; for(name in names) { while ((getline < pwdf) > 0) { if ($1 == name) { - printf(fmt, $1, $3, $5, $6, $7); + printf(fmt, $1, $3, $5); close(pwdf); notfound = ""; break; @@ -65,7 +65,7 @@ END { command = ypmatch " " name " passwd"; command | getline; if (NF > 0) { - printf(fmt, $1, $3, $5, $6, $7); + printf(fmt, $1, $3, $5); } close(command); } diff --git a/source3/script/mksmbpasswd.sh b/source3/script/mksmbpasswd.sh index 6e592acd652..10acc1257d7 100755 --- a/source3/script/mksmbpasswd.sh +++ b/source3/script/mksmbpasswd.sh @@ -2,5 +2,5 @@ awk 'BEGIN {FS=":" printf("#\n# SMB password file.\n#\n") } -{ printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", $1, $3, $5, $6, $7) } +{ printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:[U]:LCT-00000000:%s\n", $1, $3, $5) } ' diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index d73fcda117d..b418e7cd549 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -240,16 +240,47 @@ BOOL set_file_oplock(files_struct *fsp) { #if defined(HAVE_KERNEL_OPLOCKS) if(lp_kernel_oplocks()) { - if(fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write) < 0) { - if(errno != EAGAIN) { +#if 0 /* for now. */ + extern struct current_user current_user; +#endif + int saved_errno; + int fcntl_ret; + +#if 0 /* for now. */ + /* + * Go back to being root. + */ + + unbecome_user(); +#endif + + fcntl_ret = fcntl(fsp->fd_ptr->fd, F_OPLKREG, oplock_pipe_write); + saved_errno = errno; + +#if 0 /* for now. */ + /* + * Go back to being the correct user. + */ + if(!become_user(fsp->conn, current_user.vuid)) + { + DEBUG( 0, ( "set_file_oplock: unable to re-become user!" ) ); + DEBUGADD( 0, ( "Shutting down server\n" ) ); + close_sockets(); + close(oplock_sock); + exit_server("unable to re-become user"); + } +#endif + + if(fcntl_ret < 0) { + if(saved_errno != EAGAIN) { DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \ inode = %.0f. Error was %s\n", fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode, strerror(errno) )); } else { - DEBUG(5,("set_file_oplock: Refused oplock on file %s, dev = %x, \ + DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \ inode = %.0f. Another process had the file open.\n", - fsp->fsp_name, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode )); + fsp->fsp_name, fsp->fd_ptr->fd, (unsigned int)fsp->fd_ptr->dev, (double)fsp->fd_ptr->inode )); } return False; } diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 03553b0ea96..b97b0c765fd 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -32,7 +32,7 @@ static char *prog_name; static void usage(char *name, BOOL is_root) { if(is_root) - fprintf(stderr, "Usage is : %s [-D DEBUGLEVEL] [-a] [-d] [-m] [-n] [username] [password]\n\ + fprintf(stderr, "Usage is : %s [-D DEBUGLEVEL] [-a] [-d] [-e] [-m] [-n] [username] [password]\n\ %s: [-R ] [-D DEBUGLEVEL] [-j DOMAINNAME] [-r machine] [-U remote_username] [username] [password]\n%s: [-h]\n", name, name, name); else fprintf(stderr, "Usage is : %s [-h] [-D DEBUGLEVEL] [-r machine] [-U remote_username] [password]\n", name); @@ -112,6 +112,56 @@ unable to join domain.\n", prog_name); return (int)ret; } +/************************************************************* + Utility function to create password hashes. +*************************************************************/ + +static void create_new_hashes( char *new_passwd, uchar *new_p16, uchar *new_nt_p16) +{ + memset(new_nt_p16, '\0', 16); + E_md4hash((uchar *) new_passwd, new_nt_p16); + + /* Mangle the password into Lanman format */ + new_passwd[14] = '\0'; + strupper(new_passwd); + + /* + * Calculate the SMB (lanman) hash functions of the new password. + */ + + memset(new_p16, '\0', 16); + E_P16((uchar *) new_passwd, new_p16); +} + +/************************************************************* + Utility function to prompt for new password. +*************************************************************/ + +static void prompt_for_new_password(char *new_passwd) +{ + char *p; + + new_passwd[0] = '\0'; + + p = getpass("New SMB password:"); + + strncpy(new_passwd, p, sizeof(fstring)); + new_passwd[sizeof(fstring)-1] = '\0'; + + p = getpass("Retype new SMB password:"); + + if (strncmp(p, new_passwd, sizeof(fstring)-1)) + { + fprintf(stderr, "%s: Mismatch - password unchanged.\n", prog_name); + exit(1); + } + + if (new_passwd[0] == '\0') { + printf("Password not set\n"); + exit(0); + } +} + /********************************************************* Start here. **********************************************************/ @@ -140,6 +190,7 @@ int main(int argc, char **argv) BOOL got_new_pass = False; BOOL trust_account = False; BOOL disable_user = False; + BOOL enable_user = False; BOOL set_no_password = False; BOOL joining_domain = False; char *new_domain = NULL; @@ -202,7 +253,7 @@ int main(int argc, char **argv) is_root = (real_uid == 0); - while ((ch = getopt(argc, argv, "adhmnj:r:R:D:U:")) != EOF) { + while ((ch = getopt(argc, argv, "adehmnj:r:R:D:U:")) != EOF) { switch(ch) { case 'a': if(is_root) @@ -218,6 +269,14 @@ int main(int argc, char **argv) } else usage(prog_name, is_root); break; + case 'e': + if(is_root) { + enable_user = True; + got_new_pass = True; + fstrcpy(new_passwd, "XXXXXX"); + } else + usage(prog_name, is_root); + break; case 'D': DEBUGLEVEL = atoi(optarg); break; @@ -337,7 +396,17 @@ int main(int argc, char **argv) } else { if(add_user) { - fprintf(stderr, "%s: Only root can set anothers password.\n", prog_name); + fprintf(stderr, "%s: Only root can add a user.\n", prog_name); + usage(prog_name, False); + } + + if(disable_user) { + fprintf(stderr, "%s: Only root can disable a user.\n", prog_name); + usage(prog_name, False); + } + + if(enable_user) { + fprintf(stderr, "%s: Only root can enable a user.\n", prog_name); usage(prog_name, False); } @@ -392,22 +461,8 @@ int main(int argc, char **argv) fstrcpy(old_passwd, p); } - if (!got_new_pass) { - new_passwd[0] = '\0'; - - p = getpass("New SMB password:"); - - strncpy(new_passwd, p, sizeof(fstring)); - new_passwd[sizeof(fstring)-1] = '\0'; - - p = getpass("Retype new SMB password:"); - - if (strncmp(p, new_passwd, sizeof(fstring)-1)) - { - fprintf(stderr, "%s: Mismatch - password unchanged.\n", prog_name); - exit(1); - } - } + if (!got_new_pass) + prompt_for_new_password(new_passwd); if (new_passwd[0] == '\0') { printf("Password not set\n"); @@ -493,25 +548,14 @@ int main(int argc, char **argv) /* Calculate the MD4 hash (NT compatible) of the new password. */ - memset(new_nt_p16, '\0', 16); - E_md4hash((uchar *) new_passwd, new_nt_p16); - - /* Mangle the password into Lanman format */ - new_passwd[14] = '\0'; - strupper(new_passwd); - - /* - * Calculate the SMB (lanman) hash functions of the new password. - */ - - memset(new_p16, '\0', 16); - E_P16((uchar *) new_passwd, new_p16); - + create_new_hashes( new_passwd, new_p16, new_nt_p16); + /* * Open the smbpaswd file. */ vp = startsmbpwent(True); if (!vp && errno == ENOENT) { + fprintf(stderr,"%s: smbpasswd file did not exist - attempting to create it.\n", prog_name); fp = fopen(lp_smb_passwd_file(), "w"); if (fp) { fprintf(fp, "# Samba SMB password file\n"); @@ -578,23 +622,19 @@ int main(int argc, char **argv) * and the valid last change time. */ - if(disable_user) { - /* - * This currently won't work as it means changing - * the length of the record. JRA. - */ + if(disable_user) smb_pwent->acct_ctrl |= ACB_DISABLED; - smb_pwent->smb_passwd = NULL; - smb_pwent->smb_nt_passwd = NULL; - } else if (set_no_password) { - /* - * This currently won't work as it means changing - * the length of the record. JRA. - */ + else if (enable_user) { + if(smb_pwent->smb_passwd == NULL) { + prompt_for_new_password(new_passwd); + create_new_hashes( new_passwd, new_p16, new_nt_p16); + smb_pwent->smb_passwd = new_p16; + smb_pwent->smb_nt_passwd = new_nt_p16; + } + smb_pwent->acct_ctrl &= ~ACB_DISABLED; + } else if (set_no_password) smb_pwent->acct_ctrl |= ACB_PWNOTREQ; - smb_pwent->smb_passwd = NULL; - smb_pwent->smb_nt_passwd = NULL; - } else { + else { smb_pwent->smb_passwd = new_p16; smb_pwent->smb_nt_passwd = new_nt_p16; } @@ -609,6 +649,8 @@ int main(int argc, char **argv) endsmbpwent(vp); if(disable_user) printf("User %s disabled.\n", user_name); + else if(enable_user) + printf("User %s enabled.\n", user_name); else if (set_no_password) printf("User %s - set to no password.\n", user_name); else