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

Generated by: LCOV version 1.13