[PATCH] Set password from nt-hash .Useful to sync password from OpenLdap.
Jeremy Allison
jra at samba.org
Wed Oct 7 23:51:52 UTC 2015
On Mon, Oct 05, 2015 at 05:46:54PM +0200, Alberto Maria Fiaschi wrote:
> From 1354f76aa702504e83ac5463c85cd0f82b9a675d Mon Sep 17 00:00:00 2001
> From: Alberto Maria Fiaschi <alberto.fiaschi at estar.toscana.it>
> Date: Wed, 10 Jun 2015 15:26:58 +0200
> Subject: [PATCH] Add --set-nt-hash option to pdbedit to update user password
> from nt-hash hexstring.
>
> Useful to take in sync password from other repository.
> (Modify MASK_USER_GOOD to include new flag BIT_PWSETNTHASH)
>
> pdbedit -vw show also password hashes .
>
> Split pdb_set_plaintext_passwd in two function:
> pdb_set_plaintext_passwd and pdb_update_history.
> pdb_update_history update password history and is call from
> pdb_set_plaintext_passwd.
OK, I took a look at this - there are some things
I like. The good:
1). Split pdb_set_plaintext_passwd in two function:
pdb_set_plaintext_passwd and pdb_update_history.
looks like a nice cleanup change.
The bad:
I'm not 100% convinced of the utility of updating
directly the NT-hash. What exactly is your use-case
here ?
and the ugly:
I really don't like the -vw change that dumps out
password hashes. I don't think we should make that
particularly easy to do (although it's not a security
issue per se).
> docs-xml/manpages/pdbedit.8.xml | 20 +++++++++++++++++--
> source3/include/passdb.h | 1 +
> source3/passdb/pdb_get_set.c | 24 +++++++++++++++++------
> source3/utils/pdbedit.c | 43 +++++++++++++++++++++++++++++++++++++----
> 4 files changed, 76 insertions(+), 12 deletions(-)
>
> diff --git a/docs-xml/manpages/pdbedit.8.xml b/docs-xml/manpages/pdbedit.8.xml
> index 6ed0399..c4ae1a1 100644
> --- a/docs-xml/manpages/pdbedit.8.xml
> +++ b/docs-xml/manpages/pdbedit.8.xml
> @@ -43,6 +43,7 @@
> <arg choice="opt">-r</arg>
> <arg choice="opt">-s configfile</arg>
> <arg choice="opt">-S script</arg>
> + <arg choice="opt">--set-nt-hash</arg>
> <arg choice="opt">-t</arg>
> <arg choice="opt">--time-format</arg>
> <arg choice="opt">-u username</arg>
> @@ -99,7 +100,8 @@ samba:45:Test User
> <term>-v|--verbose</term>
> <listitem><para>This option enables the verbose listing format.
> It causes pdbedit to list the users in the database, printing
> - out the account fields in a descriptive format.</para>
> + out the account fields in a descriptive format.Used together
> + with -w also shows passwords hashes.</para>
>
> <para>Example: <command>pdbedit -L -v</command></para>
> <para><programlisting>
> @@ -134,7 +136,9 @@ Profile Path: \\BERSERKER\profile
> out the account fields in a format compatible with the
> <filename>smbpasswd</filename> file format. (see the
> <citerefentry><refentrytitle>smbpasswd</refentrytitle>
> - <manvolnum>5</manvolnum></citerefentry> for details)</para>
> + <manvolnum>5</manvolnum></citerefentry> for details).
> + Instead used together with (-v) displays the passwords
> + hashes in verbose output.</para>
>
> <para>Example: <command>pdbedit -L -w</command></para>
> <programlisting>
> @@ -205,6 +209,18 @@ samba:45:0F2B255F7B67A7A9AAD3B435B51404EE:
>
>
> <varlistentry>
> + <term>--set-nt-hash</term>
> + <listitem><para>This option can be used while modifying
> + a user account. It will set the user's password using
> + the nt-hash value given as hexadecimal string.
> + Useful to synchronize passwords.</para>
> +
> + <para>Example: <literal>--set-nt-hash 8846F7EAEE8FB117AD06BDD830B7586C</literal>
> + </para>
> + </listitem>
> + </varlistentry>
> +
> + <varlistentry>
> <term>-p|--profile profile</term>
> <listitem><para>This option can be used while adding or
> modifying a user account. It will specify the user's profile
> diff --git a/source3/include/passdb.h b/source3/include/passdb.h
> index 893d0d0..b78846d 100644
> --- a/source3/include/passdb.h
> +++ b/source3/include/passdb.h
> @@ -811,6 +811,7 @@ bool pdb_set_nt_passwd(struct samu *sampass, const uint8_t pwd[NT_HASH_LEN], enu
> bool pdb_set_lanman_passwd(struct samu *sampass, const uint8_t pwd[LM_HASH_LEN], enum pdb_value_state flag);
> bool pdb_set_pw_history(struct samu *sampass, const uint8_t *pwd, uint32_t historyLen, enum pdb_value_state flag);
> bool pdb_set_plaintext_pw_only(struct samu *sampass, const char *password, enum pdb_value_state flag);
> +bool pdb_update_history(struct samu *sampass,const uint8_t new_nt[NT_HASH_LEN]);
> bool pdb_set_bad_password_count(struct samu *sampass, uint16_t bad_password_count, enum pdb_value_state flag);
> bool pdb_set_logon_count(struct samu *sampass, uint16_t logon_count, enum pdb_value_state flag);
> bool pdb_set_country_code(struct samu *sampass, uint16_t country_code,
> diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
> index 9f27459..74a71cb 100644
> --- a/source3/passdb/pdb_get_set.c
> +++ b/source3/passdb/pdb_get_set.c
> @@ -999,10 +999,6 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
> {
> uchar new_lanman_p16[LM_HASH_LEN];
> uchar new_nt_p16[NT_HASH_LEN];
> - uchar *pwhistory;
> - uint32_t pwHistLen;
> - uint32_t current_history_len;
> - const uint8_t *current_history;
>
> if (!plaintext)
> return False;
> @@ -1032,6 +1028,21 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
> if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
> return False;
>
> +
> + return pdb_update_history(sampass, new_nt_p16);
> +}
> +
> +/*********************************************************************
> + Update password history after change
> + ********************************************************************/
> +
> +bool pdb_update_history(struct samu *sampass, const uint8_t new_nt[NT_HASH_LEN])
> +{
> + uchar *pwhistory;
> + uint32_t pwHistLen;
> + uint32_t current_history_len;
> + const uint8_t *current_history;
> +
> if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) == 0) {
> /*
> * No password history for non-user accounts
> @@ -1055,7 +1066,7 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
> */
> current_history = pdb_get_pw_history(sampass, ¤t_history_len);
> if ((current_history_len != 0) && (current_history == NULL)) {
> - DEBUG(1, ("pdb_set_plaintext_passwd: pwhistory == NULL!\n"));
> + DEBUG(1, ("pdb_update_history: pwhistory == NULL!\n"));
> return false;
> }
>
> @@ -1096,11 +1107,12 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
> * The old format was to store the md5 hash of
> * the salt+newpw.
> */
> - memcpy(&pwhistory[PW_HISTORY_SALT_LEN], new_nt_p16, SALTED_MD5_HASH_LEN);
> + memcpy(&pwhistory[PW_HISTORY_SALT_LEN], new_nt, SALTED_MD5_HASH_LEN);
>
> pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED);
>
> return True;
> +
> }
>
> /* check for any PDB_SET/CHANGED field and fill the appropriate mask bit */
> diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
> index 1f44fb0..202758e 100644
> --- a/source3/utils/pdbedit.c
> +++ b/source3/utils/pdbedit.c
> @@ -55,9 +55,10 @@
> #define BIT_LOGONHOURS 0x10000000
> #define BIT_KICKOFFTIME 0x20000000
> #define BIT_DESCRIPTION 0x40000000
> +#define BIT_PWSETNTHASH 0x80000000
>
> #define MASK_ALWAYS_GOOD 0x0000001F
> -#define MASK_USER_GOOD 0x60405FE0
> +#define MASK_USER_GOOD 0xE0405FE0
>
> static int get_sid_from_cli_string(struct dom_sid *sid, const char *str_sid)
> {
> @@ -317,6 +318,12 @@ static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdst
> hours = pdb_get_hours(sam_pwent);
> pdb_sethexhours(temp, hours);
> printf ("Logon hours : %s\n", temp);
> + if (smbpwdstyle){
> + pdb_sethexpwd(temp, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
> + printf ("LM hash : %s\n", temp);
> + pdb_sethexpwd(temp, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
> + printf ("NT hash : %s\n", temp);
> + }
>
> } else if (smbpwdstyle) {
> char lm_passwd[33];
> @@ -499,7 +506,7 @@ static int set_user_info(const char *username, const char *fullname,
> const char *profile, const char *account_control,
> const char *user_sid, const char *user_domain,
> const bool badpw, const bool hours,
> - const char *kickoff_time)
> + const char *kickoff_time, const char *str_hex_pwd)
> {
> bool updated_autolock = False, updated_badpw = False;
> struct samu *sam_pwent;
> @@ -601,9 +608,33 @@ static int set_user_info(const char *username, const char *fullname,
>
> pdb_set_kickoff_time(sam_pwent, value, PDB_CHANGED);
> }
> + if (str_hex_pwd) {
> + unsigned char new_nt_p16[NT_HASH_LEN];
> + if(strlen(str_hex_pwd) != (NT_HASH_LEN *2)){
> + fprintf(stderr, "Invalid hash\n");
> + return -1;
> + }
> +
> + pdb_gethexpwd(str_hex_pwd, new_nt_p16);
> +
> + if (!pdb_set_nt_passwd (sam_pwent, new_nt_p16 , PDB_CHANGED)) {
> + fprintf(stderr, "Failed to set password from nt-hash\n");
> + return -1;
> + }
> +
> + if (!pdb_set_pass_last_set_time (sam_pwent, time(NULL), PDB_CHANGED)){
> + fprintf(stderr, "Failed to set last password set time\n");
> + return -1;
> + }
> + if (!pdb_update_history(sam_pwent, new_nt_p16)){
> + fprintf(stderr, "Failed to update password history\n");
> + return -1;
> + }
> + }
>
> if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
> - print_user_info(username, True, False);
> +
> + print_user_info(username, True, (str_hex_pwd != NULL ));
> } else {
> fprintf (stderr, "Unable to modify entry!\n");
> TALLOC_FREE(sam_pwent);
> @@ -1021,6 +1052,7 @@ int main(int argc, const char **argv)
> static int pw_from_stdin = False;
> struct pdb_methods *bin, *bout;
> static char *kickoff_time = NULL;
> + static char *str_hex_pwd = NULL;
> TALLOC_CTX *frame = talloc_stackframe();
> NTSTATUS status;
> poptContext pc;
> @@ -1058,6 +1090,7 @@ int main(int argc, const char **argv)
> {"time-format", 0, POPT_ARG_STRING, &pwd_time_format, 0, "The time format for time parameters", NULL },
> {"password-from-stdin", 't', POPT_ARG_NONE, &pw_from_stdin, 0, "get password from standard in", NULL},
> {"kickoff-time", 'K', POPT_ARG_STRING, &kickoff_time, 0, "set the kickoff time", NULL},
> + {"set-nt-hash", 0, POPT_ARG_STRING, &str_hex_pwd, 0, "set password from nt-hash", NULL},
> POPT_COMMON_SAMBA
> POPT_TABLEEND
> };
> @@ -1118,7 +1151,9 @@ int main(int argc, const char **argv)
> (badpw_reset ? BIT_BADPWRESET : 0) +
> (hours_reset ? BIT_LOGONHOURS : 0) +
> (kickoff_time ? BIT_KICKOFFTIME : 0) +
> + (str_hex_pwd ? BIT_PWSETNTHASH : 0 ) +
> (acct_desc ? BIT_DESCRIPTION : 0);
> +
>
> if (setparms & BIT_BACKEND) {
> /* HACK: set the global passdb backend by overwriting globals.
> @@ -1315,7 +1350,7 @@ int main(int argc, const char **argv)
> profile_path, account_control,
> user_sid, user_domain,
> badpw_reset, hours_reset,
> - kickoff_time);
> + kickoff_time,str_hex_pwd);
> }
> }
> }
> --
> 2.4.9
>
More information about the samba-technical
mailing list