r17005: Add a new helper mode to ntlm_auth: ntlm-change-password-1
authorAndrew Bartlett <abartlet@samba.org>
Thu, 13 Jul 2006 09:29:25 +0000 (09:29 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:19:17 +0000 (11:19 -0500)
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 967292b7136c5100c0b9a2783c34b1948b16dad4)

source3/nsswitch/winbindd.c
source3/nsswitch/winbindd_dual.c
source3/nsswitch/winbindd_nss.h
source3/nsswitch/winbindd_pam.c
source3/rpc_client/cli_samr.c
source3/utils/ntlm_auth.c

index e5582915b2f63b83e7d0c0fc080a4955694251cc..a4cd724e00639af7a96798b9e66437e420d3860e 100644 (file)
@@ -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 */
 
index 5908c78d9a8a180801b3cff3dedbde9ef6808fa1..b4d4a794aea1aceb0dfedb6b1801f57288dd4d0d 100644 (file)
@@ -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_CRAP,        winbindd_dual_pam_auth_crap,         "AUTH_CRAP" },
        { 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_DUAL_SID2UID,         winbindd_dual_sid2uid,               "DUAL_SID2UID" },
        { WINBINDD_DUAL_SID2GID,         winbindd_dual_sid2gid,               "DUAL_SID2GID" },
index 6167a10c46466ceda0414c96bec0fc5c938febe3..be0bb11948b18d6fd0176e54b77694f1cd035c8c 100644 (file)
@@ -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 */
 
@@ -225,6 +226,18 @@ struct winbindd_request {
                     fstring oldpass;
                     fstring newpass;
                 } 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;
index 34d23ebf8fa2ebdd47b8986a2094845642c78a45..6af8e31bc0bdc1e7b10915fcc7459bb0d588d9aa 100644 (file)
@@ -1901,3 +1901,151 @@ 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)
+{
+       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;
+}
index ea8db636423b77ef87b7d1fff55c972c1d79e95e..4c6a868e7f0c99796bfe229692d832c36e30ae0e 100644 (file)
@@ -1288,6 +1288,50 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
        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 */
 
 NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
index fc9e3e9546a072cdcfec304f1c362c78c1b42b69..9e178ec9456a0d0544d5f9055e36f4d089a861ca 100644 (file)
@@ -38,6 +38,7 @@ enum stdio_helper_mode {
        GSS_SPNEGO,
        GSS_SPNEGO_CLIENT,
        NTLM_SERVER_1,
+       NTLM_CHANGE_PASSWORD_1,
        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, 
                                          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 {
        enum stdio_helper_mode mode;
        const char *name;
@@ -74,6 +77,7 @@ static const struct {
        { GSS_SPNEGO, "gss-spnego", manage_gss_spnego_request},
        { GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_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}
 };
 
@@ -390,7 +394,87 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
        free_response(&response);
        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 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) 
 {
        char buf[SQUID_BUFFER_SIZE+1];