LCOV - code coverage report
Current view: top level - source3/utils - ntlm_auth.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 661 1227 53.9 %
Date: 2024-02-28 12:06:22 Functions: 28 36 77.8 %

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

Generated by: LCOV version 1.14