Winbindd change password request
Alexey Kobozev
cobedump at gmail.com
Thu Jun 15 14:13:35 GMT 2006
Hi guys!
Attached is the patch for crap change password in winbindd and ntlm_auth
It was done on samba 3.0.23rc2
Please review it.
Thanks.
-alexey
-------------- next part --------------
diff -rup samba-3.0.23rc2/source/nsswitch/winbindd.c samba-3.0.23rc2-patched/source/nsswitch/winbindd.c
--- samba-3.0.23rc2/source/nsswitch/winbindd.c 2006-06-13 04:52:16.000000000 +0300
+++ samba-3.0.23rc2-patched/source/nsswitch/winbindd.c 2006-06-15 16:00:21.026393136 +0300
@@ -214,6 +214,7 @@ static struct winbindd_dispatch_table {
{ WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },
{ WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },
{ WINBINDD_PAM_LOGOFF, winbindd_pam_logoff, "PAM_LOGOFF" },
+ { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, winbindd_pam_chng_pswd_auth_crap, "CHNG_PSWD_AUTH_CRAP" },
/* Enumeration functions */
diff -rup samba-3.0.23rc2/source/nsswitch/winbindd_misc.c samba-3.0.23rc2-patched/source/nsswitch/winbindd_misc.c
--- samba-3.0.23rc2/source/nsswitch/winbindd_misc.c 2006-04-20 05:29:21.000000000 +0300
+++ samba-3.0.23rc2-patched/source/nsswitch/winbindd_misc.c 2006-06-15 16:00:30.894892896 +0300
@@ -445,8 +445,12 @@ static void domain_info_init_recv(void *
request_ok(state);
}
+
void winbindd_ping(struct winbindd_cli_state *state)
{
+ void *res = NULL;
+ int count = 0;
+
DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
request_ok(state);
}
diff -rup samba-3.0.23rc2/source/nsswitch/winbindd_nss.h samba-3.0.23rc2-patched/source/nsswitch/winbindd_nss.h
--- samba-3.0.23rc2/source/nsswitch/winbindd_nss.h 2006-05-23 21:54:32.000000000 +0300
+++ samba-3.0.23rc2-patched/source/nsswitch/winbindd_nss.h 2006-06-15 16:00:40.190479752 +0300
@@ -65,6 +65,7 @@ enum winbindd_cmd {
WINBINDD_PAM_AUTH_CRAP,
WINBINDD_PAM_CHAUTHTOK,
WINBINDD_PAM_LOGOFF,
+ WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,
/* List various things */
@@ -226,6 +227,18 @@ struct winbindd_request {
} chauthtok; /* pam_winbind passwd module */
struct {
fstring user;
+ fstring domain;
+ unsigned char new_nt_pswd[516];
+ uint16 new_nt_pswd_len;
+ unsigned char old_nt_hash_enc[16];
+ uint16 old_nt_hash_enc_len;
+ unsigned char new_lm_pswd[516];
+ uint16 new_lm_pswd_len;
+ unsigned char old_lm_hash_enc[16];
+ uint16 old_lm_hash_enc_len;
+ } chng_pswd_auth_crap;/* pam_winbind passwd module */
+ struct {
+ fstring user;
fstring krb5ccname;
uid_t uid;
} logoff; /* pam_winbind session module */
diff -rup samba-3.0.23rc2/source/nsswitch/winbindd_pam.c samba-3.0.23rc2-patched/source/nsswitch/winbindd_pam.c
--- samba-3.0.23rc2/source/nsswitch/winbindd_pam.c 2006-06-09 22:30:30.000000000 +0300
+++ samba-3.0.23rc2-patched/source/nsswitch/winbindd_pam.c 2006-06-15 16:00:48.345240040 +0300
@@ -1853,3 +1853,113 @@ process_result:
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
+/* Change user password with auth crap*/
+
+void winbindd_pam_chng_pswd_auth_crap(struct winbindd_cli_state *state)
+{
+ NTSTATUS result;
+ DATA_BLOB new_nt_password;
+ DATA_BLOB old_nt_hash_enc;
+ DATA_BLOB new_lm_password;
+ DATA_BLOB old_lm_hash_enc;
+ char *domain = NULL, *user = NULL;
+ POLICY_HND dom_pol;
+ struct winbindd_domain *contact_domain;
+ struct rpc_pipe_client *cli;
+
+ /* Ensure null termination */
+ state->request.data.chng_pswd_auth_crap.user[sizeof(state->request.data.chng_pswd_auth_crap.user)-1]=0;
+ state->request.data.chng_pswd_auth_crap.domain[sizeof(state->request.data.chng_pswd_auth_crap.domain)-1]=0;
+
+ DEBUG(3, ("[%5lu]: pam change pswd auth crap domain: %s user: %s\n", (unsigned long)state->pid,
+ state->request.data.chng_pswd_auth_crap.domain, state->request.data.chng_pswd_auth_crap.user));
+
+ if (*state->request.data.chng_pswd_auth_crap.domain)
+ {
+ domain = state->request.data.chng_pswd_auth_crap.domain;
+ }
+ else if (lp_winbind_use_default_domain())
+ {
+ domain = (char *)lp_workgroup();
+ }
+ else
+ {
+ parse_domain_user(state->request.data.chng_pswd_auth_crap.user, domain, user);
+
+ if(!*domain)
+ {
+ DEBUG(5,("no domain specified with username (%s) - failing auth\n", state->request.data.chng_pswd_auth_crap.user));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+ }
+
+ if(!user)
+ {
+ user = state->request.data.chng_pswd_auth_crap.user;
+ }
+
+ DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, domain, user));
+
+ /* Setup crap */
+ if (!(contact_domain = find_domain_from_name(domain)))
+ {
+ DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n",
+ state->request.data.chng_pswd_auth_crap.user, domain, user, domain));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+
+ /* Change password */
+ new_nt_password = data_blob_talloc(state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.new_nt_pswd,
+ state->request.data.chng_pswd_auth_crap.new_nt_pswd_len);
+
+ old_nt_hash_enc = data_blob_talloc(state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.old_nt_hash_enc,
+ state->request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
+
+ if(state->request.data.chng_pswd_auth_crap.new_lm_pswd_len > 0)
+ {
+ new_lm_password = data_blob_talloc(state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.new_lm_pswd,
+ state->request.data.chng_pswd_auth_crap.new_lm_pswd_len);
+
+ old_lm_hash_enc = data_blob_talloc(state->mem_ctx,
+ state->request.data.chng_pswd_auth_crap.old_lm_hash_enc,
+ state->request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
+ }
+ else
+ {
+ new_lm_password.length = 0;
+ old_lm_hash_enc.length = 0;
+ }
+
+ /* Get sam handle */
+
+ result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, &dom_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
+ goto done;
+ }
+
+ result = rpccli_samr_chng_pswd_auth_crap(cli, state->mem_ctx, user, new_nt_password, old_nt_hash_enc, new_lm_password, old_lm_hash_enc);
+
+done:
+ state->response.data.auth.nt_status = NT_STATUS_V(result);
+ fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
+ fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
+ state->response.data.auth.pam_error = nt_status_to_pam(result);
+
+ DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
+ ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n",
+ domain,
+ user,
+ state->response.data.auth.nt_status_string,
+ state->response.data.auth.pam_error));
+
+ if (NT_STATUS_IS_OK(result))
+ request_ok(state);
+ else
+ request_error(state);
+}
diff -rup samba-3.0.23rc2/source/rpc_client/cli_samr.c samba-3.0.23rc2-patched/source/rpc_client/cli_samr.c
--- samba-3.0.23rc2/source/rpc_client/cli_samr.c 2006-05-23 21:54:29.000000000 +0300
+++ samba-3.0.23rc2-patched/source/rpc_client/cli_samr.c 2006-06-15 16:01:11.896659680 +0300
@@ -1288,6 +1288,73 @@ NTSTATUS rpccli_samr_chgpasswd_user(stru
return result;
}
+/* User change passwd with auth crap */
+
+NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const char *username,
+ DATA_BLOB new_nt_password,
+ DATA_BLOB old_nt_hash_enc,
+ DATA_BLOB new_lm_password,
+ DATA_BLOB old_lm_hash_enc)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_CHGPASSWD_USER q;
+ SAMR_R_CHGPASSWD_USER r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uchar new_lanman_password[516];
+ uchar old_lanman_hash_enc[16];
+ uchar *new_lm_ptr = NULL;
+ uchar *old_lm_hash_ptr = NULL;
+
+ char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
+
+ DEBUG(5,("rpccli_samr_chng_pswd_auth_crap on server: %s\n", srv_name_slash));
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+ ZERO_STRUCT(new_lanman_password);
+ ZERO_STRUCT(old_lanman_hash_enc);
+
+ if(!new_lm_password.length || !old_lm_hash_enc.length || !lp_client_lanman_auth())
+ {
+ DEBUG(5,("rpccli_samr_chng_pswd_auth_crap lanman cred not used\n"));
+ new_lm_ptr = new_lanman_password;
+ old_lm_hash_ptr = old_lanman_hash_enc;
+ }
+ else
+ {
+ new_lm_ptr = new_lm_password.data;
+ old_lm_hash_ptr = old_lm_hash_enc.data;
+ }
+
+
+ /* Marshall data and send request */
+
+ init_samr_q_chgpasswd_user(&q, srv_name_slash, username,
+ new_nt_password.data,
+ old_nt_hash_enc.data,
+ new_lm_ptr,
+ old_lm_hash_ptr);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD_USER,
+ q, r,
+ qbuf, rbuf,
+ samr_io_q_chgpasswd_user,
+ samr_io_r_chgpasswd_user,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ if (!NT_STATUS_IS_OK(result = r.status)) {
+ goto done;
+ }
+
+ done:
+
+ return result;
+}
+
/* change password 3 */
NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
diff -rup samba-3.0.23rc2/source/utils/ntlm_auth.c samba-3.0.23rc2-patched/source/utils/ntlm_auth.c
--- samba-3.0.23rc2/source/utils/ntlm_auth.c 2006-05-23 21:54:35.000000000 +0300
+++ samba-3.0.23rc2-patched/source/utils/ntlm_auth.c 2006-06-15 16:01:30.929766208 +0300
@@ -86,6 +86,10 @@ const char *opt_password;
static DATA_BLOB opt_challenge;
static DATA_BLOB opt_lm_response;
static DATA_BLOB opt_nt_response;
+static DATA_BLOB opt_new_nt_pswd;
+static DATA_BLOB opt_old_nt_hash_enc;
+static DATA_BLOB opt_new_lm_pswd;
+static DATA_BLOB opt_old_lm_hash_enc;
static int request_lm_key;
static int request_user_session_key;
@@ -1696,6 +1700,82 @@ static BOOL check_auth_crap(void)
return True;
}
+/* Change user password using auth crap */
+static BOOL change_pswd_auth_crap()
+{
+ NTSTATUS nt_status;
+ NSS_STATUS result;
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ if (!get_require_membership_sid())
+ {
+ x_fprintf(x_stdout, "Can't get membership sid (0x%x)\n", NT_STATUS_V(NT_STATUS_INVALID_PARAMETER));
+
+ return False;
+ }
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ fstrcpy(request.data.chng_pswd_auth_crap.user, opt_username);
+ fstrcpy(request.data.chng_pswd_auth_crap.domain,opt_domain);
+
+ if(opt_new_nt_pswd.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd, opt_new_nt_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_nt_pswd));
+ request.data.chng_pswd_auth_crap.new_nt_pswd_len = opt_new_nt_pswd.length;
+ }
+
+ if(opt_old_nt_hash_enc.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc, opt_old_nt_hash_enc.data, sizeof(request.data.chng_pswd_auth_crap.old_nt_hash_enc));
+ request.data.chng_pswd_auth_crap.old_nt_hash_enc_len = opt_old_nt_hash_enc.length;
+ }
+
+ if(opt_new_lm_pswd.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd, opt_new_lm_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_lm_pswd));
+ request.data.chng_pswd_auth_crap.new_lm_pswd_len = opt_new_lm_pswd.length;
+ }
+
+ if(opt_old_lm_hash_enc.length)
+ {
+ memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc, opt_old_lm_hash_enc.data, sizeof(request.data.chng_pswd_auth_crap.old_lm_hash_enc));
+ request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = opt_old_lm_hash_enc.length;
+ }
+
+ result = winbindd_request_response(WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, &request, &response);
+
+ /* Display response */
+
+ if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0))
+ {
+ x_fprintf(x_stdout, "Reading winbind reply failed!)\n");
+ free_response(&response);
+ return False;
+ }
+
+ nt_status = (NT_STATUS(response.data.auth.nt_status));
+ if (!NT_STATUS_IS_OK(nt_status))
+ {
+ x_fprintf(x_stdout, "%s: %s (0x%x)\n", response.data.auth.nt_status_string, response.data.auth.error_string, NT_STATUS_V(nt_status));
+ free_response(&response);
+ return False;
+ }
+ else
+ {
+ DEBUG(3, ("%s: %s (0x%x)\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.error_string,
+ response.data.auth.nt_status));
+ }
+
+ free_response(&response);
+
+ return True;
+}
+
/* Main program */
enum {
@@ -1710,7 +1790,11 @@ enum {
OPT_LM_KEY,
OPT_USER_SESSION_KEY,
OPT_DIAGNOSTICS,
- OPT_REQUIRE_MEMBERSHIP
+ OPT_REQUIRE_MEMBERSHIP,
+ OPT_NEW_NT,
+ OPT_OLD_NT,
+ OPT_NEW_LM,
+ OPT_OLD_LM
};
int main(int argc, const char **argv)
@@ -1722,6 +1806,10 @@ enum {
static const char *hex_challenge;
static const char *hex_lm_response;
static const char *hex_nt_response;
+ static const char *hex_new_nt_pswd;
+ static const char *hex_old_nt_hash;
+ static const char *hex_new_lm_pswd;
+ static const char *hex_old_lm_hash;
poptContext pc;
@@ -1747,6 +1835,10 @@ enum {
{ "request-nt-key", 0, POPT_ARG_NONE, &request_user_session_key, OPT_USER_SESSION_KEY, "Retrieve User (NT) session key"},
{ "diagnostics", 0, POPT_ARG_NONE, &diagnostics, OPT_DIAGNOSTICS, "Perform diagnostics on the authentictaion chain"},
{ "require-membership-of", 0, POPT_ARG_STRING, &require_membership_of, OPT_REQUIRE_MEMBERSHIP, "Require that a user be a member of this group (either name or SID) for authentication to succeed" },
+ { "new-nt-pswd-blob", 0, POPT_ARG_STRING, &hex_new_nt_pswd, OPT_NEW_NT, "New clear text password encrypted with old NT password hash (HEX encoded)"},
+ { "old-nt-hash-blob", 0, POPT_ARG_STRING, &hex_old_nt_hash, OPT_OLD_NT, "Old password hash encrypted with new NT password hash (HEX encoded)"},
+ { "new-lm-pswd-blob", 0, POPT_ARG_STRING, &hex_new_lm_pswd, OPT_NEW_LM, "New clear text password encrypted with old LM password hash (HEX encoded)"},
+ { "old-lm-hash-blob", 0, POPT_ARG_STRING, &hex_old_lm_hash, OPT_OLD_LM, "Old password hash encrypted with new LM password hash (HEX encoded)"},
POPT_COMMON_SAMBA
POPT_TABLEEND
};
@@ -1808,8 +1900,48 @@ enum {
exit(1);
}
break;
+
+ case OPT_NEW_NT:
+ opt_new_nt_pswd = strhex_to_data_blob(NULL, hex_new_nt_pswd);
+ if (opt_new_nt_pswd.length < 516) {
+ x_fprintf(x_stderr, "hex decode of %s failed! (only got %d bytes)\n",
+ hex_new_nt_pswd,
+ (int)opt_new_nt_pswd.length);
+ exit(1);
+ }
+ break;
- case OPT_REQUIRE_MEMBERSHIP:
+ case OPT_OLD_NT:
+ opt_old_nt_hash_enc = strhex_to_data_blob(NULL, hex_old_nt_hash);
+ if (opt_old_nt_hash_enc.length < 16) {
+ x_fprintf(x_stderr, "hex decode of %s failed! (only got %d bytes)\n",
+ hex_old_nt_hash,
+ (int)opt_old_nt_hash_enc.length);
+ exit(1);
+ }
+ break;
+
+ case OPT_NEW_LM:
+ opt_new_lm_pswd = strhex_to_data_blob(NULL, hex_new_lm_pswd);
+ if (opt_new_lm_pswd.length < 516) {
+ x_fprintf(x_stderr, "hex decode of %s failed! (only got %d bytes)\n",
+ hex_new_lm_pswd,
+ (int)opt_new_lm_pswd.length);
+ exit(1);
+ }
+ break;
+
+ case OPT_OLD_LM:
+ opt_old_lm_hash_enc = strhex_to_data_blob(NULL, hex_old_lm_hash);
+ if (opt_old_lm_hash_enc.length < 16) {
+ x_fprintf(x_stderr, "hex decode of %s failed! (only got %d bytes)\n",
+ hex_old_lm_hash,
+ (int)opt_old_lm_hash_enc.length);
+ exit(1);
+ }
+ break;
+
+ case OPT_REQUIRE_MEMBERSHIP:
if (StrnCaseCmp("S-", require_membership_of, 2) == 0) {
require_membership_of_sid = require_membership_of;
}
@@ -1848,6 +1980,15 @@ enum {
opt_workstation = "";
}
+ if(opt_new_nt_pswd.length)
+ {
+ if(!change_pswd_auth_crap())
+ {
+ exit(1);
+ }
+ exit(0);
+ }
+
if (opt_challenge.length) {
if (!check_auth_crap()) {
exit(1);
More information about the samba-technical
mailing list