LCOV - code coverage report
Current view: top level - source3/utils - ntlm_auth.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 659 1226 53.8 %
Date: 2024-02-14 10:14:15 Functions: 28 36 77.8 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Winbind status program.
       5             : 
       6             :    Copyright (C) Tim Potter      2000-2003
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
       8             :    Copyright (C) Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it> 2000
       9             :    Copyright (C) Robert O'Callahan 2006 (added cached credential code).
      10             :    Copyright (C) Kai Blin <kai@samba.org> 2008
      11             :    Copyright (C) Simo Sorce 2010
      12             : 
      13             :    This program is free software; you can redistribute it and/or modify
      14             :    it under the terms of the GNU General Public License as published by
      15             :    the Free Software Foundation; either version 3 of the License, or
      16             :    (at your option) any later version.
      17             : 
      18             :    This program is distributed in the hope that it will be useful,
      19             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      20             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21             :    GNU General Public License for more details.
      22             : 
      23             :    You should have received a copy of the GNU General Public License
      24             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      25             : */
      26             : 
      27             : #include "includes.h"
      28             : #include "lib/param/param.h"
      29             : #include "lib/cmdline/cmdline.h"
      30             : #include "libcli/security/security.h"
      31             : #include "utils/ntlm_auth.h"
      32             : #include "../libcli/auth/libcli_auth.h"
      33             : #include "auth/ntlmssp/ntlmssp.h"
      34             : #include "auth/gensec/gensec.h"
      35             : #include "auth/gensec/gensec_internal.h"
      36             : #include "auth/credentials/credentials.h"
      37             : #include "librpc/crypto/gse.h"
      38             : #include "smb_krb5.h"
      39             : #include "lib/util/tiniparser.h"
      40             : #include "librpc/gen_ndr/krb5pac.h"
      41             : #include "auth/common_auth.h"
      42             : #include "source3/include/auth.h"
      43             : #include "source3/auth/proto.h"
      44             : #include "nsswitch/libwbclient/wbclient.h"
      45             : #include "nsswitch/winbind_struct_protocol.h"
      46             : #include "nsswitch/libwbclient/wbclient_internal.h"
      47             : #include "lib/param/loadparm.h"
      48             : #include "lib/util/base64.h"
      49             : #include "cmdline_contexts.h"
      50             : #include "lib/util/tevent_ntstatus.h"
      51             : #include "lib/util/string_wrappers.h"
      52             : 
      53             : #include <gnutls/gnutls.h>
      54             : #include <gnutls/crypto.h>
      55             : 
      56             : #ifdef HAVE_KRB5
      57             : #include "auth/kerberos/pac_utils.h"
      58             : #endif
      59             : 
      60             : #ifndef PAM_WINBIND_CONFIG_FILE
      61             : #define PAM_WINBIND_CONFIG_FILE "/etc/security/pam_winbind.conf"
      62             : #endif
      63             : 
      64             : #define WINBIND_KRB5_AUTH       0x00000080
      65             : 
      66             : #undef DBGC_CLASS
      67             : #define DBGC_CLASS DBGC_WINBIND
      68             : 
      69             : #define INITIAL_BUFFER_SIZE 300
      70             : #define MAX_BUFFER_SIZE 630000
      71             : 
      72             : enum stdio_helper_mode {
      73             :         SQUID_2_4_BASIC,
      74             :         SQUID_2_5_BASIC,
      75             :         SQUID_2_5_NTLMSSP,
      76             :         NTLMSSP_CLIENT_1,
      77             :         GSS_SPNEGO_SERVER,
      78             :         GSS_SPNEGO_CLIENT,
      79             :         NTLM_SERVER_1,
      80             :         NTLM_CHANGE_PASSWORD_1,
      81             :         NUM_HELPER_MODES
      82             : };
      83             : 
      84             : enum ntlm_auth_cli_state {
      85             :         CLIENT_INITIAL = 0,
      86             :         CLIENT_RESPONSE,
      87             :         CLIENT_FINISHED,
      88             :         CLIENT_ERROR
      89             : };
      90             : 
      91             : struct ntlm_auth_state {
      92             :         TALLOC_CTX *mem_ctx;
      93             :         enum stdio_helper_mode helper_mode;
      94             :         enum ntlm_auth_cli_state cli_state;
      95             :         struct ntlmssp_state *ntlmssp_state;
      96             :         uint32_t neg_flags;
      97             :         char *want_feature_list;
      98             :         bool have_session_key;
      99             :         DATA_BLOB session_key;
     100             :         DATA_BLOB initial_message;
     101             :         void *gensec_private_1;
     102             : };
     103             : typedef void (*stdio_helper_function)(enum stdio_helper_mode stdio_helper_mode,
     104             :                                       struct loadparm_context *lp_ctx,
     105             :                                       struct ntlm_auth_state *state, char *buf,
     106             :                                         int length, void **private2);
     107             : 
     108             : static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
     109             :                                   struct loadparm_context *lp_ctx,
     110             :                                   char *buf, int length, void **private1);
     111             : 
     112             : static void manage_squid_request(enum stdio_helper_mode stdio_helper_mode,
     113             :                                  struct loadparm_context *lp_ctx,
     114             :                                  struct ntlm_auth_state *state,
     115             :                                  stdio_helper_function fn, void **private2);
     116             : 
     117             : static void manage_squid_basic_request (enum stdio_helper_mode stdio_helper_mode,
     118             :                                       struct loadparm_context *lp_ctx,
     119             :                                       struct ntlm_auth_state *state,
     120             :                                         char *buf, int length, void **private2);
     121             : 
     122             : static void manage_squid_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode,
     123             :                                       struct loadparm_context *lp_ctx,
     124             :                                       struct ntlm_auth_state *state,
     125             :                                         char *buf, int length, void **private2);
     126             : 
     127             : static void manage_client_ntlmssp_request (enum stdio_helper_mode stdio_helper_mode,
     128             :                                       struct loadparm_context *lp_ctx,
     129             :                                       struct ntlm_auth_state *state,
     130             :                                         char *buf, int length, void **private2);
     131             : 
     132             : static void manage_gss_spnego_request (enum stdio_helper_mode stdio_helper_mode,
     133             :                                       struct loadparm_context *lp_ctx,
     134             :                                       struct ntlm_auth_state *state,
     135             :                                         char *buf, int length, void **private2);
     136             : 
     137             : static void manage_gss_spnego_client_request (enum stdio_helper_mode stdio_helper_mode,
     138             :                                       struct loadparm_context *lp_ctx,
     139             :                                       struct ntlm_auth_state *state,
     140             :                                         char *buf, int length, void **private2);
     141             : 
     142             : static void manage_ntlm_server_1_request (enum stdio_helper_mode stdio_helper_mode,
     143             :                                       struct loadparm_context *lp_ctx,
     144             :                                       struct ntlm_auth_state *state,
     145             :                                         char *buf, int length, void **private2);
     146             : 
     147             : static void manage_ntlm_change_password_1_request(enum stdio_helper_mode stdio_helper_mode,
     148             :                                       struct loadparm_context *lp_ctx,
     149             :                                       struct ntlm_auth_state *state,
     150             :                                         char *buf, int length, void **private2);
     151             : 
     152             : static const struct {
     153             :         enum stdio_helper_mode mode;
     154             :         const char *name;
     155             :         stdio_helper_function fn;
     156             : } stdio_helper_protocols[] = {
     157             :         { SQUID_2_4_BASIC, "squid-2.4-basic", manage_squid_basic_request},
     158             :         { SQUID_2_5_BASIC, "squid-2.5-basic", manage_squid_basic_request},
     159             :         { SQUID_2_5_NTLMSSP, "squid-2.5-ntlmssp", manage_squid_ntlmssp_request},
     160             :         { NTLMSSP_CLIENT_1, "ntlmssp-client-1", manage_client_ntlmssp_request},
     161             :         { GSS_SPNEGO_SERVER, "gss-spnego", manage_gss_spnego_request},
     162             :         { GSS_SPNEGO_CLIENT, "gss-spnego-client", manage_gss_spnego_client_request},
     163             :         { NTLM_SERVER_1, "ntlm-server-1", manage_ntlm_server_1_request},
     164             :         { NTLM_CHANGE_PASSWORD_1, "ntlm-change-password-1", manage_ntlm_change_password_1_request},
     165             :         { NUM_HELPER_MODES, NULL, NULL}
     166             : };
     167             : 
     168             : const char *opt_username;
     169             : const char *opt_domain;
     170             : const char *opt_workstation;
     171             : const char *opt_password;
     172             : static DATA_BLOB opt_challenge;
     173             : static DATA_BLOB opt_lm_response;
     174             : static DATA_BLOB opt_nt_response;
     175             : static int request_lm_key;
     176             : static int request_user_session_key;
     177             : static int use_cached_creds;
     178             : static int offline_logon;
     179             : static int opt_allow_mschapv2;
     180             : 
     181             : static const char *require_membership_of;
     182             : static const char *require_membership_of_sid;
     183             : static const char *opt_pam_winbind_conf;
     184             : 
     185             : const char *opt_target_service;
     186             : const char *opt_target_hostname;
     187             : 
     188             : 
     189             : /* This is a bit hairy, but the basic idea is to do a password callback
     190             :    to the calling application.  The callback comes from within gensec */
     191             : 
     192           0 : static void manage_gensec_get_pw_request(enum stdio_helper_mode stdio_helper_mode,
     193             :                                          struct loadparm_context *lp_ctx,
     194             :                                          struct ntlm_auth_state *state, char *buf, int length,
     195             :                                          void **password)
     196             : {
     197             :         DATA_BLOB in;
     198           0 :         if (strlen(buf) < 2) {
     199           0 :                 DEBUG(1, ("query [%s] invalid", buf));
     200           0 :                 printf("BH Query invalid\n");
     201           0 :                 return;
     202             :         }
     203             : 
     204           0 :         if (strlen(buf) > 3) {
     205           0 :                 in = base64_decode_data_blob(buf + 3);
     206             :         } else {
     207           0 :                 in = data_blob(NULL, 0);
     208             :         }
     209             : 
     210           0 :         if (strncmp(buf, "PW ", 3) == 0) {
     211             : 
     212           0 :                 *password = talloc_strndup(NULL,
     213           0 :                                            (const char *)in.data, in.length);
     214             : 
     215           0 :                 if (*password == NULL) {
     216           0 :                         DEBUG(1, ("Out of memory\n"));
     217           0 :                         printf("BH Out of memory\n");
     218           0 :                         data_blob_free(&in);
     219           0 :                         return;
     220             :                 }
     221             : 
     222           0 :                 printf("OK\n");
     223           0 :                 data_blob_free(&in);
     224           0 :                 return;
     225             :         }
     226           0 :         DEBUG(1, ("Asked for (and expected) a password\n"));
     227           0 :         printf("BH Expected a password\n");
     228           0 :         data_blob_free(&in);
     229             : }
     230             : 
     231             : /**
     232             :  * Callback for password credentials.  This is not async, and when
     233             :  * GENSEC and the credentials code is made async, it will look rather
     234             :  * different.
     235             :  */
     236             : 
     237           0 : static const char *get_password(struct cli_credentials *credentials)
     238             : {
     239           0 :         TALLOC_CTX *frame = talloc_stackframe();
     240           0 :         char *password = NULL;
     241             :         struct ntlm_auth_state *state;
     242             : 
     243           0 :         state = talloc_zero(frame, struct ntlm_auth_state);
     244           0 :         if (state == NULL) {
     245           0 :                 DEBUG(0, ("squid_stream: Failed to talloc ntlm_auth_state\n"));
     246           0 :                 fprintf(stderr, "ERR\n");
     247           0 :                 exit(1);
     248             :         }
     249             : 
     250           0 :         state->mem_ctx = state;
     251             : 
     252             :         /* Ask for a password */
     253           0 :         printf("PW\n");
     254             : 
     255           0 :         manage_squid_request(NUM_HELPER_MODES /* bogus */, NULL, state, manage_gensec_get_pw_request, (void **)&password);
     256           0 :         talloc_steal(credentials, password);
     257           0 :         TALLOC_FREE(frame);
     258           0 :         return password;
     259             : }
     260             : 
     261             : /**
     262             :  * A limited set of features are defined with text strings as needed
     263             :  * by ntlm_auth
     264             :  *
     265             :  */
     266         100 : static void gensec_want_feature_list(struct gensec_security *state, char* feature_list)
     267             : {
     268         100 :         if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, true)) {
     269           0 :                 DEBUG(10, ("want GENSEC_FEATURE_SESSION_KEY\n"));
     270           0 :                 gensec_want_feature(state, GENSEC_FEATURE_SESSION_KEY);
     271             :         }
     272         100 :         if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, true)) {
     273           0 :                 DEBUG(10, ("want GENSEC_FEATURE_SIGN\n"));
     274           0 :                 gensec_want_feature(state, GENSEC_FEATURE_SIGN);
     275             :         }
     276         100 :         if (in_list("NTLMSSP_FEATURE_SEAL", feature_list, true)) {
     277           0 :                 DEBUG(10, ("want GENSEC_FEATURE_SEAL\n"));
     278           0 :                 gensec_want_feature(state, GENSEC_FEATURE_SEAL);
     279             :         }
     280         100 :         if (in_list("NTLMSSP_FEATURE_CCACHE", feature_list, true)) {
     281           0 :                 DEBUG(10, ("want GENSEC_FEATURE_NTLM_CCACHE\n"));
     282           0 :                 gensec_want_feature(state, GENSEC_FEATURE_NTLM_CCACHE);
     283             :         }
     284         100 : }
     285             : 
     286          13 : static char winbind_separator(void)
     287             : {
     288             :         struct wbcInterfaceDetails *details;
     289             :         wbcErr ret;
     290             :         static bool got_sep;
     291             :         static char sep;
     292             : 
     293          13 :         if (got_sep)
     294           0 :                 return sep;
     295             : 
     296          13 :         ret = wbcInterfaceDetails(&details);
     297          13 :         if (!WBC_ERROR_IS_OK(ret)) {
     298           0 :                 d_fprintf(stderr, "could not obtain winbind separator!\n");
     299           0 :                 return *lp_winbind_separator();
     300             :         }
     301             : 
     302          13 :         sep = details->winbind_separator;
     303             : 
     304          13 :         wbcFreeMemory(details);
     305             : 
     306          13 :         got_sep = True;
     307             : 
     308          13 :         if (!sep) {
     309           0 :                 d_fprintf(stderr, "winbind separator was NULL!\n");
     310           0 :                 return *lp_winbind_separator();
     311             :         }
     312             : 
     313          13 :         return sep;
     314             : }
     315             : 
     316         141 : const char *get_winbind_domain(void)
     317             : {
     318             :         struct wbcInterfaceDetails *details;
     319             :         wbcErr ret;
     320             : 
     321             :         static fstring winbind_domain;
     322         141 :         if (*winbind_domain) {
     323          68 :                 return winbind_domain;
     324             :         }
     325             : 
     326             :         /* Send off request */
     327             : 
     328          73 :         ret = wbcInterfaceDetails(&details);
     329          73 :         if (!WBC_ERROR_IS_OK(ret)) {
     330           0 :                 DEBUG(1, ("could not obtain winbind domain name!\n"));
     331           0 :                 return lp_workgroup();
     332             :         }
     333             : 
     334          73 :         fstrcpy(winbind_domain, details->netbios_domain);
     335             : 
     336          73 :         wbcFreeMemory(details);
     337             : 
     338          73 :         return winbind_domain;
     339             : 
     340             : }
     341             : 
     342          76 : const char *get_winbind_netbios_name(void)
     343             : {
     344             :         struct wbcInterfaceDetails *details;
     345             :         wbcErr ret;
     346             : 
     347             :         static fstring winbind_netbios_name;
     348             : 
     349          76 :         if (*winbind_netbios_name) {
     350          32 :                 return winbind_netbios_name;
     351             :         }
     352             : 
     353             :         /* Send off request */
     354             : 
     355          44 :         ret = wbcInterfaceDetails(&details);
     356          44 :         if (!WBC_ERROR_IS_OK(ret)) {
     357           0 :                 DEBUG(1, ("could not obtain winbind netbios name!\n"));
     358           0 :                 return lp_netbios_name();
     359             :         }
     360             : 
     361          44 :         fstrcpy(winbind_netbios_name, details->netbios_name);
     362             : 
     363          44 :         wbcFreeMemory(details);
     364             : 
     365          44 :         return winbind_netbios_name;
     366             : 
     367             : }
     368             : 
     369          96 : DATA_BLOB get_challenge(void)
     370             : {
     371             :         static DATA_BLOB chal;
     372          96 :         if (opt_challenge.length)
     373           0 :                 return opt_challenge;
     374             : 
     375          96 :         chal = data_blob(NULL, 8);
     376             : 
     377          96 :         generate_random_buffer(chal.data, chal.length);
     378          96 :         return chal;
     379             : }
     380             : 
     381             : /* Copy of parse_domain_user from winbindd_util.c.  Parse a string of the
     382             :    form DOMAIN/user into a domain and a user */
     383             : 
     384           0 : static bool parse_ntlm_auth_domain_user(const char *domuser, fstring domain,
     385             :                                      fstring user)
     386             : {
     387             : 
     388           0 :         char *p = strchr(domuser,winbind_separator());
     389             : 
     390           0 :         if (!p) {
     391           0 :                 return False;
     392             :         }
     393             : 
     394           0 :         fstrcpy(user, p+1);
     395           0 :         fstrcpy(domain, domuser);
     396           0 :         domain[PTR_DIFF(p, domuser)] = 0;
     397           0 :         return strupper_m(domain);
     398             : }
     399             : 
     400         185 : static bool get_require_membership_sid(void) {
     401             :         fstring domain, name, sidbuf;
     402             :         struct wbcDomainSid sid;
     403             :         enum wbcSidType type;
     404             :         wbcErr ret;
     405             : 
     406         185 :         if (!require_membership_of) {
     407         153 :                 return True;
     408             :         }
     409             : 
     410          32 :         if (require_membership_of_sid) {
     411          32 :                 return True;
     412             :         }
     413             : 
     414             :         /* Otherwise, ask winbindd for the name->sid request */
     415             : 
     416           0 :         if (!parse_ntlm_auth_domain_user(require_membership_of,
     417             :                                          domain, name)) {
     418           0 :                 DEBUG(0, ("Could not parse %s into separate domain/name parts!\n",
     419             :                           require_membership_of));
     420           0 :                 return False;
     421             :         }
     422             : 
     423           0 :         ret = wbcLookupName(domain, name, &sid, &type);
     424           0 :         if (!WBC_ERROR_IS_OK(ret)) {
     425           0 :                 DEBUG(0, ("Winbindd lookupname failed to resolve %s into a SID!\n",
     426             :                           require_membership_of));
     427           0 :                 return False;
     428             :         }
     429             : 
     430           0 :         wbcSidToStringBuf(&sid, sidbuf, sizeof(sidbuf));
     431             : 
     432           0 :         require_membership_of_sid = SMB_STRDUP(sidbuf);
     433             : 
     434           0 :         if (require_membership_of_sid)
     435           0 :                 return True;
     436             : 
     437           0 :         return False;
     438             : }
     439             : 
     440             : /*
     441             :  * Get some configuration from pam_winbind.conf to see if we
     442             :  * need to contact trusted domain
     443             :  */
     444             : 
     445           0 : int get_pam_winbind_config(void)
     446             : {
     447           0 :         int ctrl = 0;
     448           0 :         struct tiniparser_dictionary *d = NULL;
     449             : 
     450           0 :         if (!opt_pam_winbind_conf || !*opt_pam_winbind_conf) {
     451           0 :                 opt_pam_winbind_conf = PAM_WINBIND_CONFIG_FILE;
     452             :         }
     453             : 
     454           0 :         d = tiniparser_load(opt_pam_winbind_conf);
     455             : 
     456           0 :         if (!d) {
     457           0 :                 return 0;
     458             :         }
     459             : 
     460           0 :         if (tiniparser_getboolean(d, "global:krb5_auth", false)) {
     461           0 :                 ctrl |= WINBIND_KRB5_AUTH;
     462             :         }
     463             : 
     464           0 :         tiniparser_freedict(d);
     465             : 
     466           0 :         return ctrl;
     467             : }
     468             : 
     469             : /* Authenticate a user with a plaintext password */
     470             : 
     471          17 : static bool check_plaintext_auth(const char *user, const char *pass,
     472             :                                  bool stdout_diagnostics)
     473             : {
     474             :         struct winbindd_request request;
     475             :         struct winbindd_response response;
     476             :         wbcErr ret;
     477             : 
     478          17 :         if (!get_require_membership_sid()) {
     479           0 :                 return False;
     480             :         }
     481             : 
     482             :         /* Send off request */
     483             : 
     484          17 :         ZERO_STRUCT(request);
     485          17 :         ZERO_STRUCT(response);
     486             : 
     487          17 :         fstrcpy(request.data.auth.user, user);
     488          17 :         fstrcpy(request.data.auth.pass, pass);
     489          17 :         if (require_membership_of_sid) {
     490          16 :                 strlcpy(request.data.auth.require_membership_of_sid,
     491             :                         require_membership_of_sid,
     492             :                         sizeof(request.data.auth.require_membership_of_sid));
     493             :         }
     494             : 
     495          17 :         if (offline_logon) {
     496           0 :                 request.flags |= WBFLAG_PAM_CACHED_LOGIN;
     497             :         }
     498             : 
     499          17 :         ret = wbcRequestResponse(NULL, WINBINDD_PAM_AUTH,
     500             :                                  &request, &response);
     501             : 
     502             :         /* Display response */
     503             : 
     504          17 :         if (stdout_diagnostics) {
     505           1 :                 if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0)) {
     506           0 :                         d_fprintf(stderr, "Reading winbind reply failed! (0x01)\n");
     507             :                 }
     508             : 
     509           1 :                 d_printf("%s: %s (0x%x)\n",
     510             :                          response.data.auth.nt_status_string,
     511             :                          response.data.auth.error_string,
     512             :                          response.data.auth.nt_status);
     513             :         } else {
     514          16 :                 if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0)) {
     515           0 :                         DEBUG(1, ("Reading winbind reply failed! (0x01)\n"));
     516             :                 }
     517             : 
     518          16 :                 DEBUG(3, ("%s: %s (0x%x)\n",
     519             :                           response.data.auth.nt_status_string,
     520             :                           response.data.auth.error_string,
     521             :                           response.data.auth.nt_status));
     522             :         }
     523             : 
     524          17 :         return WBC_ERROR_IS_OK(ret);
     525             : }
     526             : 
     527             : /* authenticate a user with an encrypted username/password */
     528             : 
     529         168 : NTSTATUS contact_winbind_auth_crap(const char *username,
     530             :                                    const char *domain,
     531             :                                    const char *workstation,
     532             :                                    const DATA_BLOB *challenge,
     533             :                                    const DATA_BLOB *lm_response,
     534             :                                    const DATA_BLOB *nt_response,
     535             :                                    uint32_t flags,
     536             :                                    uint32_t extra_logon_parameters,
     537             :                                    uint8_t lm_key[8],
     538             :                                    uint8_t user_session_key[16],
     539             :                                    uint8_t *pauthoritative,
     540             :                                    char **error_string,
     541             :                                    char **unix_name)
     542             : {
     543             :         NTSTATUS nt_status;
     544             :         wbcErr ret;
     545             :         struct winbindd_request request;
     546             :         struct winbindd_response response;
     547             : 
     548         168 :         *pauthoritative = 1;
     549             : 
     550         168 :         if (!get_require_membership_sid()) {
     551           0 :                 return NT_STATUS_INVALID_PARAMETER;
     552             :         }
     553             : 
     554         168 :         ZERO_STRUCT(request);
     555         168 :         ZERO_STRUCT(response);
     556             : 
     557         168 :         request.flags = flags;
     558             : 
     559         168 :         request.data.auth_crap.logon_parameters = extra_logon_parameters
     560         168 :                 | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
     561             : 
     562         168 :         if (opt_allow_mschapv2) {
     563           0 :                         request.data.auth_crap.logon_parameters |= MSV1_0_ALLOW_MSVCHAPV2;
     564             :         }
     565             : 
     566         168 :         if (require_membership_of_sid)
     567          16 :                 fstrcpy(request.data.auth_crap.require_membership_of_sid, require_membership_of_sid);
     568             : 
     569         168 :         fstrcpy(request.data.auth_crap.user, username);
     570         168 :         fstrcpy(request.data.auth_crap.domain, domain);
     571             : 
     572         168 :         fstrcpy(request.data.auth_crap.workstation,
     573             :                 workstation);
     574             : 
     575         168 :         memcpy(request.data.auth_crap.chal, challenge->data, MIN(challenge->length, 8));
     576             : 
     577         168 :         if (lm_response && lm_response->length) {
     578         140 :                 size_t capped_lm_response_len = MIN(
     579             :                         lm_response->length,
     580             :                         sizeof(request.data.auth_crap.lm_resp));
     581             : 
     582         140 :                 memcpy(request.data.auth_crap.lm_resp,
     583         140 :                        lm_response->data,
     584             :                        capped_lm_response_len);
     585         140 :                 request.data.auth_crap.lm_resp_len = capped_lm_response_len;
     586             :         }
     587             : 
     588         168 :         if (nt_response && nt_response->length) {
     589         136 :                 if (nt_response->length > sizeof(request.data.auth_crap.nt_resp)) {
     590          21 :                         request.flags = request.flags | WBFLAG_BIG_NTLMV2_BLOB;
     591          21 :                         request.extra_len = nt_response->length;
     592          21 :                         request.extra_data.data = SMB_MALLOC_ARRAY(char, request.extra_len);
     593          21 :                         if (request.extra_data.data == NULL) {
     594           0 :                                 return NT_STATUS_NO_MEMORY;
     595             :                         }
     596          21 :                         memcpy(request.extra_data.data, nt_response->data,
     597          21 :                                nt_response->length);
     598             : 
     599             :                 } else {
     600         115 :                         memcpy(request.data.auth_crap.nt_resp,
     601         115 :                                nt_response->data, nt_response->length);
     602             :                 }
     603         136 :                 request.data.auth_crap.nt_resp_len = nt_response->length;
     604             :         }
     605             : 
     606         168 :         ret = wbcRequestResponsePriv(
     607             :                 NULL,
     608             :                 WINBINDD_PAM_AUTH_CRAP,
     609             :                 &request,
     610             :                 &response);
     611         168 :         SAFE_FREE(request.extra_data.data);
     612             : 
     613             :         /* Display response */
     614             : 
     615         168 :         if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0)) {
     616           0 :                 nt_status = NT_STATUS_UNSUCCESSFUL;
     617           0 :                 if (error_string)
     618           0 :                         *error_string = smb_xstrdup("Reading winbind reply failed!");
     619           0 :                 winbindd_free_response(&response);
     620           0 :                 return nt_status;
     621             :         }
     622             : 
     623         168 :         nt_status = (NT_STATUS(response.data.auth.nt_status));
     624         168 :         if (!NT_STATUS_IS_OK(nt_status)) {
     625          44 :                 if (error_string)
     626          44 :                         *error_string = smb_xstrdup(response.data.auth.error_string);
     627          44 :                 *pauthoritative = response.data.auth.authoritative;
     628          44 :                 winbindd_free_response(&response);
     629          44 :                 return nt_status;
     630             :         }
     631             : 
     632         124 :         if ((flags & WBFLAG_PAM_LMKEY) && lm_key) {
     633          84 :                 memcpy(lm_key, response.data.auth.first_8_lm_hash,
     634             :                        sizeof(response.data.auth.first_8_lm_hash));
     635             :         }
     636         124 :         if ((flags & WBFLAG_PAM_USER_SESSION_KEY) && user_session_key) {
     637         124 :                 memcpy(user_session_key, response.data.auth.user_session_key,
     638             :                         sizeof(response.data.auth.user_session_key));
     639             :         }
     640             : 
     641         124 :         if (flags & WBFLAG_PAM_UNIX_NAME) {
     642          20 :                 *unix_name = SMB_STRDUP(response.data.auth.unix_username);
     643          20 :                 if (!*unix_name) {
     644           0 :                         winbindd_free_response(&response);
     645           0 :                         return NT_STATUS_NO_MEMORY;
     646             :                 }
     647             :         }
     648             : 
     649         124 :         winbindd_free_response(&response);
     650         124 :         return nt_status;
     651             : }
     652             : 
     653             : /* contact server to change user password using auth crap */
     654           0 : static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username,
     655             :                                                       const char *domain,
     656             :                                                       const DATA_BLOB new_nt_pswd,
     657             :                                                       const DATA_BLOB old_nt_hash_enc,
     658             :                                                       const DATA_BLOB new_lm_pswd,
     659             :                                                       const DATA_BLOB old_lm_hash_enc,
     660             :                                                       char  **error_string)
     661             : {
     662             :         NTSTATUS nt_status;
     663             :         wbcErr ret;
     664             :         struct winbindd_request request;
     665             :         struct winbindd_response response;
     666             : 
     667           0 :         if (!get_require_membership_sid())
     668             :         {
     669           0 :                 if(error_string)
     670           0 :                         *error_string = smb_xstrdup("Can't get membership sid.");
     671           0 :                 return NT_STATUS_INVALID_PARAMETER;
     672             :         }
     673             : 
     674           0 :         ZERO_STRUCT(request);
     675           0 :         ZERO_STRUCT(response);
     676             : 
     677           0 :         if(username != NULL)
     678           0 :                 fstrcpy(request.data.chng_pswd_auth_crap.user, username);
     679           0 :         if(domain != NULL)
     680           0 :                 fstrcpy(request.data.chng_pswd_auth_crap.domain,domain);
     681             : 
     682           0 :         if(new_nt_pswd.length)
     683             :         {
     684           0 :                 memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd, new_nt_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_nt_pswd));
     685           0 :                 request.data.chng_pswd_auth_crap.new_nt_pswd_len = new_nt_pswd.length;
     686             :         }
     687             : 
     688           0 :         if(old_nt_hash_enc.length)
     689             :         {
     690           0 :                 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));
     691           0 :                 request.data.chng_pswd_auth_crap.old_nt_hash_enc_len = old_nt_hash_enc.length;
     692             :         }
     693             : 
     694           0 :         if(new_lm_pswd.length)
     695             :         {
     696           0 :                 memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd, new_lm_pswd.data, sizeof(request.data.chng_pswd_auth_crap.new_lm_pswd));
     697           0 :                 request.data.chng_pswd_auth_crap.new_lm_pswd_len = new_lm_pswd.length;
     698             :         }
     699             : 
     700           0 :         if(old_lm_hash_enc.length)
     701             :         {
     702           0 :                 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));
     703           0 :                 request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = old_lm_hash_enc.length;
     704             :         }
     705             : 
     706           0 :         ret = wbcRequestResponse(NULL, WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP,
     707             :                                  &request, &response);
     708             : 
     709             :         /* Display response */
     710             : 
     711           0 :         if (!WBC_ERROR_IS_OK(ret) && (response.data.auth.nt_status == 0))
     712             :         {
     713           0 :                 nt_status = NT_STATUS_UNSUCCESSFUL;
     714           0 :                 if (error_string)
     715           0 :                         *error_string = smb_xstrdup("Reading winbind reply failed!");
     716           0 :                 winbindd_free_response(&response);
     717           0 :                 return nt_status;
     718             :         }
     719             : 
     720           0 :         nt_status = (NT_STATUS(response.data.auth.nt_status));
     721           0 :         if (!NT_STATUS_IS_OK(nt_status))
     722             :         {
     723           0 :                 if (error_string)
     724           0 :                         *error_string = smb_xstrdup(response.data.auth.error_string);
     725           0 :                 winbindd_free_response(&response);
     726           0 :                 return nt_status;
     727             :         }
     728             : 
     729           0 :         winbindd_free_response(&response);
     730             : 
     731           0 :     return nt_status;
     732             : }
     733             : 
     734          40 : static NTSTATUS ntlm_auth_generate_session_info(struct auth4_context *auth_context,
     735             :                                                 TALLOC_CTX *mem_ctx,
     736             :                                                 void *server_returned_info,
     737             :                                                 const char *original_user_name,
     738             :                                                 uint32_t session_info_flags,
     739             :                                                 struct auth_session_info **session_info_out)
     740             : {
     741          40 :         const char *unix_username = (const char *)server_returned_info;
     742          40 :         struct dom_sid *sids = NULL;
     743          40 :         struct auth_session_info *session_info = NULL;
     744             : 
     745          40 :         session_info = talloc_zero(mem_ctx, struct auth_session_info);
     746          40 :         if (session_info == NULL) {
     747           0 :                 return NT_STATUS_NO_MEMORY;
     748             :         }
     749             : 
     750          40 :         session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
     751          40 :         if (session_info->unix_info == NULL) {
     752           0 :                 TALLOC_FREE(session_info);
     753           0 :                 return NT_STATUS_NO_MEMORY;
     754             :         }
     755          40 :         session_info->unix_info->unix_name = talloc_strdup(session_info->unix_info,
     756             :                                                            unix_username);
     757          40 :         if (session_info->unix_info->unix_name == NULL) {
     758           0 :                 TALLOC_FREE(session_info);
     759           0 :                 return NT_STATUS_NO_MEMORY;
     760             :         }
     761             : 
     762          40 :         session_info->security_token = talloc_zero(session_info, struct security_token);
     763          40 :         if (session_info->security_token == NULL) {
     764           0 :                 TALLOC_FREE(session_info);
     765           0 :                 return NT_STATUS_NO_MEMORY;
     766             :         }
     767             : 
     768          40 :         sids = talloc_zero_array(session_info->security_token,
     769             :                                  struct dom_sid, 3);
     770          40 :         if (sids == NULL) {
     771           0 :                 TALLOC_FREE(session_info);
     772           0 :                 return NT_STATUS_NO_MEMORY;
     773             :         }
     774          40 :         sid_copy(&sids[0], &global_sid_World);
     775          40 :         sid_copy(&sids[1], &global_sid_Network);
     776          40 :         sid_copy(&sids[2], &global_sid_Authenticated_Users);
     777             : 
     778          40 :         session_info->security_token->num_sids = talloc_array_length(sids);
     779          40 :         session_info->security_token->sids = sids;
     780             : 
     781          40 :         *session_info_out = session_info;
     782             : 
     783          40 :         return NT_STATUS_OK;
     784             : }
     785             : 
     786           4 : static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_ctx,
     787             :                                                     TALLOC_CTX *mem_ctx,
     788             :                                                     struct smb_krb5_context *smb_krb5_context,
     789             :                                                     DATA_BLOB *pac_blob,
     790             :                                                     const char *princ_name,
     791             :                                                     const struct tsocket_address *remote_address,
     792             :                                                     uint32_t session_info_flags,
     793             :                                                     struct auth_session_info **session_info)
     794             : {
     795             :         TALLOC_CTX *tmp_ctx;
     796           4 :         struct PAC_LOGON_INFO *logon_info = NULL;
     797             :         char *unixuser;
     798             :         NTSTATUS status;
     799           4 :         const char *domain = "";
     800           4 :         const char *user = "";
     801             : 
     802           4 :         tmp_ctx = talloc_new(mem_ctx);
     803           4 :         if (!tmp_ctx) {
     804           0 :                 return NT_STATUS_NO_MEMORY;
     805             :         }
     806             : 
     807           4 :         if (pac_blob) {
     808             : #ifdef HAVE_KRB5
     809           4 :                 status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL,
     810             :                                                  NULL, NULL, 0, &logon_info);
     811             : #else
     812             :                 status = NT_STATUS_ACCESS_DENIED;
     813             : #endif
     814           4 :                 if (!NT_STATUS_IS_OK(status)) {
     815           0 :                         goto done;
     816             :                 }
     817             :         } else {
     818           0 :                 status = NT_STATUS_ACCESS_DENIED;
     819           0 :                 DBG_WARNING("Kerberos ticket for[%s] has no PAC: %s\n",
     820             :                             princ_name, nt_errstr(status));
     821           0 :                 goto done;
     822             :         }
     823             : 
     824           4 :         if (logon_info->info3.base.account_name.string != NULL) {
     825           4 :                 user = logon_info->info3.base.account_name.string;
     826             :         } else {
     827           0 :                 user = "";
     828             :         }
     829           4 :         if (logon_info->info3.base.logon_domain.string != NULL) {
     830           4 :                 domain = logon_info->info3.base.logon_domain.string;
     831             :         } else {
     832           0 :                 domain = "";
     833             :         }
     834             : 
     835           4 :         if (strlen(user) == 0 || strlen(domain) == 0) {
     836           0 :                 status = NT_STATUS_ACCESS_DENIED;
     837           0 :                 DBG_WARNING("Kerberos ticket for[%s] has invalid "
     838             :                             "account_name[%s]/logon_domain[%s]: %s\n",
     839             :                             princ_name,
     840             :                             logon_info->info3.base.account_name.string,
     841             :                             logon_info->info3.base.logon_domain.string,
     842             :                             nt_errstr(status));
     843           0 :                 goto done;
     844             :         }
     845             : 
     846           4 :         DBG_NOTICE("Kerberos ticket principal name is [%s] "
     847             :                    "account_name[%s]/logon_domain[%s]\n",
     848             :                    princ_name, user, domain);
     849             : 
     850           4 :         if (!strequal(domain, lp_workgroup())) {
     851           0 :                 if (!lp_allow_trusted_domains()) {
     852           0 :                         status = NT_STATUS_LOGON_FAILURE;
     853           0 :                         goto done;
     854             :                 }
     855             :         }
     856             : 
     857           4 :         unixuser = talloc_asprintf(tmp_ctx, "%s%c%s", domain, winbind_separator(), user);
     858           4 :         if (!unixuser) {
     859           0 :                 status = NT_STATUS_NO_MEMORY;
     860           0 :                 goto done;
     861             :         }
     862             : 
     863           4 :         status = ntlm_auth_generate_session_info(auth_ctx, mem_ctx, unixuser, NULL, session_info_flags, session_info);
     864             : 
     865           4 : done:
     866           4 :         TALLOC_FREE(tmp_ctx);
     867           4 :         return status;
     868             : }
     869             : 
     870             : 
     871             : 
     872             : /**
     873             :  * Return the challenge as determined by the authentication subsystem
     874             :  * @return an 8 byte random challenge
     875             :  */
     876             : 
     877          44 : static NTSTATUS ntlm_auth_get_challenge(struct auth4_context *auth_ctx,
     878             :                                         uint8_t chal[8])
     879             : {
     880          44 :         if (auth_ctx->challenge.data.length == 8) {
     881           0 :                 DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
     882             :                           auth_ctx->challenge.set_by));
     883           0 :                 memcpy(chal, auth_ctx->challenge.data.data, 8);
     884           0 :                 return NT_STATUS_OK;
     885             :         }
     886             : 
     887          44 :         if (!auth_ctx->challenge.set_by) {
     888          44 :                 generate_random_buffer(chal, 8);
     889             : 
     890          44 :                 auth_ctx->challenge.data             = data_blob_talloc(auth_ctx, chal, 8);
     891          44 :                 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
     892          44 :                 auth_ctx->challenge.set_by           = "random";
     893             :         }
     894             : 
     895          44 :         DEBUG(10,("auth_get_challenge: challenge set by %s\n",
     896             :                  auth_ctx->challenge.set_by));
     897             : 
     898          44 :         return NT_STATUS_OK;
     899             : }
     900             : 
     901             : /**
     902             :  * NTLM2 authentication modifies the effective challenge,
     903             :  * @param challenge The new challenge value
     904             :  */
     905           0 : static NTSTATUS ntlm_auth_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by)
     906             : {
     907           0 :         auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
     908           0 :         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
     909             : 
     910           0 :         auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
     911           0 :         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
     912             : 
     913           0 :         return NT_STATUS_OK;
     914             : }
     915             : 
     916             : /**
     917             :  * Check the password on an NTLMSSP login.
     918             :  *
     919             :  * Return the session keys used on the connection.
     920             :  */
     921             : 
     922             : struct winbind_pw_check_state {
     923             :         uint8_t authoritative;
     924             :         void *server_info;
     925             :         DATA_BLOB nt_session_key;
     926             :         DATA_BLOB lm_session_key;
     927             : };
     928             : 
     929          28 : static struct tevent_req *winbind_pw_check_send(
     930             :         TALLOC_CTX *mem_ctx,
     931             :         struct tevent_context *ev,
     932             :         struct auth4_context *auth4_context,
     933             :         const struct auth_usersupplied_info *user_info)
     934             : {
     935          28 :         struct tevent_req *req = NULL;
     936          28 :         struct winbind_pw_check_state *state = NULL;
     937             :         NTSTATUS nt_status;
     938          28 :         char *error_string = NULL;
     939             :         uint8_t lm_key[8];
     940             :         uint8_t user_sess_key[16];
     941          28 :         char *unix_name = NULL;
     942             : 
     943          28 :         req = tevent_req_create(
     944             :                 mem_ctx, &state, struct winbind_pw_check_state);
     945          28 :         if (req == NULL) {
     946           0 :                 return NULL;
     947             :         }
     948             : 
     949          28 :         nt_status = contact_winbind_auth_crap(
     950          28 :                 user_info->client.account_name,
     951          28 :                 user_info->client.domain_name,
     952          28 :                 user_info->workstation_name,
     953          28 :                 &auth4_context->challenge.data,
     954             :                 &user_info->password.response.lanman,
     955             :                 &user_info->password.response.nt,
     956             :                 WBFLAG_PAM_LMKEY |
     957             :                 WBFLAG_PAM_USER_SESSION_KEY |
     958             :                 WBFLAG_PAM_UNIX_NAME,
     959             :                 0,
     960             :                 lm_key, user_sess_key,
     961          28 :                 &state->authoritative,
     962             :                 &error_string,
     963             :                 &unix_name);
     964             : 
     965          28 :         if (tevent_req_nterror(req, nt_status)) {
     966           8 :                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
     967           0 :                         DBG_ERR("Login for user [%s]\\[%s]@[%s] failed due "
     968             :                                 "to [%s]\n",
     969             :                                 user_info->client.domain_name,
     970             :                                 user_info->client.account_name,
     971             :                                 user_info->workstation_name,
     972             :                                 error_string ?
     973             :                                 error_string :
     974             :                                 "unknown error (NULL)");
     975             :                 } else {
     976           8 :                         DBG_NOTICE("Login for user [%s]\\[%s]@[%s] failed due "
     977             :                                    "to [%s]\n",
     978             :                                    user_info->client.domain_name,
     979             :                                    user_info->client.account_name,
     980             :                                    user_info->workstation_name,
     981             :                                    error_string ?
     982             :                                    error_string :
     983             :                                    "unknown error (NULL)");
     984             :                 }
     985           8 :                 goto done;
     986             :         }
     987             : 
     988          20 :         if (!all_zero(lm_key, 8)) {
     989          20 :                 state->lm_session_key = data_blob_talloc(state, NULL, 16);
     990          20 :                 if (tevent_req_nomem(state->lm_session_key.data, req)) {
     991           0 :                         goto done;
     992             :                 }
     993          20 :                 memcpy(state->lm_session_key.data, lm_key, 8);
     994          20 :                 memset(state->lm_session_key.data+8, '\0', 8);
     995             :         }
     996          20 :         if (!all_zero(user_sess_key, 16)) {
     997          20 :                 state->nt_session_key = data_blob_talloc(
     998             :                         state, user_sess_key, 16);
     999          20 :                 if (tevent_req_nomem(state->nt_session_key.data, req)) {
    1000           0 :                         goto done;
    1001             :                 }
    1002             :         }
    1003          20 :         state->server_info = talloc_strdup(state, unix_name);
    1004          20 :         if (tevent_req_nomem(state->server_info, req)) {
    1005           0 :                 goto done;
    1006             :         }
    1007          20 :         tevent_req_done(req);
    1008             : 
    1009          28 : done:
    1010          28 :         SAFE_FREE(error_string);
    1011          28 :         SAFE_FREE(unix_name);
    1012          28 :         return tevent_req_post(req, ev);
    1013             : }
    1014             : 
    1015          28 : static NTSTATUS winbind_pw_check_recv(struct tevent_req *req,
    1016             :                                       TALLOC_CTX *mem_ctx,
    1017             :                                       uint8_t *pauthoritative,
    1018             :                                       void **server_returned_info,
    1019             :                                       DATA_BLOB *nt_session_key,
    1020             :                                       DATA_BLOB *lm_session_key)
    1021             : {
    1022          28 :         struct winbind_pw_check_state *state = tevent_req_data(
    1023             :                 req, struct winbind_pw_check_state);
    1024             :         NTSTATUS status;
    1025             : 
    1026          28 :         if (pauthoritative != NULL) {
    1027          28 :                 *pauthoritative = state->authoritative;
    1028             :         }
    1029             : 
    1030          28 :         if (tevent_req_is_nterror(req, &status)) {
    1031           8 :                 return status;
    1032             :         }
    1033             : 
    1034          20 :         if (server_returned_info != NULL) {
    1035          20 :                 *server_returned_info = talloc_move(
    1036             :                         mem_ctx, &state->server_info);
    1037             :         }
    1038          20 :         if (nt_session_key != NULL) {
    1039          20 :                 *nt_session_key = (DATA_BLOB) {
    1040          20 :                         .data = talloc_move(
    1041             :                                 mem_ctx, &state->nt_session_key.data),
    1042          20 :                         .length = state->nt_session_key.length,
    1043             :                 };
    1044             :         }
    1045          20 :         if (lm_session_key != NULL) {
    1046          20 :                 *lm_session_key = (DATA_BLOB) {
    1047          20 :                         .data = talloc_move(
    1048             :                                 mem_ctx, &state->lm_session_key.data),
    1049          20 :                         .length = state->lm_session_key.length,
    1050             :                 };
    1051             :         }
    1052             : 
    1053          20 :         return NT_STATUS_OK;
    1054             : }
    1055             : 
    1056             : struct local_pw_check_state {
    1057             :         uint8_t authoritative;
    1058             :         void *server_info;
    1059             :         DATA_BLOB nt_session_key;
    1060             :         DATA_BLOB lm_session_key;
    1061             : };
    1062             : 
    1063          16 : static struct tevent_req *local_pw_check_send(
    1064             :         TALLOC_CTX *mem_ctx,
    1065             :         struct tevent_context *ev,
    1066             :         struct auth4_context *auth4_context,
    1067             :         const struct auth_usersupplied_info *user_info)
    1068             : {
    1069          16 :         struct tevent_req *req = NULL;
    1070          16 :         struct local_pw_check_state *state = NULL;
    1071             :         struct samr_Password lm_pw, nt_pw;
    1072             :         NTSTATUS nt_status;
    1073             : 
    1074          16 :         req = tevent_req_create(
    1075             :                 mem_ctx, &state, struct local_pw_check_state);
    1076          16 :         if (req == NULL) {
    1077           0 :                 return NULL;
    1078             :         }
    1079          16 :         state->authoritative = 1;
    1080             : 
    1081          16 :         nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash);
    1082             : 
    1083          16 :         nt_status = ntlm_password_check(
    1084             :                 state,
    1085             :                 true,
    1086             :                 NTLM_AUTH_ON,
    1087             :                 0,
    1088          16 :                 &auth4_context->challenge.data,
    1089             :                 &user_info->password.response.lanman,
    1090             :                 &user_info->password.response.nt,
    1091          16 :                 user_info->client.account_name,
    1092          16 :                 user_info->client.account_name,
    1093          16 :                 user_info->client.domain_name,
    1094             :                 &lm_pw,
    1095             :                 &nt_pw,
    1096          16 :                 &state->nt_session_key,
    1097          16 :                 &state->lm_session_key);
    1098             : 
    1099          16 :         if (tevent_req_nterror(req, nt_status)) {
    1100           0 :                 DBG_NOTICE("Login for user [%s]\\[%s]@[%s] failed due to "
    1101             :                            "[%s]\n",
    1102             :                            user_info->client.domain_name,
    1103             :                            user_info->client.account_name,
    1104             :                            user_info->workstation_name,
    1105             :                            nt_errstr(nt_status));
    1106           0 :                 return tevent_req_post(req, ev);
    1107             :         }
    1108             : 
    1109          32 :         state->server_info = talloc_asprintf(
    1110             :                 state,
    1111             :                 "%s%c%s",
    1112          16 :                 user_info->client.domain_name,
    1113          16 :                 *lp_winbind_separator(),
    1114          16 :                 user_info->client.account_name);
    1115          16 :         if (tevent_req_nomem(state->server_info, req)) {
    1116           0 :                 return tevent_req_post(req, ev);
    1117             :         }
    1118             : 
    1119          16 :         tevent_req_done(req);
    1120          16 :         return tevent_req_post(req, ev);
    1121             : }
    1122             : 
    1123          16 : static NTSTATUS local_pw_check_recv(struct tevent_req *req,
    1124             :                                     TALLOC_CTX *mem_ctx,
    1125             :                                     uint8_t *pauthoritative,
    1126             :                                     void **server_returned_info,
    1127             :                                     DATA_BLOB *nt_session_key,
    1128             :                                     DATA_BLOB *lm_session_key)
    1129             : {
    1130          16 :         struct local_pw_check_state *state = tevent_req_data(
    1131             :                 req, struct local_pw_check_state);
    1132             :         NTSTATUS status;
    1133             : 
    1134          16 :         if (pauthoritative != NULL) {
    1135          16 :                 *pauthoritative = state->authoritative;
    1136             :         }
    1137             : 
    1138          16 :         if (tevent_req_is_nterror(req, &status)) {
    1139           0 :                 return status;
    1140             :         }
    1141             : 
    1142          16 :         if (server_returned_info != NULL) {
    1143          16 :                 *server_returned_info = talloc_move(
    1144             :                         mem_ctx, &state->server_info);
    1145             :         }
    1146          16 :         if (nt_session_key != NULL) {
    1147          16 :                 *nt_session_key = (DATA_BLOB) {
    1148          16 :                         .data = talloc_move(
    1149             :                                 mem_ctx, &state->nt_session_key.data),
    1150          16 :                         .length = state->nt_session_key.length,
    1151             :                 };
    1152             :         }
    1153          16 :         if (lm_session_key != NULL) {
    1154          16 :                 *lm_session_key = (DATA_BLOB) {
    1155          16 :                         .data = talloc_move(
    1156             :                                 mem_ctx, &state->lm_session_key.data),
    1157          16 :                         .length = state->lm_session_key.length,
    1158             :                 };
    1159             :         }
    1160             : 
    1161          16 :         return NT_STATUS_OK;
    1162             : }
    1163             : 
    1164          48 : static NTSTATUS ntlm_auth_prepare_gensec_client(TALLOC_CTX *mem_ctx,
    1165             :                                                 struct loadparm_context *lp_ctx,
    1166             :                                                 struct gensec_security **gensec_security_out)
    1167             : {
    1168          48 :         struct gensec_security *gensec_security = NULL;
    1169             :         NTSTATUS nt_status;
    1170             :         TALLOC_CTX *tmp_ctx;
    1171          48 :         const struct gensec_security_ops **backends = NULL;
    1172          48 :         struct gensec_settings *gensec_settings = NULL;
    1173          48 :         size_t idx = 0;
    1174             : 
    1175          48 :         tmp_ctx = talloc_new(mem_ctx);
    1176          48 :         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
    1177             : 
    1178          48 :         gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
    1179          48 :         if (gensec_settings == NULL) {
    1180           0 :                 DEBUG(10, ("lpcfg_gensec_settings failed\n"));
    1181           0 :                 TALLOC_FREE(tmp_ctx);
    1182           0 :                 return NT_STATUS_NO_MEMORY;
    1183             :         }
    1184             : 
    1185          48 :         backends = talloc_zero_array(gensec_settings,
    1186             :                                      const struct gensec_security_ops *, 4);
    1187          48 :         if (backends == NULL) {
    1188           0 :                 TALLOC_FREE(tmp_ctx);
    1189           0 :                 return NT_STATUS_NO_MEMORY;
    1190             :         }
    1191          48 :         gensec_settings->backends = backends;
    1192             : 
    1193          48 :         gensec_init();
    1194             : 
    1195             :         /* These need to be in priority order, krb5 before NTLMSSP */
    1196             : #if defined(HAVE_KRB5)
    1197          48 :         backends[idx++] = &gensec_gse_krb5_security_ops;
    1198             : #endif
    1199             : 
    1200          48 :         backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP);
    1201             : 
    1202          48 :         backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO);
    1203             : 
    1204          48 :         nt_status = gensec_client_start(NULL, &gensec_security,
    1205             :                                         gensec_settings);
    1206          48 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1207           0 :                 TALLOC_FREE(tmp_ctx);
    1208           0 :                 return nt_status;
    1209             :         }
    1210             : 
    1211          48 :         talloc_unlink(tmp_ctx, gensec_settings);
    1212             : 
    1213          48 :         if (opt_target_service != NULL) {
    1214           4 :                 nt_status = gensec_set_target_service(gensec_security,
    1215             :                                                       opt_target_service);
    1216           4 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1217           0 :                         TALLOC_FREE(tmp_ctx);
    1218           0 :                         return nt_status;
    1219             :                 }
    1220             :         }
    1221             : 
    1222          48 :         if (opt_target_hostname != NULL) {
    1223           4 :                 nt_status = gensec_set_target_hostname(gensec_security,
    1224             :                                                        opt_target_hostname);
    1225           4 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1226           0 :                         TALLOC_FREE(tmp_ctx);
    1227           0 :                         return nt_status;
    1228             :                 }
    1229             :         }
    1230             : 
    1231          48 :         *gensec_security_out = talloc_steal(mem_ctx, gensec_security);
    1232          48 :         TALLOC_FREE(tmp_ctx);
    1233          48 :         return NT_STATUS_OK;
    1234             : }
    1235             : 
    1236          52 : static struct auth4_context *make_auth4_context_ntlm_auth(TALLOC_CTX *mem_ctx, bool local_pw)
    1237             : {
    1238          52 :         struct auth4_context *auth4_context = talloc_zero(mem_ctx, struct auth4_context);
    1239          52 :         if (auth4_context == NULL) {
    1240           0 :                 DEBUG(10, ("failed to allocate auth4_context failed\n"));
    1241           0 :                 return NULL;
    1242             :         }
    1243          52 :         auth4_context->generate_session_info = ntlm_auth_generate_session_info;
    1244          52 :         auth4_context->generate_session_info_pac = ntlm_auth_generate_session_info_pac;
    1245          52 :         auth4_context->get_ntlm_challenge = ntlm_auth_get_challenge;
    1246          52 :         auth4_context->set_ntlm_challenge = ntlm_auth_set_challenge;
    1247          52 :         if (local_pw) {
    1248          16 :                 auth4_context->check_ntlm_password_send = local_pw_check_send;
    1249          16 :                 auth4_context->check_ntlm_password_recv = local_pw_check_recv;
    1250             :         } else {
    1251          36 :                 auth4_context->check_ntlm_password_send =
    1252             :                         winbind_pw_check_send;
    1253          36 :                 auth4_context->check_ntlm_password_recv =
    1254             :                         winbind_pw_check_recv;
    1255             :         }
    1256          52 :         auth4_context->private_data = NULL;
    1257          52 :         return auth4_context;
    1258             : }
    1259             : 
    1260          52 : static NTSTATUS ntlm_auth_prepare_gensec_server(TALLOC_CTX *mem_ctx,
    1261             :                                                 struct loadparm_context *lp_ctx,
    1262             :                                                 struct gensec_security **gensec_security_out)
    1263             : {
    1264             :         struct gensec_security *gensec_security;
    1265             :         NTSTATUS nt_status;
    1266             : 
    1267             :         TALLOC_CTX *tmp_ctx;
    1268             :         const struct gensec_security_ops **backends;
    1269             :         struct gensec_settings *gensec_settings;
    1270          52 :         size_t idx = 0;
    1271             :         struct cli_credentials *server_credentials;
    1272             : 
    1273             :         struct auth4_context *auth4_context;
    1274             : 
    1275          52 :         tmp_ctx = talloc_new(mem_ctx);
    1276          52 :         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
    1277             : 
    1278          52 :         auth4_context = make_auth4_context_ntlm_auth(tmp_ctx, opt_password);
    1279          52 :         if (auth4_context == NULL) {
    1280           0 :                 TALLOC_FREE(tmp_ctx);
    1281           0 :                 return NT_STATUS_NO_MEMORY;
    1282             :         }
    1283             : 
    1284          52 :         gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
    1285          52 :         if (lp_ctx == NULL) {
    1286           0 :                 DEBUG(10, ("lpcfg_gensec_settings failed\n"));
    1287           0 :                 TALLOC_FREE(tmp_ctx);
    1288           0 :                 return NT_STATUS_NO_MEMORY;
    1289             :         }
    1290             : 
    1291             :         /*
    1292             :          * This should be a 'netbios domain -> DNS domain'
    1293             :          * mapping, and can currently validly return NULL on
    1294             :          * poorly configured systems.
    1295             :          *
    1296             :          * This is used for the NTLMSSP server
    1297             :          *
    1298             :          */
    1299          52 :         if (opt_password) {
    1300          16 :                 gensec_settings->server_netbios_name = lp_netbios_name();
    1301          16 :                 gensec_settings->server_netbios_domain = lp_workgroup();
    1302             :         } else {
    1303          36 :                 gensec_settings->server_netbios_name = get_winbind_netbios_name();
    1304          36 :                 gensec_settings->server_netbios_domain = get_winbind_domain();
    1305             :         }
    1306             : 
    1307          52 :         gensec_settings->server_dns_domain = strlower_talloc(gensec_settings,
    1308          52 :                                                              get_mydnsdomname(talloc_tos()));
    1309          52 :         gensec_settings->server_dns_name = strlower_talloc(gensec_settings,
    1310             :                                                            get_mydnsfullname());
    1311             : 
    1312          52 :         backends = talloc_zero_array(gensec_settings,
    1313             :                                      const struct gensec_security_ops *, 4);
    1314             : 
    1315          52 :         if (backends == NULL) {
    1316           0 :                 TALLOC_FREE(tmp_ctx);
    1317           0 :                 return NT_STATUS_NO_MEMORY;
    1318             :         }
    1319          52 :         gensec_settings->backends = backends;
    1320             : 
    1321          52 :         gensec_init();
    1322             : 
    1323             :         /* These need to be in priority order, krb5 before NTLMSSP */
    1324             : #if defined(HAVE_KRB5)
    1325          52 :         backends[idx++] = &gensec_gse_krb5_security_ops;
    1326             : #endif
    1327             : 
    1328          52 :         backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_NTLMSSP);
    1329             : 
    1330          52 :         backends[idx++] = gensec_security_by_oid(NULL, GENSEC_OID_SPNEGO);
    1331             : 
    1332             :         /*
    1333             :          * This is anonymous for now, because we just use it
    1334             :          * to set the kerberos state at the moment
    1335             :          */
    1336          52 :         server_credentials = cli_credentials_init_anon(tmp_ctx);
    1337          52 :         if (!server_credentials) {
    1338           0 :                 DBG_ERR("Failed to init server credentials\n");
    1339           0 :                 return NT_STATUS_NO_MEMORY;
    1340             :         }
    1341             : 
    1342          52 :         cli_credentials_set_conf(server_credentials, lp_ctx);
    1343             : 
    1344          52 :         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC || lp_security() == SEC_ADS || USE_KERBEROS_KEYTAB) {
    1345          52 :                 cli_credentials_set_kerberos_state(server_credentials,
    1346             :                                                    CRED_USE_KERBEROS_DESIRED,
    1347             :                                                    CRED_SPECIFIED);
    1348             :         } else {
    1349           0 :                 cli_credentials_set_kerberos_state(server_credentials,
    1350             :                                                    CRED_USE_KERBEROS_DISABLED,
    1351             :                                                    CRED_SPECIFIED);
    1352             :         }
    1353             : 
    1354          52 :         nt_status = gensec_server_start(tmp_ctx, gensec_settings,
    1355             :                                         auth4_context, &gensec_security);
    1356             : 
    1357          52 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1358           0 :                 TALLOC_FREE(tmp_ctx);
    1359           0 :                 return nt_status;
    1360             :         }
    1361             : 
    1362          52 :         gensec_set_credentials(gensec_security, server_credentials);
    1363             : 
    1364             :         /*
    1365             :          * TODO: Allow the caller to pass their own description here
    1366             :          * via a command-line option
    1367             :          */
    1368          52 :         nt_status = gensec_set_target_service_description(gensec_security,
    1369             :                                                           "ntlm_auth");
    1370          52 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1371           0 :                 TALLOC_FREE(tmp_ctx);
    1372           0 :                 return nt_status;
    1373             :         }
    1374             : 
    1375          52 :         talloc_unlink(tmp_ctx, lp_ctx);
    1376          52 :         talloc_unlink(tmp_ctx, server_credentials);
    1377          52 :         talloc_unlink(tmp_ctx, gensec_settings);
    1378          52 :         talloc_unlink(tmp_ctx, auth4_context);
    1379             : 
    1380          52 :         *gensec_security_out = talloc_steal(mem_ctx, gensec_security);
    1381          52 :         TALLOC_FREE(tmp_ctx);
    1382          52 :         return NT_STATUS_OK;
    1383             : }
    1384             : 
    1385         104 : static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode,
    1386             :                                    struct loadparm_context *lp_ctx,
    1387             :                                    struct ntlm_auth_state *state,
    1388             :                                                 char *buf, int length, void **private2)
    1389             : {
    1390         104 :         manage_gensec_request(stdio_helper_mode, lp_ctx, buf, length, &state->gensec_private_1);
    1391         104 :         return;
    1392             : }
    1393             : 
    1394           8 : static void manage_squid_basic_request(enum stdio_helper_mode stdio_helper_mode,
    1395             :                                    struct loadparm_context *lp_ctx,
    1396             :                                    struct ntlm_auth_state *state,
    1397             :                                         char *buf, int length, void **private2)
    1398             : {
    1399             :         char *user, *pass;
    1400           8 :         user=buf;
    1401             : 
    1402           8 :         pass=(char *)memchr(buf,' ',length);
    1403           8 :         if (!pass) {
    1404           0 :                 DEBUG(2, ("Password not found. Denying access\n"));
    1405           0 :                 printf("ERR\n");
    1406           0 :                 return;
    1407             :         }
    1408           8 :         *pass='\0';
    1409           8 :         pass++;
    1410             : 
    1411           8 :         if (state->helper_mode == SQUID_2_5_BASIC) {
    1412           8 :                 char *end = rfc1738_unescape(user);
    1413           8 :                 if (end == NULL || (end - user) != strlen(user)) {
    1414           0 :                         DEBUG(2, ("Badly rfc1738 encoded username: %s; "
    1415             :                                   "denying access\n", user));
    1416           0 :                         printf("ERR\n");
    1417           0 :                         return;
    1418             :                 }
    1419           8 :                 end = rfc1738_unescape(pass);
    1420           8 :                 if (end == NULL || (end - pass) != strlen(pass)) {
    1421           0 :                         DEBUG(2, ("Badly encoded password for %s; "
    1422             :                                   "denying access\n", user));
    1423           0 :                         printf("ERR\n");
    1424           0 :                         return;
    1425             :                 }
    1426             :         }
    1427             : 
    1428           8 :         if (check_plaintext_auth(user, pass, False)) {
    1429           4 :                 printf("OK\n");
    1430             :         } else {
    1431           4 :                 printf("ERR\n");
    1432             :         }
    1433             : }
    1434             : 
    1435         304 : static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode,
    1436             :                                   struct loadparm_context *lp_ctx,
    1437             :                                   char *buf, int length, void **private1)
    1438             : {
    1439             :         DATA_BLOB in;
    1440         304 :         DATA_BLOB out = data_blob(NULL, 0);
    1441         304 :         char *out_base64 = NULL;
    1442         304 :         const char *reply_arg = NULL;
    1443             :         struct gensec_ntlm_state {
    1444             :                 struct gensec_security *gensec_state;
    1445             :                 const char *set_password;
    1446             :         };
    1447             :         struct gensec_ntlm_state *state;
    1448             : 
    1449             :         NTSTATUS nt_status;
    1450         304 :         bool first = false;
    1451             :         const char *reply_code;
    1452             :         struct cli_credentials *creds;
    1453             : 
    1454             :         static char *want_feature_list = NULL;
    1455             :         static DATA_BLOB session_key;
    1456             : 
    1457             :         TALLOC_CTX *mem_ctx;
    1458             : 
    1459         304 :         mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx");
    1460         304 :         if (mem_ctx == NULL) {
    1461           0 :                 printf("BH No Memory\n");
    1462           0 :                 exit(1);
    1463             :         }
    1464             : 
    1465         304 :         if (*private1) {
    1466         204 :                 state = talloc_get_type(*private1, struct gensec_ntlm_state);
    1467         204 :                 if (state == NULL) {
    1468           0 :                         DBG_WARNING("*private1 is of type %s\n",
    1469             :                                     talloc_get_name(*private1));
    1470           0 :                         printf("BH *private1 is of type %s\n",
    1471             :                                talloc_get_name(*private1));
    1472           0 :                         exit(1);
    1473             :                 }
    1474             :         } else {
    1475         100 :                 state = talloc_zero(NULL, struct gensec_ntlm_state);
    1476         100 :                 if (!state) {
    1477           0 :                         printf("BH No Memory\n");
    1478           0 :                         exit(1);
    1479             :                 }
    1480         100 :                 *private1 = state;
    1481         100 :                 if (opt_password) {
    1482          60 :                         state->set_password = opt_password;
    1483             :                 }
    1484             :         }
    1485             : 
    1486         304 :         if (strlen(buf) < 2) {
    1487           0 :                 DEBUG(1, ("query [%s] invalid", buf));
    1488           0 :                 printf("BH Query invalid\n");
    1489           0 :                 talloc_free(mem_ctx);
    1490           0 :                 return;
    1491             :         }
    1492             : 
    1493         304 :         if (strlen(buf) > 3) {
    1494         172 :                 if(strncmp(buf, "SF ", 3) == 0) {
    1495           0 :                         DEBUG(10, ("Setting flags to negotiate\n"));
    1496           0 :                         talloc_free(want_feature_list);
    1497           0 :                         want_feature_list = talloc_strndup(state, buf+3, strlen(buf)-3);
    1498           0 :                         printf("OK\n");
    1499           0 :                         talloc_free(mem_ctx);
    1500           0 :                         return;
    1501             :                 }
    1502         172 :                 in = base64_decode_data_blob_talloc(mem_ctx, buf + 3);
    1503             :         } else {
    1504         132 :                 in = data_blob(NULL, 0);
    1505             :         }
    1506             : 
    1507         304 :         if (strncmp(buf, "YR", 2) == 0) {
    1508          80 :                 if (state->gensec_state) {
    1509           0 :                         talloc_free(state->gensec_state);
    1510           0 :                         state->gensec_state = NULL;
    1511             :                 }
    1512         224 :         } else if ( (strncmp(buf, "OK", 2) == 0)) {
    1513             :                 /* Just return BH, like ntlm_auth from Samba 3 does. */
    1514           0 :                 printf("BH Command expected\n");
    1515           0 :                 talloc_free(mem_ctx);
    1516           0 :                 return;
    1517         224 :         } else if ( (strncmp(buf, "TT ", 3) != 0) &&
    1518         160 :                     (strncmp(buf, "KK ", 3) != 0) &&
    1519          96 :                     (strncmp(buf, "AF ", 3) != 0) &&
    1520          80 :                     (strncmp(buf, "NA ", 3) != 0) &&
    1521          80 :                     (strncmp(buf, "UG", 2) != 0) &&
    1522          80 :                     (strncmp(buf, "PW ", 3) != 0) &&
    1523          80 :                     (strncmp(buf, "GK", 2) != 0) &&
    1524          40 :                     (strncmp(buf, "GF", 2) != 0)) {
    1525           0 :                 DEBUG(1, ("SPNEGO request [%s] invalid prefix\n", buf));
    1526           0 :                 printf("BH SPNEGO request invalid prefix\n");
    1527           0 :                 talloc_free(mem_ctx);
    1528           0 :                 return;
    1529             :         }
    1530             : 
    1531             :         /* setup gensec */
    1532         304 :         if (!(state->gensec_state)) {
    1533         100 :                 switch (stdio_helper_mode) {
    1534          20 :                 case GSS_SPNEGO_CLIENT:
    1535             :                         /*
    1536             :                          * cached credentials are only supported by
    1537             :                          * NTLMSSP_CLIENT_1 for now.
    1538             :                          */
    1539          20 :                         use_cached_creds = false;
    1540             :                         FALL_THROUGH;
    1541          48 :                 case NTLMSSP_CLIENT_1:
    1542             :                         /* setup the client side */
    1543             : 
    1544          48 :                         if (state->set_password != NULL) {
    1545          44 :                                 use_cached_creds = false;
    1546             :                         }
    1547             : 
    1548          48 :                         if (use_cached_creds) {
    1549             :                                 struct wbcCredentialCacheParams params;
    1550           4 :                                 struct wbcCredentialCacheInfo *info = NULL;
    1551           4 :                                 struct wbcAuthErrorInfo *error = NULL;
    1552             :                                 wbcErr wbc_status;
    1553             : 
    1554           4 :                                 params.account_name = opt_username;
    1555           4 :                                 params.domain_name = opt_domain;
    1556           4 :                                 params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;
    1557           4 :                                 params.num_blobs = 0;
    1558           4 :                                 params.blobs = NULL;
    1559             : 
    1560           4 :                                 wbc_status = wbcCredentialCache(&params, &info,
    1561             :                                                                 &error);
    1562           4 :                                 wbcFreeMemory(error);
    1563           4 :                                 if (!WBC_ERROR_IS_OK(wbc_status)) {
    1564           0 :                                         use_cached_creds = false;
    1565             :                                 }
    1566           4 :                                 wbcFreeMemory(info);
    1567             :                         }
    1568             : 
    1569          48 :                         nt_status = ntlm_auth_prepare_gensec_client(state, lp_ctx,
    1570             :                                                                     &state->gensec_state);
    1571          48 :                         if (!NT_STATUS_IS_OK(nt_status)) {
    1572           0 :                                 printf("BH GENSEC mech failed to start: %s\n",
    1573             :                                        nt_errstr(nt_status));
    1574           0 :                                 talloc_free(mem_ctx);
    1575           0 :                                 return;
    1576             :                         }
    1577             : 
    1578          48 :                         creds = cli_credentials_init(state->gensec_state);
    1579          48 :                         cli_credentials_set_conf(creds, lp_ctx);
    1580          48 :                         if (opt_username) {
    1581          48 :                                 cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED);
    1582             :                         }
    1583          48 :                         if (opt_domain) {
    1584          48 :                                 cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED);
    1585             :                         }
    1586          48 :                         if (use_cached_creds) {
    1587           4 :                                 gensec_want_feature(state->gensec_state,
    1588             :                                                     GENSEC_FEATURE_NTLM_CCACHE);
    1589          44 :                         } else if (state->set_password) {
    1590          44 :                                 cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED);
    1591             :                         } else {
    1592           0 :                                 cli_credentials_set_password_callback(creds, get_password);
    1593             :                         }
    1594          48 :                         if (opt_workstation) {
    1595          48 :                                 cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED);
    1596             :                         }
    1597             : 
    1598          48 :                         gensec_set_credentials(state->gensec_state, creds);
    1599             : 
    1600          48 :                         break;
    1601          52 :                 case GSS_SPNEGO_SERVER:
    1602             :                 case SQUID_2_5_NTLMSSP:
    1603             :                 {
    1604          52 :                         nt_status = ntlm_auth_prepare_gensec_server(state, lp_ctx,
    1605             :                                                                     &state->gensec_state);
    1606          52 :                         if (!NT_STATUS_IS_OK(nt_status)) {
    1607           0 :                                 printf("BH GENSEC mech failed to start: %s\n",
    1608             :                                        nt_errstr(nt_status));
    1609           0 :                                 talloc_free(mem_ctx);
    1610           0 :                                 return;
    1611             :                         }
    1612          52 :                         break;
    1613             :                 }
    1614           0 :                 default:
    1615           0 :                         talloc_free(mem_ctx);
    1616           0 :                         abort();
    1617             :                 }
    1618             : 
    1619         100 :                 gensec_want_feature_list(state->gensec_state, want_feature_list);
    1620             : 
    1621             :                 /* Session info is not complete, do not pass to auth log */
    1622         100 :                 gensec_want_feature(state->gensec_state, GENSEC_FEATURE_NO_AUTHZ_LOG);
    1623             : 
    1624         100 :                 switch (stdio_helper_mode) {
    1625          52 :                 case GSS_SPNEGO_CLIENT:
    1626             :                 case GSS_SPNEGO_SERVER:
    1627          52 :                         nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_SPNEGO);
    1628          52 :                         if (!in.length) {
    1629          24 :                                 first = true;
    1630             :                         }
    1631          52 :                         break;
    1632          28 :                 case NTLMSSP_CLIENT_1:
    1633          28 :                         if (!in.length) {
    1634          28 :                                 first = true;
    1635             :                         }
    1636             :                         FALL_THROUGH;
    1637             :                 case SQUID_2_5_NTLMSSP:
    1638          48 :                         nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_NTLMSSP);
    1639          48 :                         break;
    1640           0 :                 default:
    1641           0 :                         talloc_free(mem_ctx);
    1642           0 :                         abort();
    1643             :                 }
    1644             : 
    1645         100 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1646           0 :                         DEBUG(1, ("GENSEC mech failed to start: %s\n", nt_errstr(nt_status)));
    1647           0 :                         printf("BH GENSEC mech failed to start\n");
    1648           0 :                         talloc_free(mem_ctx);
    1649           0 :                         return;
    1650             :                 }
    1651             : 
    1652             :         }
    1653             : 
    1654             :         /* update */
    1655             : 
    1656         304 :         if (strncmp(buf, "PW ", 3) == 0) {
    1657           0 :                 state->set_password = talloc_strndup(state,
    1658           0 :                                                      (const char *)in.data,
    1659             :                                                      in.length);
    1660             : 
    1661           0 :                 cli_credentials_set_password(gensec_get_credentials(state->gensec_state),
    1662             :                                              state->set_password,
    1663             :                                              CRED_SPECIFIED);
    1664           0 :                 printf("OK\n");
    1665           0 :                 talloc_free(mem_ctx);
    1666           0 :                 return;
    1667             :         }
    1668             : 
    1669         304 :         if (strncmp(buf, "GK", 2) == 0) {
    1670             :                 char *base64_key;
    1671          40 :                 DEBUG(10, ("Requested session key\n"));
    1672          40 :                 nt_status = gensec_session_key(state->gensec_state, mem_ctx, &session_key);
    1673          40 :                 if(!NT_STATUS_IS_OK(nt_status)) {
    1674           0 :                         DEBUG(1, ("gensec_session_key failed: %s\n", nt_errstr(nt_status)));
    1675           0 :                         printf("BH No session key\n");
    1676           0 :                         talloc_free(mem_ctx);
    1677           0 :                         return;
    1678             :                 } else {
    1679          40 :                         base64_key = base64_encode_data_blob(state, session_key);
    1680          40 :                         SMB_ASSERT(base64_key != NULL);
    1681          40 :                         printf("GK %s\n", base64_key);
    1682          40 :                         talloc_free(base64_key);
    1683             :                 }
    1684          40 :                 talloc_free(mem_ctx);
    1685          40 :                 return;
    1686             :         }
    1687             : 
    1688         264 :         if (strncmp(buf, "GF", 2) == 0) {
    1689             :                 uint32_t neg_flags;
    1690             : 
    1691          40 :                 DEBUG(10, ("Requested negotiated NTLMSSP feature flags\n"));
    1692             : 
    1693          40 :                 neg_flags = gensec_ntlmssp_neg_flags(state->gensec_state);
    1694          40 :                 if (neg_flags == 0) {
    1695           0 :                         printf("BH\n");
    1696           0 :                         talloc_free(mem_ctx);
    1697           0 :                         return;
    1698             :                 }
    1699             : 
    1700          40 :                 printf("GF 0x%08x\n", neg_flags);
    1701          40 :                 talloc_free(mem_ctx);
    1702          40 :                 return;
    1703             :         }
    1704             : 
    1705         224 :         nt_status = gensec_update(state->gensec_state, mem_ctx, in, &out);
    1706             : 
    1707             :         /* don't leak 'bad password'/'no such user' info to the network client */
    1708         224 :         nt_status = nt_status_squash(nt_status);
    1709             : 
    1710         224 :         if (out.length) {
    1711         176 :                 out_base64 = base64_encode_data_blob(mem_ctx, out);
    1712         176 :                 SMB_ASSERT(out_base64 != NULL);
    1713             :         } else {
    1714          48 :                 out_base64 = NULL;
    1715             :         }
    1716             : 
    1717         224 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1718         132 :                 reply_arg = "*";
    1719         132 :                 if (first && state->gensec_state->gensec_role == GENSEC_CLIENT) {
    1720          28 :                         reply_code = "YR";
    1721         104 :                 } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) {
    1722          36 :                         reply_code = "KK";
    1723          68 :                 } else if (state->gensec_state->gensec_role == GENSEC_SERVER) {
    1724          68 :                         reply_code = "TT";
    1725             :                 } else {
    1726           0 :                         abort();
    1727             :                 }
    1728             : 
    1729             : 
    1730          92 :         } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
    1731           0 :                 reply_code = "BH NT_STATUS_ACCESS_DENIED";
    1732           0 :                 reply_arg = nt_errstr(nt_status);
    1733           0 :                 DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
    1734          92 :         } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) {
    1735           0 :                 reply_code = "BH NT_STATUS_UNSUCCESSFUL";
    1736           0 :                 reply_arg = nt_errstr(nt_status);
    1737           0 :                 DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
    1738          92 :         } else if (!NT_STATUS_IS_OK(nt_status)) {
    1739           8 :                 reply_code = "NA";
    1740           8 :                 reply_arg = nt_errstr(nt_status);
    1741           8 :                 DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
    1742          84 :         } else if /* OK */ (state->gensec_state->gensec_role == GENSEC_SERVER) {
    1743             :                 struct auth_session_info *session_info;
    1744             : 
    1745          40 :                 nt_status = gensec_session_info(state->gensec_state, mem_ctx, &session_info);
    1746          40 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1747           0 :                         reply_code = "BH Failed to retrieve session info";
    1748           0 :                         reply_arg = nt_errstr(nt_status);
    1749           0 :                         DEBUG(1, ("GENSEC failed to retrieve the session info: %s\n", nt_errstr(nt_status)));
    1750             :                 } else {
    1751             : 
    1752          40 :                         reply_code = "AF";
    1753          40 :                         reply_arg = talloc_strdup(state->gensec_state, session_info->unix_info->unix_name);
    1754          40 :                         if (reply_arg == NULL) {
    1755           0 :                                 reply_code = "BH out of memory";
    1756           0 :                                 reply_arg = nt_errstr(NT_STATUS_NO_MEMORY);
    1757             :                         }
    1758          40 :                         talloc_free(session_info);
    1759             :                 }
    1760          44 :         } else if (state->gensec_state->gensec_role == GENSEC_CLIENT) {
    1761          44 :                 reply_code = "AF";
    1762          44 :                 reply_arg = out_base64;
    1763             :         } else {
    1764           0 :                 abort();
    1765             :         }
    1766             : 
    1767         224 :         switch (stdio_helper_mode) {
    1768          76 :         case GSS_SPNEGO_SERVER:
    1769          76 :                 printf("%s %s %s\n", reply_code,
    1770             :                        out_base64 ? out_base64 : "*",
    1771             :                        reply_arg ? reply_arg : "*");
    1772          76 :                 break;
    1773         148 :         default:
    1774         148 :                 if (out_base64) {
    1775         112 :                         printf("%s %s\n", reply_code, out_base64);
    1776          36 :                 } else if (reply_arg) {
    1777          20 :                         printf("%s %s\n", reply_code, reply_arg);
    1778             :                 } else {
    1779          16 :                         printf("%s\n", reply_code);
    1780             :                 }
    1781             :         }
    1782             : 
    1783         224 :         talloc_free(mem_ctx);
    1784         224 :         return;
    1785             : }
    1786             : 
    1787          76 : static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
    1788             :                                    struct loadparm_context *lp_ctx,
    1789             :                                    struct ntlm_auth_state *state,
    1790             :                                       char *buf, int length, void **private2)
    1791             : {
    1792          76 :         manage_gensec_request(stdio_helper_mode, lp_ctx, buf, length, &state->gensec_private_1);
    1793          76 :         return;
    1794             : }
    1795             : 
    1796          72 : static void manage_squid_ntlmssp_request(enum stdio_helper_mode stdio_helper_mode,
    1797             :                                    struct loadparm_context *lp_ctx,
    1798             :                                    struct ntlm_auth_state *state,
    1799             :                                          char *buf, int length, void **private2)
    1800             : {
    1801          72 :         manage_gensec_request(stdio_helper_mode, lp_ctx, buf, length, &state->gensec_private_1);
    1802          72 :         return;
    1803             : }
    1804             : 
    1805          52 : static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper_mode,
    1806             :                                    struct loadparm_context *lp_ctx,
    1807             :                                    struct ntlm_auth_state *state,
    1808             :                                              char *buf, int length, void **private2)
    1809             : {
    1810          52 :         manage_gensec_request(stdio_helper_mode, lp_ctx, buf, length, &state->gensec_private_1);
    1811          52 :         return;
    1812             : }
    1813             : 
    1814         112 : static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode,
    1815             :                                    struct loadparm_context *lp_ctx,
    1816             :                                    struct ntlm_auth_state *state,
    1817             :                                                 char *buf, int length, void **private2)
    1818             : {
    1819             :         char *request, *parameter;
    1820             :         static DATA_BLOB challenge;
    1821             :         static DATA_BLOB lm_response;
    1822             :         static DATA_BLOB nt_response;
    1823             :         static char *full_username;
    1824             :         static char *username;
    1825             :         static char *domain;
    1826             :         static char *plaintext_password;
    1827             :         static bool ntlm_server_1_user_session_key;
    1828             :         static bool ntlm_server_1_lm_session_key;
    1829             : 
    1830         112 :         if (strequal(buf, ".")) {
    1831          20 :                 if (!full_username && !username) {
    1832           0 :                         printf("Error: No username supplied!\n");
    1833          20 :                 } else if (plaintext_password) {
    1834             :                         /* handle this request as plaintext */
    1835           8 :                         if (!full_username) {
    1836           8 :                                 if (asprintf(&full_username, "%s%c%s", domain, winbind_separator(), username) == -1) {
    1837           0 :                                         printf("Error: Out of memory in "
    1838             :                                                "asprintf!\n.\n");
    1839           0 :                                         return;
    1840             :                                 }
    1841             :                         }
    1842           8 :                         if (check_plaintext_auth(full_username, plaintext_password, False)) {
    1843           4 :                                 printf("Authenticated: Yes\n");
    1844             :                         } else {
    1845           4 :                                 printf("Authenticated: No\n");
    1846             :                         }
    1847          12 :                 } else if (!lm_response.data && !nt_response.data) {
    1848           0 :                         printf("Error: No password supplied!\n");
    1849          12 :                 } else if (!challenge.data) {
    1850           0 :                         printf("Error: No lanman-challenge supplied!\n");
    1851             :                 } else {
    1852          12 :                         char *error_string = NULL;
    1853             :                         uchar lm_key[8];
    1854             :                         uchar user_session_key[16];
    1855          12 :                         uint32_t flags = 0;
    1856             :                         NTSTATUS nt_status;
    1857          12 :                         if (full_username && !username) {
    1858             :                                 fstring fstr_user;
    1859             :                                 fstring fstr_domain;
    1860             : 
    1861           0 :                                 if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) {
    1862             :                                         /* username might be 'tainted', don't print into our new-line deleimianted stream */
    1863           0 :                                         printf("Error: Could not parse into "
    1864             :                                                "domain and username\n");
    1865             :                                 }
    1866           0 :                                 SAFE_FREE(username);
    1867           0 :                                 SAFE_FREE(domain);
    1868           0 :                                 username = smb_xstrdup(fstr_user);
    1869           0 :                                 domain = smb_xstrdup(fstr_domain);
    1870             :                         }
    1871             : 
    1872          12 :                         if (opt_password) {
    1873             :                                 DATA_BLOB nt_session_key, lm_session_key;
    1874             :                                 struct samr_Password lm_pw, nt_pw;
    1875           8 :                                 TALLOC_CTX *mem_ctx = talloc_new(NULL);
    1876           8 :                                 ZERO_STRUCT(user_session_key);
    1877           8 :                                 ZERO_STRUCT(lm_key);
    1878             : 
    1879           8 :                                 nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash);
    1880           8 :                                 nt_status = ntlm_password_check(mem_ctx,
    1881             :                                                                 true,
    1882             :                                                                 NTLM_AUTH_ON,
    1883             :                                                                 0,
    1884             :                                                                 &challenge,
    1885             :                                                                 &lm_response,
    1886             :                                                                 &nt_response,
    1887             :                                                                 username,
    1888             :                                                                 username,
    1889             :                                                                 domain,
    1890             :                                                                 &lm_pw, &nt_pw,
    1891             :                                                                 &nt_session_key,
    1892             :                                                                 &lm_session_key);
    1893           8 :                                 error_string = smb_xstrdup(get_friendly_nt_error_msg(nt_status));
    1894           8 :                                 if (ntlm_server_1_user_session_key) {
    1895           8 :                                         if (nt_session_key.length == sizeof(user_session_key)) {
    1896           4 :                                                 memcpy(user_session_key,
    1897           4 :                                                        nt_session_key.data,
    1898             :                                                        sizeof(user_session_key));
    1899             :                                         }
    1900             :                                 }
    1901           8 :                                 if (ntlm_server_1_lm_session_key) {
    1902           0 :                                         if (lm_session_key.length == sizeof(lm_key)) {
    1903           0 :                                                 memcpy(lm_key,
    1904           0 :                                                        lm_session_key.data,
    1905             :                                                        sizeof(lm_key));
    1906             :                                         }
    1907             :                                 }
    1908           8 :                                 TALLOC_FREE(mem_ctx);
    1909             : 
    1910             :                         } else {
    1911           4 :                                 uint8_t authoritative = 1;
    1912             : 
    1913           4 :                                 if (!domain) {
    1914           0 :                                         domain = smb_xstrdup(get_winbind_domain());
    1915             :                                 }
    1916             : 
    1917           4 :                                 if (ntlm_server_1_lm_session_key)
    1918           0 :                                         flags |= WBFLAG_PAM_LMKEY;
    1919             : 
    1920           4 :                                 if (ntlm_server_1_user_session_key)
    1921           4 :                                         flags |= WBFLAG_PAM_USER_SESSION_KEY;
    1922             : 
    1923           4 :                                 nt_status = contact_winbind_auth_crap(username,
    1924             :                                                                       domain,
    1925             :                                                                       lp_netbios_name(),
    1926             :                                                                       &challenge,
    1927             :                                                                       &lm_response,
    1928             :                                                                       &nt_response,
    1929             :                                                                       flags, 0,
    1930             :                                                                       lm_key,
    1931             :                                                                       user_session_key,
    1932             :                                                                       &authoritative,
    1933             :                                                                       &error_string,
    1934             :                                                                       NULL);
    1935             :                         }
    1936             : 
    1937          12 :                         if (!NT_STATUS_IS_OK(nt_status)) {
    1938           8 :                                 printf("Authenticated: No\n");
    1939           8 :                                 printf("Authentication-Error: %s\n.\n",
    1940             :                                        error_string);
    1941             :                         } else {
    1942             :                                 char *hex_lm_key;
    1943             :                                 char *hex_user_session_key;
    1944             : 
    1945           4 :                                 printf("Authenticated: Yes\n");
    1946             : 
    1947           4 :                                 if (ntlm_server_1_lm_session_key
    1948           0 :                                     && (!all_zero(lm_key,
    1949             :                                                   sizeof(lm_key)))) {
    1950           0 :                                         hex_lm_key = hex_encode_talloc(NULL,
    1951             :                                                                 (const unsigned char *)lm_key,
    1952             :                                                                 sizeof(lm_key));
    1953           0 :                                         printf("LANMAN-Session-Key: %s\n",
    1954             :                                                hex_lm_key);
    1955           0 :                                         TALLOC_FREE(hex_lm_key);
    1956             :                                 }
    1957             : 
    1958           4 :                                 if (ntlm_server_1_user_session_key
    1959           4 :                                     && (!all_zero(user_session_key,
    1960             :                                                   sizeof(user_session_key)))) {
    1961           4 :                                         hex_user_session_key = hex_encode_talloc(NULL,
    1962             :                                                                           (const unsigned char *)user_session_key,
    1963             :                                                                           sizeof(user_session_key));
    1964           4 :                                         printf("User-Session-Key: %s\n",
    1965             :                                                hex_user_session_key);
    1966           4 :                                         TALLOC_FREE(hex_user_session_key);
    1967             :                                 }
    1968             :                         }
    1969          12 :                         SAFE_FREE(error_string);
    1970             :                 }
    1971             :                 /* clear out the state */
    1972          20 :                 challenge = data_blob_null;
    1973          20 :                 nt_response = data_blob_null;
    1974          20 :                 lm_response = data_blob_null;
    1975          20 :                 SAFE_FREE(full_username);
    1976          20 :                 SAFE_FREE(username);
    1977          20 :                 SAFE_FREE(domain);
    1978          20 :                 SAFE_FREE(plaintext_password);
    1979          20 :                 ntlm_server_1_user_session_key = False;
    1980          20 :                 ntlm_server_1_lm_session_key = False;
    1981          20 :                 printf(".\n");
    1982             : 
    1983          20 :                 return;
    1984             :         }
    1985             : 
    1986          92 :         request = buf;
    1987             : 
    1988             :         /* Indicates a base64 encoded structure */
    1989          92 :         parameter = strstr_m(request, ":: ");
    1990          92 :         if (!parameter) {
    1991          92 :                 parameter = strstr_m(request, ": ");
    1992             : 
    1993          92 :                 if (!parameter) {
    1994           0 :                         DEBUG(0, ("Parameter not found!\n"));
    1995           0 :                         printf("Error: Parameter not found!\n.\n");
    1996           0 :                         return;
    1997             :                 }
    1998             : 
    1999          92 :                 parameter[0] ='\0';
    2000          92 :                 parameter++;
    2001          92 :                 parameter[0] ='\0';
    2002          92 :                 parameter++;
    2003             : 
    2004             :         } else {
    2005           0 :                 parameter[0] ='\0';
    2006           0 :                 parameter++;
    2007           0 :                 parameter[0] ='\0';
    2008           0 :                 parameter++;
    2009           0 :                 parameter[0] ='\0';
    2010           0 :                 parameter++;
    2011             : 
    2012           0 :                 base64_decode_inplace(parameter);
    2013             :         }
    2014             : 
    2015          92 :         if (strequal(request, "LANMAN-Challenge")) {
    2016          12 :                 challenge = strhex_to_data_blob(NULL, parameter);
    2017          12 :                 if (challenge.length != 8) {
    2018           0 :                         printf("Error: hex decode of %s failed! "
    2019             :                                "(got %d bytes, expected 8)\n.\n",
    2020             :                                parameter,
    2021           0 :                                (int)challenge.length);
    2022           0 :                         challenge = data_blob_null;
    2023             :                 }
    2024          80 :         } else if (strequal(request, "NT-Response")) {
    2025          12 :                 nt_response = strhex_to_data_blob(NULL, parameter);
    2026          12 :                 if (nt_response.length < 24) {
    2027           0 :                         printf("Error: hex decode of %s failed! "
    2028             :                                "(only got %d bytes, needed at least 24)\n.\n",
    2029             :                                parameter,
    2030           0 :                                (int)nt_response.length);
    2031           0 :                         nt_response = data_blob_null;
    2032             :                 }
    2033          68 :         } else if (strequal(request, "LANMAN-Response")) {
    2034           0 :                 lm_response = strhex_to_data_blob(NULL, parameter);
    2035           0 :                 if (lm_response.length != 24) {
    2036           0 :                         printf("Error: hex decode of %s failed! "
    2037             :                                "(got %d bytes, expected 24)\n.\n",
    2038             :                                parameter,
    2039           0 :                                (int)lm_response.length);
    2040           0 :                         lm_response = data_blob_null;
    2041             :                 }
    2042          68 :         } else if (strequal(request, "Password")) {
    2043           8 :                 plaintext_password = smb_xstrdup(parameter);
    2044          60 :         } else if (strequal(request, "NT-Domain")) {
    2045          20 :                 domain = smb_xstrdup(parameter);
    2046          40 :         } else if (strequal(request, "Username")) {
    2047          20 :                 username = smb_xstrdup(parameter);
    2048          20 :         } else if (strequal(request, "Full-Username")) {
    2049           0 :                 full_username = smb_xstrdup(parameter);
    2050          20 :         } else if (strequal(request, "Request-User-Session-Key")) {
    2051          20 :                 ntlm_server_1_user_session_key = strequal(parameter, "Yes");
    2052           0 :         } else if (strequal(request, "Request-LanMan-Session-Key")) {
    2053           0 :                 ntlm_server_1_lm_session_key = strequal(parameter, "Yes");
    2054             :         } else {
    2055           0 :                 printf("Error: Unknown request %s\n.\n", request);
    2056             :         }
    2057             : }
    2058             : 
    2059           0 : static void manage_ntlm_change_password_1_request(enum stdio_helper_mode stdio_helper_mode,
    2060             :                                                   struct loadparm_context *lp_ctx,
    2061             :                                                   struct ntlm_auth_state *state,
    2062             :                                                   char *buf, int length, void **private2)
    2063             : {
    2064             :         char *request, *parameter;
    2065             :         static DATA_BLOB new_nt_pswd;
    2066             :         static DATA_BLOB old_nt_hash_enc;
    2067             :         static DATA_BLOB new_lm_pswd;
    2068             :         static DATA_BLOB old_lm_hash_enc;
    2069             :         static char *full_username = NULL;
    2070             :         static char *username = NULL;
    2071             :         static char *domain = NULL;
    2072             :         static char *newpswd =  NULL;
    2073             :         static char *oldpswd = NULL;
    2074             : 
    2075           0 :         if (strequal(buf, "."))       {
    2076           0 :                 if(newpswd && oldpswd) {
    2077             :                         uchar old_nt_hash[16];
    2078             :                         uchar old_lm_hash[16];
    2079             :                         uchar new_nt_hash[16];
    2080             :                         uchar new_lm_hash[16];
    2081             : 
    2082           0 :                         gnutls_cipher_hd_t cipher_hnd = NULL;
    2083           0 :                         gnutls_datum_t old_nt_key = {
    2084             :                                 .data = old_nt_hash,
    2085             :                                 .size = sizeof(old_nt_hash),
    2086             :                         };
    2087             :                         int rc;
    2088             : 
    2089           0 :                         new_nt_pswd = data_blob(NULL, 516);
    2090           0 :                         old_nt_hash_enc = data_blob(NULL, 16);
    2091             : 
    2092             :                         /* Calculate the MD4 hash (NT compatible) of the
    2093             :                          * password */
    2094           0 :                         E_md4hash(oldpswd, old_nt_hash);
    2095           0 :                         E_md4hash(newpswd, new_nt_hash);
    2096             : 
    2097             :                         /* E_deshash returns false for 'long'
    2098             :                            passwords (> 14 DOS chars).
    2099             : 
    2100             :                            Therefore, don't send a buffer
    2101             :                            encrypted with the truncated hash
    2102             :                            (it could allow an even easier
    2103             :                            attack on the password)
    2104             : 
    2105             :                            Likewise, obey the admin's restriction
    2106             :                         */
    2107             : 
    2108           0 :                         rc = gnutls_cipher_init(&cipher_hnd,
    2109             :                                                 GNUTLS_CIPHER_ARCFOUR_128,
    2110             :                                                 &old_nt_key,
    2111             :                                                 NULL);
    2112           0 :                         if (rc < 0) {
    2113           0 :                                 DBG_ERR("gnutls_cipher_init failed: %s\n",
    2114             :                                         gnutls_strerror(rc));
    2115           0 :                                 if (rc == GNUTLS_E_UNWANTED_ALGORITHM) {
    2116           0 :                                         DBG_ERR("Running in FIPS mode, NTLM blocked\n");
    2117             :                                 }
    2118           0 :                                 return;
    2119             :                         }
    2120             : 
    2121           0 :                         if (lp_client_lanman_auth() &&
    2122           0 :                             E_deshash(newpswd, new_lm_hash) &&
    2123           0 :                             E_deshash(oldpswd, old_lm_hash)) {
    2124           0 :                                 new_lm_pswd = data_blob(NULL, 516);
    2125           0 :                                 old_lm_hash_enc = data_blob(NULL, 16);
    2126           0 :                                 encode_pw_buffer(new_lm_pswd.data, newpswd,
    2127             :                                                  STR_UNICODE);
    2128             : 
    2129           0 :                                 rc = gnutls_cipher_encrypt(cipher_hnd,
    2130           0 :                                                            new_lm_pswd.data,
    2131             :                                                            516);
    2132           0 :                                 if (rc < 0) {
    2133           0 :                                         gnutls_cipher_deinit(cipher_hnd);
    2134           0 :                                         return;
    2135             :                                 }
    2136           0 :                                 rc = E_old_pw_hash(new_nt_hash, old_lm_hash,
    2137             :                                               old_lm_hash_enc.data);
    2138           0 :                                 if (rc != 0) {
    2139           0 :                                         DBG_ERR("E_old_pw_hash failed: %s\n",
    2140             :                                                 gnutls_strerror(rc));
    2141           0 :                                         return;
    2142             :                                 }
    2143             :                         } else {
    2144           0 :                                 new_lm_pswd.data = NULL;
    2145           0 :                                 new_lm_pswd.length = 0;
    2146           0 :                                 old_lm_hash_enc.data = NULL;
    2147           0 :                                 old_lm_hash_enc.length = 0;
    2148             :                         }
    2149             : 
    2150           0 :                         encode_pw_buffer(new_nt_pswd.data, newpswd,
    2151             :                                          STR_UNICODE);
    2152             : 
    2153           0 :                         rc = gnutls_cipher_encrypt(cipher_hnd,
    2154           0 :                                                    new_nt_pswd.data,
    2155             :                                                    516);
    2156           0 :                         gnutls_cipher_deinit(cipher_hnd);
    2157           0 :                         if (rc < 0) {
    2158           0 :                                 return;
    2159             :                         }
    2160           0 :                         rc = E_old_pw_hash(new_nt_hash, old_nt_hash,
    2161             :                                       old_nt_hash_enc.data);
    2162           0 :                         if (rc != 0) {
    2163           0 :                                 DBG_ERR("E_old_pw_hash failed: %s\n",
    2164             :                                         gnutls_strerror(rc));
    2165           0 :                                 return;
    2166             :                         }
    2167             : 
    2168           0 :                         ZERO_ARRAY(old_nt_hash);
    2169           0 :                         ZERO_ARRAY(old_lm_hash);
    2170           0 :                         ZERO_ARRAY(new_nt_hash);
    2171           0 :                         ZERO_ARRAY(new_lm_hash);
    2172             :                 }
    2173             : 
    2174           0 :                 if (!full_username && !username) {
    2175           0 :                         printf("Error: No username supplied!\n");
    2176           0 :                 } else if ((!new_nt_pswd.data || !old_nt_hash_enc.data) &&
    2177           0 :                            (!new_lm_pswd.data || old_lm_hash_enc.data) ) {
    2178           0 :                         printf("Error: No NT or LM password "
    2179             :                                "blobs supplied!\n");
    2180             :                 } else {
    2181           0 :                         char *error_string = NULL;
    2182             : 
    2183           0 :                         if (full_username && !username) {
    2184             :                                 fstring fstr_user;
    2185             :                                 fstring fstr_domain;
    2186             : 
    2187           0 :                                 if (!parse_ntlm_auth_domain_user(full_username,
    2188             :                                                                  fstr_user,
    2189             :                                                                  fstr_domain)) {
    2190             :                                         /* username might be 'tainted', don't
    2191             :                                          * print into our new-line
    2192             :                                          * deleimianted stream */
    2193           0 :                                         printf("Error: Could not "
    2194             :                                                "parse into domain and "
    2195             :                                                "username\n");
    2196           0 :                                         SAFE_FREE(username);
    2197           0 :                                         username = smb_xstrdup(full_username);
    2198             :                                 } else {
    2199           0 :                                         SAFE_FREE(username);
    2200           0 :                                         SAFE_FREE(domain);
    2201           0 :                                         username = smb_xstrdup(fstr_user);
    2202           0 :                                         domain = smb_xstrdup(fstr_domain);
    2203             :                                 }
    2204             : 
    2205             :                         }
    2206             : 
    2207           0 :                         if(!NT_STATUS_IS_OK(contact_winbind_change_pswd_auth_crap(
    2208             :                                                     username, domain,
    2209             :                                                     new_nt_pswd,
    2210             :                                                     old_nt_hash_enc,
    2211             :                                                     new_lm_pswd,
    2212             :                                                     old_lm_hash_enc,
    2213             :                                                     &error_string))) {
    2214           0 :                                 printf("Password-Change: No\n");
    2215           0 :                                 printf("Password-Change-Error: %s\n.\n",
    2216             :                                        error_string);
    2217             :                         } else {
    2218           0 :                                 printf("Password-Change: Yes\n");
    2219             :                         }
    2220             : 
    2221           0 :                         SAFE_FREE(error_string);
    2222             :                 }
    2223             :                 /* clear out the state */
    2224           0 :                 new_nt_pswd = data_blob_null;
    2225           0 :                 old_nt_hash_enc = data_blob_null;
    2226           0 :                 new_lm_pswd = data_blob_null;
    2227           0 :                 old_nt_hash_enc = data_blob_null;
    2228           0 :                 SAFE_FREE(full_username);
    2229           0 :                 SAFE_FREE(username);
    2230           0 :                 SAFE_FREE(domain);
    2231           0 :                 SAFE_FREE(newpswd);
    2232           0 :                 SAFE_FREE(oldpswd);
    2233           0 :                 printf(".\n");
    2234             : 
    2235           0 :                 return;
    2236             :         }
    2237             : 
    2238           0 :         request = buf;
    2239             : 
    2240             :         /* Indicates a base64 encoded structure */
    2241           0 :         parameter = strstr_m(request, ":: ");
    2242           0 :         if (!parameter) {
    2243           0 :                 parameter = strstr_m(request, ": ");
    2244             : 
    2245           0 :                 if (!parameter) {
    2246           0 :                         DEBUG(0, ("Parameter not found!\n"));
    2247           0 :                         printf("Error: Parameter not found!\n.\n");
    2248           0 :                         return;
    2249             :                 }
    2250             : 
    2251           0 :                 parameter[0] ='\0';
    2252           0 :                 parameter++;
    2253           0 :                 parameter[0] ='\0';
    2254           0 :                 parameter++;
    2255             :         } else {
    2256           0 :                 parameter[0] ='\0';
    2257           0 :                 parameter++;
    2258           0 :                 parameter[0] ='\0';
    2259           0 :                 parameter++;
    2260           0 :                 parameter[0] ='\0';
    2261           0 :                 parameter++;
    2262             : 
    2263           0 :                 base64_decode_inplace(parameter);
    2264             :         }
    2265             : 
    2266           0 :         if (strequal(request, "new-nt-password-blob")) {
    2267           0 :                 new_nt_pswd = strhex_to_data_blob(NULL, parameter);
    2268           0 :                 if (new_nt_pswd.length != 516) {
    2269           0 :                         printf("Error: hex decode of %s failed! "
    2270             :                                "(got %d bytes, expected 516)\n.\n",
    2271             :                                parameter,
    2272           0 :                                (int)new_nt_pswd.length);
    2273           0 :                         new_nt_pswd = data_blob_null;
    2274             :                 }
    2275           0 :         } else if (strequal(request, "old-nt-hash-blob")) {
    2276           0 :                 old_nt_hash_enc = strhex_to_data_blob(NULL, parameter);
    2277           0 :                 if (old_nt_hash_enc.length != 16) {
    2278           0 :                         printf("Error: hex decode of %s failed! "
    2279             :                                "(got %d bytes, expected 16)\n.\n",
    2280             :                                parameter,
    2281           0 :                                (int)old_nt_hash_enc.length);
    2282           0 :                         old_nt_hash_enc = data_blob_null;
    2283             :                 }
    2284           0 :         } else if (strequal(request, "new-lm-password-blob")) {
    2285           0 :                 new_lm_pswd = strhex_to_data_blob(NULL, parameter);
    2286           0 :                 if (new_lm_pswd.length != 516) {
    2287           0 :                         printf("Error: hex decode of %s failed! "
    2288             :                                "(got %d bytes, expected 516)\n.\n",
    2289             :                                parameter,
    2290           0 :                                (int)new_lm_pswd.length);
    2291           0 :                         new_lm_pswd = data_blob_null;
    2292             :                 }
    2293             :         }
    2294           0 :         else if (strequal(request, "old-lm-hash-blob"))       {
    2295           0 :                 old_lm_hash_enc = strhex_to_data_blob(NULL, parameter);
    2296           0 :                 if (old_lm_hash_enc.length != 16)
    2297             :                 {
    2298           0 :                         printf("Error: hex decode of %s failed! "
    2299             :                                "(got %d bytes, expected 16)\n.\n",
    2300             :                                parameter,
    2301           0 :                                (int)old_lm_hash_enc.length);
    2302           0 :                         old_lm_hash_enc = data_blob_null;
    2303             :                 }
    2304           0 :         } else if (strequal(request, "nt-domain")) {
    2305           0 :                 domain = smb_xstrdup(parameter);
    2306           0 :         } else if(strequal(request, "username")) {
    2307           0 :                 username = smb_xstrdup(parameter);
    2308           0 :         } else if(strequal(request, "full-username")) {
    2309           0 :                 username = smb_xstrdup(parameter);
    2310           0 :         } else if(strequal(request, "new-password")) {
    2311           0 :                 newpswd = smb_xstrdup(parameter);
    2312           0 :         } else if (strequal(request, "old-password")) {
    2313           0 :                 oldpswd = smb_xstrdup(parameter);
    2314             :         } else {
    2315           0 :                 printf("Error: Unknown request %s\n.\n", request);
    2316             :         }
    2317             : }
    2318             : 
    2319         552 : static void manage_squid_request(enum stdio_helper_mode stdio_helper_mode,
    2320             :                                    struct loadparm_context *lp_ctx,
    2321             :                                    struct ntlm_auth_state *state,
    2322             :                 stdio_helper_function fn, void **private2)
    2323             : {
    2324             :         char *buf;
    2325             :         char tmp[INITIAL_BUFFER_SIZE+1];
    2326         552 :         int length, buf_size = 0;
    2327             :         char *c;
    2328             : 
    2329         552 :         buf = talloc_strdup(state->mem_ctx, "");
    2330         552 :         if (!buf) {
    2331           0 :                 DEBUG(0, ("Failed to allocate input buffer.\n"));
    2332           0 :                 fprintf(stderr, "ERR\n");
    2333           0 :                 exit(1);
    2334             :         }
    2335             : 
    2336             :         do {
    2337             : 
    2338             :                 /* this is not a typo - x_fgets doesn't work too well under
    2339             :                  * squid */
    2340         693 :                 if (fgets(tmp, sizeof(tmp)-1, stdin) == NULL) {
    2341         128 :                         if (ferror(stdin)) {
    2342           0 :                                 DEBUG(1, ("fgets() failed! dying..... errno=%d "
    2343             :                                           "(%s)\n", ferror(stdin),
    2344             :                                           strerror(ferror(stdin))));
    2345             : 
    2346           0 :                                 exit(1);
    2347             :                         }
    2348         128 :                         exit(0);
    2349             :                 }
    2350             : 
    2351         565 :                 buf = talloc_strdup_append_buffer(buf, tmp);
    2352         565 :                 buf_size += INITIAL_BUFFER_SIZE;
    2353             : 
    2354         565 :                 if (buf_size > MAX_BUFFER_SIZE) {
    2355           0 :                         DEBUG(2, ("Oversized message\n"));
    2356           0 :                         fprintf(stderr, "ERR\n");
    2357           0 :                         talloc_free(buf);
    2358           0 :                         return;
    2359             :                 }
    2360             : 
    2361         565 :                 c = strchr(buf, '\n');
    2362         565 :         } while (c == NULL);
    2363             : 
    2364         424 :         *c = '\0';
    2365         424 :         length = c-buf;
    2366             : 
    2367         424 :         DEBUG(10, ("Got '%s' from squid (length: %d).\n",buf,length));
    2368             : 
    2369         424 :         if (buf[0] == '\0') {
    2370           0 :                 DEBUG(2, ("Invalid Request\n"));
    2371           0 :                 fprintf(stderr, "ERR\n");
    2372           0 :                 talloc_free(buf);
    2373           0 :                 return;
    2374             :         }
    2375             : 
    2376         424 :         fn(stdio_helper_mode, lp_ctx, state, buf, length, private2);
    2377         424 :         talloc_free(buf);
    2378             : }
    2379             : 
    2380             : 
    2381         128 : static void squid_stream(enum stdio_helper_mode stdio_mode,
    2382             :                          struct loadparm_context *lp_ctx,
    2383             :                          stdio_helper_function fn) {
    2384             :         TALLOC_CTX *mem_ctx;
    2385             :         struct ntlm_auth_state *state;
    2386             : 
    2387             :         /* initialize FDescs */
    2388         128 :         setbuf(stdout, NULL);
    2389         128 :         setbuf(stderr, NULL);
    2390             : 
    2391         128 :         mem_ctx = talloc_init("ntlm_auth");
    2392         128 :         if (!mem_ctx) {
    2393           0 :                 DEBUG(0, ("squid_stream: Failed to create talloc context\n"));
    2394           0 :                 fprintf(stderr, "ERR\n");
    2395           0 :                 exit(1);
    2396             :         }
    2397             : 
    2398         128 :         state = talloc_zero(mem_ctx, struct ntlm_auth_state);
    2399         128 :         if (!state) {
    2400           0 :                 DEBUG(0, ("squid_stream: Failed to talloc ntlm_auth_state\n"));
    2401           0 :                 fprintf(stderr, "ERR\n");
    2402           0 :                 exit(1);
    2403             :         }
    2404             : 
    2405         128 :         state->mem_ctx = mem_ctx;
    2406         128 :         state->helper_mode = stdio_mode;
    2407             : 
    2408         424 :         while(1) {
    2409         552 :                 TALLOC_CTX *frame = talloc_stackframe();
    2410         552 :                 manage_squid_request(stdio_mode, lp_ctx, state, fn, NULL);
    2411         424 :                 TALLOC_FREE(frame);
    2412             :         }
    2413             : }
    2414             : 
    2415             : 
    2416             : /* Authenticate a user with a challenge/response */
    2417             : 
    2418           0 : static bool check_auth_crap(void)
    2419             : {
    2420             :         NTSTATUS nt_status;
    2421           0 :         uint32_t flags = 0;
    2422             :         char lm_key[8];
    2423             :         char user_session_key[16];
    2424             :         char *hex_lm_key;
    2425             :         char *hex_user_session_key;
    2426             :         char *error_string;
    2427           0 :         uint8_t authoritative = 1;
    2428             : 
    2429           0 :         setbuf(stdout, NULL);
    2430             : 
    2431           0 :         if (request_lm_key)
    2432           0 :                 flags |= WBFLAG_PAM_LMKEY;
    2433             : 
    2434           0 :         if (request_user_session_key)
    2435           0 :                 flags |= WBFLAG_PAM_USER_SESSION_KEY;
    2436             : 
    2437           0 :         flags |= WBFLAG_PAM_NT_STATUS_SQUASH;
    2438             : 
    2439           0 :         nt_status = contact_winbind_auth_crap(opt_username, opt_domain,
    2440             :                                               opt_workstation,
    2441             :                                               &opt_challenge,
    2442             :                                               &opt_lm_response,
    2443             :                                               &opt_nt_response,
    2444             :                                               flags, 0,
    2445             :                                               (unsigned char *)lm_key,
    2446             :                                               (unsigned char *)user_session_key,
    2447             :                                               &authoritative,
    2448             :                                               &error_string, NULL);
    2449             : 
    2450           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    2451           0 :                 printf("%s (0x%x)\n", error_string,
    2452             :                        NT_STATUS_V(nt_status));
    2453           0 :                 SAFE_FREE(error_string);
    2454           0 :                 return False;
    2455             :         }
    2456             : 
    2457           0 :         if (request_lm_key
    2458           0 :             && (!all_zero((uint8_t *)lm_key, sizeof(lm_key)))) {
    2459           0 :                 hex_lm_key = hex_encode_talloc(talloc_tos(), (const unsigned char *)lm_key,
    2460             :                                         sizeof(lm_key));
    2461           0 :                 printf("LM_KEY: %s\n", hex_lm_key);
    2462           0 :                 TALLOC_FREE(hex_lm_key);
    2463             :         }
    2464           0 :         if (request_user_session_key
    2465           0 :             && (!all_zero((uint8_t *)user_session_key,
    2466             :                           sizeof(user_session_key)))) {
    2467           0 :                 hex_user_session_key = hex_encode_talloc(talloc_tos(), (const unsigned char *)user_session_key,
    2468             :                                                   sizeof(user_session_key));
    2469           0 :                 printf("NT_KEY: %s\n", hex_user_session_key);
    2470           0 :                 TALLOC_FREE(hex_user_session_key);
    2471             :         }
    2472             : 
    2473           0 :         return True;
    2474             : }
    2475             : 
    2476             : /* Main program */
    2477             : 
    2478             : enum {
    2479             :         OPT_USERNAME = 1000,
    2480             :         OPT_DOMAIN,
    2481             :         OPT_WORKSTATION,
    2482             :         OPT_CHALLENGE,
    2483             :         OPT_RESPONSE,
    2484             :         OPT_LM,
    2485             :         OPT_NT,
    2486             :         OPT_PASSWORD,
    2487             :         OPT_LM_KEY,
    2488             :         OPT_USER_SESSION_KEY,
    2489             :         OPT_DIAGNOSTICS,
    2490             :         OPT_REQUIRE_MEMBERSHIP,
    2491             :         OPT_USE_CACHED_CREDS,
    2492             :         OPT_ALLOW_MSCHAPV2,
    2493             :         OPT_PAM_WINBIND_CONF,
    2494             :         OPT_TARGET_SERVICE,
    2495             :         OPT_TARGET_HOSTNAME,
    2496             :         OPT_OFFLINE_LOGON
    2497             : };
    2498             : 
    2499         137 :  int main(int argc, const char **argv)
    2500             : {
    2501         137 :         TALLOC_CTX *frame = talloc_stackframe();
    2502             :         int opt;
    2503         137 :         const char *helper_protocol = NULL;
    2504         137 :         int diagnostics = 0;
    2505             : 
    2506         137 :         const char *hex_challenge = NULL;
    2507         137 :         const char *hex_lm_response = NULL;
    2508         137 :         const char *hex_nt_response = NULL;
    2509             :         struct loadparm_context *lp_ctx;
    2510             :         poptContext pc;
    2511             :         bool ok;
    2512             : 
    2513             :         /* NOTE: DO NOT change this interface without considering the implications!
    2514             :            This is an external interface, which other programs will use to interact
    2515             :            with this helper.
    2516             :         */
    2517             : 
    2518             :         /* We do not use single-letter command abbreviations, because they harm future
    2519             :            interface stability. */
    2520             : 
    2521         685 :         struct poptOption long_options[] = {
    2522             :                 POPT_AUTOHELP
    2523             :                 {
    2524             :                         .longName   = "helper-protocol",
    2525             :                         .shortName  = 0,
    2526             :                         .argInfo    = POPT_ARG_STRING,
    2527             :                         .arg        = &helper_protocol,
    2528             :                         .val        = OPT_DOMAIN,
    2529             :                         .descrip    = "operate as a stdio-based helper",
    2530             :                         .argDescrip = "helper protocol to use"
    2531             :                 },
    2532             :                 {
    2533             :                         .longName   = "username",
    2534             :                         .shortName  = 0,
    2535             :                         .argInfo    = POPT_ARG_STRING,
    2536             :                         .arg        = &opt_username,
    2537             :                         .val        = OPT_USERNAME,
    2538             :                         .descrip    = "username"
    2539             :                 },
    2540             :                 {
    2541             :                         .longName   = "domain",
    2542             :                         .shortName  = 0,
    2543             :                         .argInfo    = POPT_ARG_STRING,
    2544             :                         .arg        = &opt_domain,
    2545             :                         .val        = OPT_DOMAIN,
    2546             :                         .descrip    = "domain name"
    2547             :                 },
    2548             :                 {
    2549             :                         .longName   = "workstation",
    2550             :                         .shortName  = 0,
    2551             :                         .argInfo    = POPT_ARG_STRING,
    2552             :                         .arg        = &opt_workstation,
    2553             :                         .val        = OPT_WORKSTATION,
    2554             :                         .descrip    = "workstation"
    2555             :                 },
    2556             :                 {
    2557             :                         .longName   = "challenge",
    2558             :                         .shortName  = 0,
    2559             :                         .argInfo    = POPT_ARG_STRING,
    2560             :                         .arg        = &hex_challenge,
    2561             :                         .val        = OPT_CHALLENGE,
    2562             :                         .descrip    = "challenge (HEX encoded)"
    2563             :                 },
    2564             :                 {
    2565             :                         .longName   = "lm-response",
    2566             :                         .shortName  = 0,
    2567             :                         .argInfo    = POPT_ARG_STRING,
    2568             :                         .arg        = &hex_lm_response,
    2569             :                         .val        = OPT_LM,
    2570             :                         .descrip    = "LM Response to the challenge (HEX encoded)"
    2571             :                 },
    2572             :                 {
    2573             :                         .longName   = "nt-response",
    2574             :                         .shortName  = 0,
    2575             :                         .argInfo    = POPT_ARG_STRING,
    2576             :                         .arg        = &hex_nt_response,
    2577             :                         .val        = OPT_NT,
    2578             :                         .descrip    = "NT or NTLMv2 Response to the challenge (HEX encoded)"
    2579             :                 },
    2580             :                 {
    2581             :                         .longName   = "password",
    2582             :                         .shortName  = 0,
    2583             :                         .argInfo    = POPT_ARG_STRING,
    2584             :                         .arg        = &opt_password,
    2585             :                         .val        = OPT_PASSWORD,
    2586             :                         .descrip    = "User's plaintext password"
    2587             :                 },
    2588             :                 {
    2589             :                         .longName   = "request-lm-key",
    2590             :                         .shortName  = 0,
    2591             :                         .argInfo    = POPT_ARG_NONE,
    2592             :                         .arg        = &request_lm_key,
    2593             :                         .val        = OPT_LM_KEY,
    2594             :                         .descrip    = "Retrieve LM session key (or, with --diagnostics, expect LM support)"
    2595             :                 },
    2596             :                 {
    2597             :                         .longName   = "request-nt-key",
    2598             :                         .shortName  = 0,
    2599             :                         .argInfo    = POPT_ARG_NONE,
    2600             :                         .arg        = &request_user_session_key,
    2601             :                         .val        = OPT_USER_SESSION_KEY,
    2602             :                         .descrip    = "Retrieve User (NT) session key"
    2603             :                 },
    2604             :                 {
    2605             :                         .longName   = "use-cached-creds",
    2606             :                         .shortName  = 0,
    2607             :                         .argInfo    = POPT_ARG_NONE,
    2608             :                         .arg        = &use_cached_creds,
    2609             :                         .val        = OPT_USE_CACHED_CREDS,
    2610             :                         .descrip    = "Use cached credentials if no password is given"
    2611             :                 },
    2612             :                 {
    2613             :                         .longName   = "allow-mschapv2",
    2614             :                         .shortName  = 0,
    2615             :                         .argInfo    = POPT_ARG_NONE,
    2616             :                         .arg        = &opt_allow_mschapv2,
    2617             :                         .val        = OPT_ALLOW_MSCHAPV2,
    2618             :                         .descrip    = "Explicitly allow MSCHAPv2",
    2619             :                 },
    2620             :                 {
    2621             :                         .longName   = "offline-logon",
    2622             :                         .shortName  = 0,
    2623             :                         .argInfo    = POPT_ARG_NONE,
    2624             :                         .arg        = &offline_logon,
    2625             :                         .val        = OPT_OFFLINE_LOGON,
    2626             :                         .descrip    = "Use cached passwords when DC is offline"
    2627             :                 },
    2628             :                 {
    2629             :                         .longName   = "diagnostics",
    2630             :                         .shortName  = 0,
    2631             :                         .argInfo    = POPT_ARG_NONE,
    2632             :                         .arg        = &diagnostics,
    2633             :                         .val        = OPT_DIAGNOSTICS,
    2634             :                         .descrip    = "Perform diagnostics on the authentication chain"
    2635             :                 },
    2636             :                 {
    2637             :                         .longName   = "require-membership-of",
    2638             :                         .shortName  = 0,
    2639             :                         .argInfo    = POPT_ARG_STRING,
    2640             :                         .arg        = &require_membership_of,
    2641             :                         .val        = OPT_REQUIRE_MEMBERSHIP,
    2642             :                         .descrip    = "Require that a user be a member of this group (either name or SID) for authentication to succeed",
    2643             :                 },
    2644             :                 {
    2645             :                         .longName   = "pam-winbind-conf",
    2646             :                         .shortName  = 0,
    2647             :                         .argInfo    = POPT_ARG_STRING,
    2648             :                         .arg        = &opt_pam_winbind_conf,
    2649             :                         .val        = OPT_PAM_WINBIND_CONF,
    2650             :                         .descrip    = "Require that request must set WBFLAG_PAM_CONTACT_TRUSTDOM when krb5 auth is required",
    2651             :                 },
    2652             :                 {
    2653             :                         .longName   = "target-service",
    2654             :                         .shortName  = 0,
    2655             :                         .argInfo    = POPT_ARG_STRING,
    2656             :                         .arg        = &opt_target_service,
    2657             :                         .val        = OPT_TARGET_SERVICE,
    2658             :                         .descrip    = "Target service (eg http)",
    2659             :                 },
    2660             :                 {
    2661             :                         .longName   = "target-hostname",
    2662             :                         .shortName  = 0,
    2663             :                         .argInfo    = POPT_ARG_STRING,
    2664             :                         .arg        = &opt_target_hostname,
    2665             :                         .val        = OPT_TARGET_HOSTNAME,
    2666             :                         .descrip    = "Target hostname",
    2667             :                 },
    2668         137 :                 POPT_COMMON_DEBUG_ONLY
    2669         137 :                 POPT_COMMON_CONFIG_ONLY
    2670         137 :                 POPT_COMMON_OPTION_ONLY
    2671         137 :                 POPT_COMMON_VERSION
    2672             :                 POPT_TABLEEND
    2673             :         };
    2674             : 
    2675             :         /* Samba client initialisation */
    2676         137 :         smb_init_locale();
    2677             : 
    2678         137 :         ok = samba_cmdline_init(frame,
    2679             :                                 SAMBA_CMDLINE_CONFIG_CLIENT,
    2680             :                                 false /* require_smbconf */);
    2681         137 :         if (!ok) {
    2682           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
    2683           0 :                 TALLOC_FREE(frame);
    2684           0 :                 exit(1);
    2685             :         }
    2686             : 
    2687         137 :         pc = samba_popt_get_context(getprogname(),
    2688             :                                     argc,
    2689             :                                     argv,
    2690             :                                     long_options,
    2691             :                                     POPT_CONTEXT_KEEP_FIRST);
    2692         137 :         if (pc == NULL) {
    2693           0 :                 DBG_ERR("Failed to setup popt context!\n");
    2694           0 :                 TALLOC_FREE(frame);
    2695           0 :                 exit(1);
    2696             :         }
    2697             : 
    2698         580 :         while((opt = poptGetNextOpt(pc)) != -1) {
    2699         406 :                 switch (opt) {
    2700           0 :                 case OPT_CHALLENGE:
    2701           0 :                         opt_challenge = strhex_to_data_blob(NULL, hex_challenge);
    2702           0 :                         if (opt_challenge.length != 8) {
    2703           0 :                                 fprintf(stderr, "hex decode of %s failed! "
    2704             :                                         "(only got %d bytes)\n",
    2705             :                                         hex_challenge,
    2706           0 :                                         (int)opt_challenge.length);
    2707           0 :                                 exit(1);
    2708             :                         }
    2709           0 :                         break;
    2710           0 :                 case OPT_LM:
    2711           0 :                         opt_lm_response = strhex_to_data_blob(NULL, hex_lm_response);
    2712           0 :                         if (opt_lm_response.length != 24) {
    2713           0 :                                 fprintf(stderr, "hex decode of %s failed! "
    2714             :                                         "(only got %d bytes)\n",
    2715             :                                         hex_lm_response,
    2716           0 :                                         (int)opt_lm_response.length);
    2717           0 :                                 exit(1);
    2718             :                         }
    2719           0 :                         break;
    2720             : 
    2721           0 :                 case OPT_NT:
    2722           0 :                         opt_nt_response = strhex_to_data_blob(NULL, hex_nt_response);
    2723           0 :                         if (opt_nt_response.length < 24) {
    2724           0 :                                 fprintf(stderr, "hex decode of %s failed! "
    2725             :                                         "(only got %d bytes)\n",
    2726             :                                         hex_nt_response,
    2727           0 :                                         (int)opt_nt_response.length);
    2728           0 :                                 exit(1);
    2729             :                         }
    2730           0 :                         break;
    2731             : 
    2732          32 :                 case OPT_REQUIRE_MEMBERSHIP:
    2733          32 :                         if (strncasecmp_m("S-", require_membership_of, 2) == 0) {
    2734          32 :                                 require_membership_of_sid = require_membership_of;
    2735             :                         }
    2736          32 :                         break;
    2737             : 
    2738           0 :                 case POPT_ERROR_BADOPT:
    2739           0 :                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
    2740             :                                 poptBadOption(pc, 0), poptStrerror(opt));
    2741           0 :                         poptPrintUsage(pc, stderr, 0);
    2742           0 :                         exit(1);
    2743             :                 }
    2744             :         }
    2745             : 
    2746         137 :         if (opt_username) {
    2747          73 :                 char *domain = SMB_STRDUP(opt_username);
    2748          73 :                 char *p = strchr_m(domain, *lp_winbind_separator());
    2749          73 :                 if (p) {
    2750           0 :                         opt_username = p+1;
    2751           0 :                         *p = '\0';
    2752           0 :                         if (opt_domain && !strequal(opt_domain, domain)) {
    2753           0 :                                 fprintf(stderr, "Domain specified in username (%s) "
    2754             :                                         "doesn't match specified domain (%s)!\n\n",
    2755             :                                         domain, opt_domain);
    2756           0 :                                 poptPrintHelp(pc, stderr, 0);
    2757           0 :                                 exit(1);
    2758             :                         }
    2759           0 :                         opt_domain = domain;
    2760             :                 } else {
    2761          73 :                         SAFE_FREE(domain);
    2762             :                 }
    2763             :         }
    2764             : 
    2765             :         /* Note: if opt_domain is "" then send no domain */
    2766         137 :         if (opt_domain == NULL) {
    2767          65 :                 opt_domain = get_winbind_domain();
    2768             :         }
    2769             : 
    2770         137 :         if (opt_workstation == NULL) {
    2771         137 :                 opt_workstation = "";
    2772             :         }
    2773             : 
    2774         137 :         lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
    2775         137 :         if (lp_ctx == NULL) {
    2776           0 :                 fprintf(stderr, "loadparm_init_s3() failed!\n");
    2777           0 :                 exit(1);
    2778             :         }
    2779             : 
    2780         137 :         if (helper_protocol) {
    2781             :                 int i;
    2782         608 :                 for (i=0; i<NUM_HELPER_MODES; i++) {
    2783         608 :                         if (strcmp(helper_protocol, stdio_helper_protocols[i].name) == 0) {
    2784         128 :                                 squid_stream(stdio_helper_protocols[i].mode, lp_ctx, stdio_helper_protocols[i].fn);
    2785           0 :                                 exit(0);
    2786             :                         }
    2787             :                 }
    2788           0 :                 fprintf(stderr, "unknown helper protocol [%s]\n\n"
    2789             :                         "Valid helper protools:\n\n", helper_protocol);
    2790             : 
    2791           0 :                 for (i=0; i<NUM_HELPER_MODES; i++) {
    2792           0 :                         fprintf(stderr, "%s\n",
    2793           0 :                                 stdio_helper_protocols[i].name);
    2794             :                 }
    2795             : 
    2796           0 :                 exit(1);
    2797             :         }
    2798             : 
    2799           9 :         if (!opt_username || !*opt_username) {
    2800           0 :                 fprintf(stderr, "username must be specified!\n\n");
    2801           0 :                 poptPrintHelp(pc, stderr, 0);
    2802           0 :                 exit(1);
    2803             :         }
    2804             : 
    2805           9 :         if (opt_challenge.length) {
    2806           0 :                 if (!check_auth_crap()) {
    2807           0 :                         exit(1);
    2808             :                 }
    2809           0 :                 exit(0);
    2810             :         }
    2811             : 
    2812           9 :         if (!opt_password) {
    2813           0 :                 char pwd[256] = {0};
    2814             :                 int rc;
    2815             : 
    2816           0 :                 rc = samba_getpass("Password: ", pwd, sizeof(pwd), false, false);
    2817           0 :                 if (rc == 0) {
    2818           0 :                         opt_password = SMB_STRDUP(pwd);
    2819             :                 }
    2820             :         }
    2821             : 
    2822           9 :         if (diagnostics) {
    2823           8 :                 if (!diagnose_ntlm_auth(request_lm_key)) {
    2824           4 :                         poptFreeContext(pc);
    2825           4 :                         return 1;
    2826             :                 }
    2827             :         } else {
    2828             :                 fstring user;
    2829             : 
    2830           1 :                 fstr_sprintf(user, "%s%c%s", opt_domain, winbind_separator(), opt_username);
    2831           1 :                 if (!check_plaintext_auth(user, opt_password, True)) {
    2832           0 :                         poptFreeContext(pc);
    2833           0 :                         return 1;
    2834             :                 }
    2835             :         }
    2836             : 
    2837             :         /* Exit code */
    2838             : 
    2839           5 :         poptFreeContext(pc);
    2840           5 :         TALLOC_FREE(frame);
    2841           5 :         return 0;
    2842             : }

Generated by: LCOV version 1.14