mirror of
https://github.com/samba-team/samba.git
synced 2025-08-04 08:22:08 +03:00
r17005: Add a new helper mode to ntlm_auth: ntlm-change-password-1
This mode proxies pre-calculated blobs from a remote (probably VPN)
client into the domain. This allows clients to change their password
over a PPTP connection (where they would not be able to connect to
SAMR directly).
The precalculated blobs do not reveal the plaintext password.
Original patch by Alexey Kobozev <cobedump@gmail.com>
(This used to be commit 967292b713
)
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
de5d967505
commit
0dc8f720e1
@ -214,6 +214,7 @@ static struct winbindd_dispatch_table {
|
|||||||
{ WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },
|
{ WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },
|
||||||
{ WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },
|
{ WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },
|
||||||
{ WINBINDD_PAM_LOGOFF, winbindd_pam_logoff, "PAM_LOGOFF" },
|
{ 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 */
|
/* Enumeration functions */
|
||||||
|
|
||||||
|
@ -353,6 +353,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
|
|||||||
{ WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" },
|
{ WINBINDD_PAM_AUTH, winbindd_dual_pam_auth, "PAM_AUTH" },
|
||||||
{ WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" },
|
{ WINBINDD_PAM_AUTH_CRAP, winbindd_dual_pam_auth_crap, "AUTH_CRAP" },
|
||||||
{ WINBINDD_PAM_LOGOFF, winbindd_dual_pam_logoff, "PAM_LOGOFF" },
|
{ WINBINDD_PAM_LOGOFF, winbindd_dual_pam_logoff, "PAM_LOGOFF" },
|
||||||
|
{ WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,winbindd_dual_pam_chng_pswd_auth_crap,"CHNG_PSWD_AUTH_CRAP" },
|
||||||
{ WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" },
|
{ WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" },
|
||||||
{ WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" },
|
{ WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" },
|
||||||
{ WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" },
|
{ WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" },
|
||||||
|
@ -65,6 +65,7 @@ enum winbindd_cmd {
|
|||||||
WINBINDD_PAM_AUTH_CRAP,
|
WINBINDD_PAM_AUTH_CRAP,
|
||||||
WINBINDD_PAM_CHAUTHTOK,
|
WINBINDD_PAM_CHAUTHTOK,
|
||||||
WINBINDD_PAM_LOGOFF,
|
WINBINDD_PAM_LOGOFF,
|
||||||
|
WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,
|
||||||
|
|
||||||
/* List various things */
|
/* List various things */
|
||||||
|
|
||||||
@ -225,6 +226,18 @@ struct winbindd_request {
|
|||||||
fstring oldpass;
|
fstring oldpass;
|
||||||
fstring newpass;
|
fstring newpass;
|
||||||
} chauthtok; /* pam_winbind passwd module */
|
} 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 {
|
struct {
|
||||||
fstring user;
|
fstring user;
|
||||||
fstring krb5ccname;
|
fstring krb5ccname;
|
||||||
|
@ -1901,3 +1901,151 @@ process_result:
|
|||||||
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
|
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)
|
||||||
|
{
|
||||||
|
struct winbindd_domain *domain = NULL;
|
||||||
|
const char *domain_name = NULL;
|
||||||
|
|
||||||
|
/* 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 != '\0') {
|
||||||
|
domain_name = state->request.data.chng_pswd_auth_crap.domain;
|
||||||
|
} else if (lp_winbind_use_default_domain()) {
|
||||||
|
domain_name = lp_workgroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domain_name != NULL)
|
||||||
|
domain = find_domain_from_name(domain_name);
|
||||||
|
|
||||||
|
if (domain != NULL) {
|
||||||
|
DEBUG(7, ("[%5lu]: pam auth crap changing pswd in domain: "
|
||||||
|
"%s\n", (unsigned long)state->pid,domain->name));
|
||||||
|
sendto_domain(state, domain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
|
||||||
|
DEBUG(5, ("CRAP change password for %s\\%s returned %s (PAM: %d)\n",
|
||||||
|
state->request.data.chng_pswd_auth_crap.domain,
|
||||||
|
state->request.data.chng_pswd_auth_crap.user,
|
||||||
|
state->response.data.auth.nt_status_string,
|
||||||
|
state->response.data.auth.pam_error));
|
||||||
|
request_error(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, 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;
|
||||||
|
fstring domain,user;
|
||||||
|
POLICY_HND dom_pol;
|
||||||
|
struct winbindd_domain *contact_domain = domainSt;
|
||||||
|
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;
|
||||||
|
*domain = 0;
|
||||||
|
*user = 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) {
|
||||||
|
fstrcpy(domain,state->request.data.chng_pswd_auth_crap.domain);
|
||||||
|
} else {
|
||||||
|
parse_domain_user(state->request.data.chng_pswd_auth_crap.user,
|
||||||
|
domain, user);
|
||||||
|
|
||||||
|
if(!*domain) {
|
||||||
|
DEBUG(3,("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 (!*domain && lp_winbind_use_default_domain()) {
|
||||||
|
fstrcpy(domain,(char *)lp_workgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!*user) {
|
||||||
|
fstrcpy(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));
|
||||||
|
|
||||||
|
/* 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));
|
||||||
|
|
||||||
|
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
|
||||||
|
}
|
||||||
|
@ -1288,6 +1288,50 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
|
|||||||
return result;
|
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;
|
||||||
|
char *srv_name_slash;
|
||||||
|
|
||||||
|
if (!(srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s",
|
||||||
|
cli->cli->desthost))) {
|
||||||
|
return NT_STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(5,("rpccli_samr_chng_pswd_auth_crap on server: %s\n",
|
||||||
|
srv_name_slash));
|
||||||
|
|
||||||
|
ZERO_STRUCT(q);
|
||||||
|
ZERO_STRUCT(r);
|
||||||
|
|
||||||
|
/* 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_password.data,
|
||||||
|
old_lm_hash_enc.data);
|
||||||
|
|
||||||
|
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 r.status;
|
||||||
|
}
|
||||||
|
|
||||||
/* change password 3 */
|
/* change password 3 */
|
||||||
|
|
||||||
NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
|
NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
|
||||||
|
@ -38,6 +38,7 @@ enum stdio_helper_mode {
|
|||||||
GSS_SPNEGO,
|
GSS_SPNEGO,
|
||||||
GSS_SPNEGO_CLIENT,
|
GSS_SPNEGO_CLIENT,
|
||||||
NTLM_SERVER_1,
|
NTLM_SERVER_1,
|
||||||
|
NTLM_CHANGE_PASSWORD_1,
|
||||||
NUM_HELPER_MODES
|
NUM_HELPER_MODES
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,6 +63,8 @@ static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helpe
|
|||||||
static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode,
|
static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode,
|
||||||
char *buf, int length);
|
char *buf, int length);
|
||||||
|
|
||||||
|
static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length);
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
enum stdio_helper_mode mode;
|
enum stdio_helper_mode mode;
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -74,6 +77,7 @@ static const struct {
|
|||||||
{ GSS_SPNEGO, "gss-spnego", manage_gss_spnego_request},
|
{ GSS_SPNEGO, "gss-spnego", manage_gss_spnego_request},
|
||||||
{ GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_request},
|
{ GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_request},
|
||||||
{ NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request},
|
{ NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request},
|
||||||
|
{ NTLM_CHANGE_PASSWORD_1, "ntlm-change-password-1", manage_ntlm_change_password_1_request},
|
||||||
{ NUM_HELPER_MODES, NULL, NULL}
|
{ NUM_HELPER_MODES, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -390,7 +394,87 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
|
|||||||
free_response(&response);
|
free_response(&response);
|
||||||
return nt_status;
|
return nt_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* contact server to change user password using auth crap */
|
||||||
|
static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username,
|
||||||
|
const char *domain,
|
||||||
|
const DATA_BLOB new_nt_pswd,
|
||||||
|
const DATA_BLOB old_nt_hash_enc,
|
||||||
|
const DATA_BLOB new_lm_pswd,
|
||||||
|
const DATA_BLOB old_lm_hash_enc,
|
||||||
|
char **error_string)
|
||||||
|
{
|
||||||
|
NTSTATUS nt_status;
|
||||||
|
NSS_STATUS result;
|
||||||
|
struct winbindd_request request;
|
||||||
|
struct winbindd_response response;
|
||||||
|
|
||||||
|
if (!get_require_membership_sid())
|
||||||
|
{
|
||||||
|
if(error_string)
|
||||||
|
*error_string = smb_xstrdup("Can't get membership sid.");
|
||||||
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZERO_STRUCT(request);
|
||||||
|
ZERO_STRUCT(response);
|
||||||
|
|
||||||
|
if(username != NULL)
|
||||||
|
fstrcpy(request.data.chng_pswd_auth_crap.user, username);
|
||||||
|
if(domain != NULL)
|
||||||
|
fstrcpy(request.data.chng_pswd_auth_crap.domain,domain);
|
||||||
|
|
||||||
|
if(new_nt_pswd.length)
|
||||||
|
{
|
||||||
|
memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd, new_nt_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_nt_pswd));
|
||||||
|
request.data.chng_pswd_auth_crap.new_nt_pswd_len = new_nt_pswd.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(old_nt_hash_enc.length)
|
||||||
|
{
|
||||||
|
memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc, 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 = old_nt_hash_enc.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_lm_pswd.length)
|
||||||
|
{
|
||||||
|
memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd, new_lm_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_lm_pswd));
|
||||||
|
request.data.chng_pswd_auth_crap.new_lm_pswd_len = new_lm_pswd.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(old_lm_hash_enc.length)
|
||||||
|
{
|
||||||
|
memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc, 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 = 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))
|
||||||
|
{
|
||||||
|
nt_status = NT_STATUS_UNSUCCESSFUL;
|
||||||
|
if (error_string)
|
||||||
|
*error_string = smb_xstrdup("Reading winbind reply failed!");
|
||||||
|
free_response(&response);
|
||||||
|
return nt_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
nt_status = (NT_STATUS(response.data.auth.nt_status));
|
||||||
|
if (!NT_STATUS_IS_OK(nt_status))
|
||||||
|
{
|
||||||
|
if (error_string)
|
||||||
|
*error_string = smb_xstrdup(response.data.auth.error_string);
|
||||||
|
free_response(&response);
|
||||||
|
return nt_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_response(&response);
|
||||||
|
|
||||||
|
return nt_status;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
|
static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
|
||||||
{
|
{
|
||||||
static const char zeros[16];
|
static const char zeros[16];
|
||||||
@ -1580,6 +1664,216 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void manage_ntlm_change_password_1_request(enum stdio_helper_mode helper_mode, char *buf, int length)
|
||||||
|
{
|
||||||
|
char *request, *parameter;
|
||||||
|
static DATA_BLOB new_nt_pswd;
|
||||||
|
static DATA_BLOB old_nt_hash_enc;
|
||||||
|
static DATA_BLOB new_lm_pswd;
|
||||||
|
static DATA_BLOB old_lm_hash_enc;
|
||||||
|
static char *full_username = NULL;
|
||||||
|
static char *username = NULL;
|
||||||
|
static char *domain = NULL;
|
||||||
|
static char *newpswd = NULL;
|
||||||
|
static char *oldpswd = NULL;
|
||||||
|
|
||||||
|
if (strequal(buf, ".")) {
|
||||||
|
if(newpswd && oldpswd) {
|
||||||
|
uchar old_nt_hash[16];
|
||||||
|
uchar old_lm_hash[16];
|
||||||
|
uchar new_nt_hash[16];
|
||||||
|
uchar new_lm_hash[16];
|
||||||
|
|
||||||
|
new_nt_pswd = data_blob(NULL, 516);
|
||||||
|
old_nt_hash_enc = data_blob(NULL, 16);
|
||||||
|
|
||||||
|
/* Calculate the MD4 hash (NT compatible) of the
|
||||||
|
* password */
|
||||||
|
E_md4hash(oldpswd, old_nt_hash);
|
||||||
|
E_md4hash(newpswd, new_nt_hash);
|
||||||
|
|
||||||
|
/* E_deshash returns false for 'long'
|
||||||
|
passwords (> 14 DOS chars).
|
||||||
|
|
||||||
|
Therefore, don't send a buffer
|
||||||
|
encrypted with the truncated hash
|
||||||
|
(it could allow an even easier
|
||||||
|
attack on the password)
|
||||||
|
|
||||||
|
Likewise, obey the admin's restriction
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (lp_client_lanman_auth() &&
|
||||||
|
E_deshash(newpswd, new_lm_hash) &&
|
||||||
|
E_deshash(oldpswd, old_lm_hash)) {
|
||||||
|
new_lm_pswd = data_blob(NULL, 516);
|
||||||
|
old_lm_hash_enc = data_blob(NULL, 16);
|
||||||
|
encode_pw_buffer(new_lm_pswd.data, newpswd,
|
||||||
|
STR_UNICODE);
|
||||||
|
|
||||||
|
SamOEMhash(new_lm_pswd.data, old_nt_hash, 516);
|
||||||
|
E_old_pw_hash(new_nt_hash, old_lm_hash,
|
||||||
|
old_lm_hash_enc.data);
|
||||||
|
} else {
|
||||||
|
new_lm_pswd.data = NULL;
|
||||||
|
new_lm_pswd.length = 0;
|
||||||
|
old_lm_hash_enc.data = NULL;
|
||||||
|
old_lm_hash_enc.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
encode_pw_buffer(new_nt_pswd.data, newpswd,
|
||||||
|
STR_UNICODE);
|
||||||
|
|
||||||
|
SamOEMhash(new_nt_pswd.data, old_nt_hash, 516);
|
||||||
|
E_old_pw_hash(new_nt_hash, old_nt_hash,
|
||||||
|
old_nt_hash_enc.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!full_username && !username) {
|
||||||
|
x_fprintf(x_stdout, "Error: No username supplied!\n");
|
||||||
|
} else if ((!new_nt_pswd.data || !old_nt_hash_enc.data) &&
|
||||||
|
(!new_lm_pswd.data || old_lm_hash_enc.data) ) {
|
||||||
|
x_fprintf(x_stdout, "Error: No NT or LM password "
|
||||||
|
"blobs supplied!\n");
|
||||||
|
} else {
|
||||||
|
char *error_string = NULL;
|
||||||
|
|
||||||
|
if (full_username && !username) {
|
||||||
|
fstring fstr_user;
|
||||||
|
fstring fstr_domain;
|
||||||
|
|
||||||
|
if (!parse_ntlm_auth_domain_user(full_username,
|
||||||
|
fstr_user,
|
||||||
|
fstr_domain)) {
|
||||||
|
/* username might be 'tainted', don't
|
||||||
|
* print into our new-line
|
||||||
|
* deleimianted stream */
|
||||||
|
x_fprintf(x_stdout, "Error: Could not "
|
||||||
|
"parse into domain and "
|
||||||
|
"username\n");
|
||||||
|
SAFE_FREE(username);
|
||||||
|
username = smb_xstrdup(full_username);
|
||||||
|
} else {
|
||||||
|
SAFE_FREE(username);
|
||||||
|
SAFE_FREE(domain);
|
||||||
|
username = smb_xstrdup(fstr_user);
|
||||||
|
domain = smb_xstrdup(fstr_domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!NT_STATUS_IS_OK(contact_winbind_change_pswd_auth_crap(
|
||||||
|
username, domain,
|
||||||
|
new_nt_pswd,
|
||||||
|
old_nt_hash_enc,
|
||||||
|
new_lm_pswd,
|
||||||
|
old_lm_hash_enc,
|
||||||
|
&error_string))) {
|
||||||
|
x_fprintf(x_stdout, "Password-Change: No\n");
|
||||||
|
x_fprintf(x_stdout, "Password-Change-Error: "
|
||||||
|
"%s\n.\n", error_string);
|
||||||
|
} else {
|
||||||
|
x_fprintf(x_stdout, "Password-Change: Yes\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFE_FREE(error_string);
|
||||||
|
}
|
||||||
|
/* clear out the state */
|
||||||
|
new_nt_pswd = data_blob(NULL, 0);
|
||||||
|
old_nt_hash_enc = data_blob(NULL, 0);
|
||||||
|
new_lm_pswd = data_blob(NULL, 0);
|
||||||
|
old_nt_hash_enc = data_blob(NULL, 0);
|
||||||
|
SAFE_FREE(full_username);
|
||||||
|
SAFE_FREE(username);
|
||||||
|
SAFE_FREE(domain);
|
||||||
|
SAFE_FREE(newpswd);
|
||||||
|
SAFE_FREE(oldpswd);
|
||||||
|
x_fprintf(x_stdout, ".\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request = buf;
|
||||||
|
|
||||||
|
/* Indicates a base64 encoded structure */
|
||||||
|
parameter = strstr_m(request, ":: ");
|
||||||
|
if (!parameter) {
|
||||||
|
parameter = strstr_m(request, ": ");
|
||||||
|
|
||||||
|
if (!parameter) {
|
||||||
|
DEBUG(0, ("Parameter not found!\n"));
|
||||||
|
x_fprintf(x_stdout, "Error: Parameter not found!\n.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter[0] ='\0';
|
||||||
|
parameter++;
|
||||||
|
parameter[0] ='\0';
|
||||||
|
parameter++;
|
||||||
|
} else {
|
||||||
|
parameter[0] ='\0';
|
||||||
|
parameter++;
|
||||||
|
parameter[0] ='\0';
|
||||||
|
parameter++;
|
||||||
|
parameter[0] ='\0';
|
||||||
|
parameter++;
|
||||||
|
|
||||||
|
base64_decode_inplace(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strequal(request, "new-nt-password-blob")) {
|
||||||
|
new_nt_pswd = strhex_to_data_blob(NULL, parameter);
|
||||||
|
if (new_nt_pswd.length != 516) {
|
||||||
|
x_fprintf(x_stdout, "Error: hex decode of %s failed! "
|
||||||
|
"(got %d bytes, expected 516)\n.\n",
|
||||||
|
parameter,
|
||||||
|
(int)new_nt_pswd.length);
|
||||||
|
new_nt_pswd = data_blob(NULL, 0);
|
||||||
|
}
|
||||||
|
} else if (strequal(request, "old-nt-hash-blob")) {
|
||||||
|
old_nt_hash_enc = strhex_to_data_blob(NULL, parameter);
|
||||||
|
if (old_nt_hash_enc.length != 16) {
|
||||||
|
x_fprintf(x_stdout, "Error: hex decode of %s failed! "
|
||||||
|
"(got %d bytes, expected 16)\n.\n",
|
||||||
|
parameter,
|
||||||
|
(int)old_nt_hash_enc.length);
|
||||||
|
old_nt_hash_enc = data_blob(NULL, 0);
|
||||||
|
}
|
||||||
|
} else if (strequal(request, "new-lm-password-blob")) {
|
||||||
|
new_lm_pswd = strhex_to_data_blob(NULL, parameter);
|
||||||
|
if (new_lm_pswd.length != 516) {
|
||||||
|
x_fprintf(x_stdout, "Error: hex decode of %s failed! "
|
||||||
|
"(got %d bytes, expected 516)\n.\n",
|
||||||
|
parameter,
|
||||||
|
(int)new_lm_pswd.length);
|
||||||
|
new_lm_pswd = data_blob(NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strequal(request, "old-lm-hash-blob")) {
|
||||||
|
old_lm_hash_enc = strhex_to_data_blob(NULL, parameter);
|
||||||
|
if (old_lm_hash_enc.length != 16)
|
||||||
|
{
|
||||||
|
x_fprintf(x_stdout, "Error: hex decode of %s failed! "
|
||||||
|
"(got %d bytes, expected 16)\n.\n",
|
||||||
|
parameter,
|
||||||
|
(int)old_lm_hash_enc.length);
|
||||||
|
old_lm_hash_enc = data_blob(NULL, 0);
|
||||||
|
}
|
||||||
|
} else if (strequal(request, "nt-domain")) {
|
||||||
|
domain = smb_xstrdup(parameter);
|
||||||
|
} else if(strequal(request, "username")) {
|
||||||
|
username = smb_xstrdup(parameter);
|
||||||
|
} else if(strequal(request, "full-username")) {
|
||||||
|
username = smb_xstrdup(parameter);
|
||||||
|
} else if(strequal(request, "new-password")) {
|
||||||
|
newpswd = smb_xstrdup(parameter);
|
||||||
|
} else if (strequal(request, "old-password")) {
|
||||||
|
oldpswd = smb_xstrdup(parameter);
|
||||||
|
} else {
|
||||||
|
x_fprintf(x_stdout, "Error: Unknown request %s\n.\n", request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helper_function fn)
|
static void manage_squid_request(enum stdio_helper_mode helper_mode, stdio_helper_function fn)
|
||||||
{
|
{
|
||||||
char buf[SQUID_BUFFER_SIZE+1];
|
char buf[SQUID_BUFFER_SIZE+1];
|
||||||
|
Reference in New Issue
Block a user