X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Futils%2Fntlm_auth.c;h=82819cf1455f02282061dbaadcb947142a8a3777;hb=6400f3ee62108e3dd1e6c1013ccea9fb4b08d562;hp=7899bd0d07690c1f56fc0781bcaa2d75fed9b52d;hpb=574a6a8c350a4bab3f42f3f9cfb382db721d69b5;p=samba.git diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 7899bd0d076..82819cf1455 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -24,7 +24,22 @@ */ #include "includes.h" +#include "popt_common.h" #include "utils/ntlm_auth.h" +#include "../libcli/auth/libcli_auth.h" +#include "../libcli/auth/spnego.h" +#include "../libcli/auth/ntlmssp.h" +#include "smb_krb5.h" +#include +#include "../lib/crypto/arcfour.h" +#include "libads/kerberos_proto.h" +#include "nsswitch/winbind_client.h" + +#ifndef PAM_WINBIND_CONFIG_FILE +#define PAM_WINBIND_CONFIG_FILE "/etc/security/pam_winbind.conf" +#endif + +#define WINBIND_KRB5_AUTH 0x00000080 #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -124,6 +139,7 @@ static int use_cached_creds; static const char *require_membership_of; static const char *require_membership_of_sid; +static const char *opt_pam_winbind_conf; static char winbind_separator(void) { @@ -211,7 +227,7 @@ DATA_BLOB get_challenge(void) static DATA_BLOB chal; if (opt_challenge.length) return opt_challenge; - + chal = data_blob(NULL, 8); generate_random_buffer(chal.data, chal.length); @@ -230,7 +246,7 @@ static bool parse_ntlm_auth_domain_user(const char *domuser, fstring domain, if (!p) { return False; } - + fstrcpy(user, p+1); fstrcpy(domain, domuser); domain[PTR_DIFF(p, domuser)] = 0; @@ -278,6 +294,36 @@ static bool get_require_membership_sid(void) { return False; } + +/* + * Get some configuration from pam_winbind.conf to see if we + * need to contact trusted domain + */ + +int get_pam_winbind_config() +{ + int ctrl = 0; + dictionary *d = NULL; + + if (!opt_pam_winbind_conf || !*opt_pam_winbind_conf) { + opt_pam_winbind_conf = PAM_WINBIND_CONFIG_FILE; + } + + d = iniparser_load(CONST_DISCARD(char *, opt_pam_winbind_conf)); + + if (!d) { + return 0; + } + + if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:krb5_auth"), false)) { + ctrl |= WINBIND_KRB5_AUTH; + } + + iniparser_freedict(d); + + return ctrl; +} + /* Authenticate a user with a plaintext password */ static bool check_plaintext_auth(const char *user, const char *pass, @@ -396,7 +442,7 @@ NTSTATUS contact_winbind_auth_crap(const char *username, } request.data.auth_crap.nt_resp_len = nt_response->length; } - + result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response); SAFE_FREE(request.extra_data.data); @@ -409,7 +455,7 @@ NTSTATUS contact_winbind_auth_crap(const char *username, winbindd_free_response(&response); return nt_status; } - + nt_status = (NT_STATUS(response.data.auth.nt_status)); if (!NT_STATUS_IS_OK(nt_status)) { if (error_string) @@ -491,7 +537,7 @@ static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username, memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc, old_lm_hash_enc.data, sizeof(request.data.chng_pswd_auth_crap.old_lm_hash_enc)); request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = old_lm_hash_enc.length; } - + result = winbindd_request_response(WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, &request, &response); /* Display response */ @@ -504,7 +550,7 @@ static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username, winbindd_free_response(&response); return nt_status; } - + nt_status = (NT_STATUS(response.data.auth.nt_status)); if (!NT_STATUS_IS_OK(nt_status)) { @@ -515,7 +561,7 @@ static NTSTATUS contact_winbind_change_pswd_auth_crap(const char *username, } winbindd_free_response(&response); - + return nt_status; } @@ -529,7 +575,7 @@ static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB char *unix_name = NULL; nt_status = contact_winbind_auth_crap(ntlmssp_state->user, ntlmssp_state->domain, - ntlmssp_state->workstation, + ntlmssp_state->client.netbios_name, &ntlmssp_state->chal, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, @@ -539,23 +585,23 @@ static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB if (NT_STATUS_IS_OK(nt_status)) { if (memcmp(lm_key, zeros, 8) != 0) { - *lm_session_key = data_blob(NULL, 16); + *lm_session_key = data_blob_talloc(ntlmssp_state, NULL, 16); memcpy(lm_session_key->data, lm_key, 8); memset(lm_session_key->data+8, '\0', 8); } - + if (memcmp(user_sess_key, zeros, 16) != 0) { - *user_session_key = data_blob(user_sess_key, 16); + *user_session_key = data_blob_talloc(ntlmssp_state, user_sess_key, 16); } - ntlmssp_state->auth_context = talloc_strdup(ntlmssp_state, - unix_name); + ntlmssp_state->callback_private = talloc_strdup(ntlmssp_state, + unix_name); } else { DEBUG(NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED) ? 0 : 3, ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n", ntlmssp_state->domain, ntlmssp_state->user, - ntlmssp_state->workstation, + ntlmssp_state->client.netbios_name, error_string ? error_string : "unknown error (NULL)")); - ntlmssp_state->auth_context = NULL; + ntlmssp_state->callback_private = NULL; } SAFE_FREE(error_string); @@ -566,35 +612,36 @@ static NTSTATUS winbind_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) { NTSTATUS nt_status; - uint8 lm_pw[16], nt_pw[16]; + struct samr_Password lm_pw, nt_pw; + + nt_lm_owf_gen (opt_password, nt_pw.hash, lm_pw.hash); - nt_lm_owf_gen (opt_password, nt_pw, lm_pw); - nt_status = ntlm_password_check(ntlmssp_state, + true, true, 0, &ntlmssp_state->chal, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, - NULL, NULL, ntlmssp_state->user, ntlmssp_state->user, ntlmssp_state->domain, - lm_pw, nt_pw, user_session_key, lm_session_key); - + &lm_pw, &nt_pw, user_session_key, lm_session_key); + if (NT_STATUS_IS_OK(nt_status)) { - ntlmssp_state->auth_context = talloc_asprintf(ntlmssp_state, + ntlmssp_state->callback_private = talloc_asprintf(ntlmssp_state, "%s%c%s", ntlmssp_state->domain, *lp_winbind_separator(), ntlmssp_state->user); } else { DEBUG(3, ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n", - ntlmssp_state->domain, ntlmssp_state->user, ntlmssp_state->workstation, + ntlmssp_state->domain, ntlmssp_state->user, + ntlmssp_state->client.netbios_name, nt_errstr(nt_status))); - ntlmssp_state->auth_context = NULL; + ntlmssp_state->callback_private = NULL; } return nt_status; } -static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_state) +static NTSTATUS ntlm_auth_start_ntlmssp_client(struct ntlmssp_state **client_ntlmssp_state) { NTSTATUS status; if ( (opt_username == NULL) || (opt_domain == NULL) ) { @@ -603,12 +650,16 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_st return NT_STATUS_INVALID_PARAMETER; } - status = ntlmssp_client_start(client_ntlmssp_state); + status = ntlmssp_client_start(NULL, + global_myname(), + lp_workgroup(), + lp_client_ntlmv2_auth(), + client_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not start NTLMSSP client: %s\n", nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); + TALLOC_FREE(*client_ntlmssp_state); return status; } @@ -617,7 +668,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_st if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set username: %s\n", nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); + TALLOC_FREE(*client_ntlmssp_state); return status; } @@ -626,17 +677,17 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_st if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set domain: %s\n", nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); + TALLOC_FREE(*client_ntlmssp_state); return status; } if (opt_password) { status = ntlmssp_set_password(*client_ntlmssp_state, opt_password); - + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set password: %s\n", nt_errstr(status))); - ntlmssp_end(client_ntlmssp_state); + TALLOC_FREE(*client_ntlmssp_state); return status; } } @@ -644,10 +695,36 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_st return NT_STATUS_OK; } -static NTSTATUS ntlm_auth_start_ntlmssp_server(NTLMSSP_STATE **ntlmssp_state) +static NTSTATUS ntlm_auth_start_ntlmssp_server(struct ntlmssp_state **ntlmssp_state) { - NTSTATUS status = ntlmssp_server_start(ntlmssp_state); - + NTSTATUS status; + const char *netbios_name; + const char *netbios_domain; + const char *dns_name; + char *dns_domain; + bool is_standalone = false; + + if (opt_password) { + netbios_name = global_myname(); + netbios_domain = lp_workgroup(); + } else { + netbios_name = get_winbind_netbios_name(); + netbios_domain = get_winbind_domain(); + } + /* This should be a 'netbios domain -> DNS domain' mapping */ + dns_domain = get_mydnsdomname(talloc_tos()); + if (dns_domain) { + strlower_m(dns_domain); + } + dns_name = get_mydnsfullname(); + + status = ntlmssp_server_start(NULL, + is_standalone, + netbios_name, + netbios_domain, + dns_name, + dns_domain, + ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not start NTLMSSP server: %s\n", nt_errstr(status))); @@ -657,12 +734,8 @@ static NTSTATUS ntlm_auth_start_ntlmssp_server(NTLMSSP_STATE **ntlmssp_state) /* Have we been given a local password, or should we ask winbind? */ if (opt_password) { (*ntlmssp_state)->check_password = local_pw_check; - (*ntlmssp_state)->get_domain = lp_workgroup; - (*ntlmssp_state)->get_global_myname = global_myname; } else { (*ntlmssp_state)->check_password = winbind_pw_check; - (*ntlmssp_state)->get_domain = get_winbind_domain; - (*ntlmssp_state)->get_global_myname = get_winbind_netbios_name; } return NT_STATUS_OK; } @@ -676,12 +749,27 @@ static NTSTATUS do_ccache_ntlm_auth(DATA_BLOB initial_msg, DATA_BLOB challenge_m { struct winbindd_request wb_request; struct winbindd_response wb_response; + int ctrl = 0; NSS_STATUS result; /* get winbindd to do the ntlmssp step on our behalf */ ZERO_STRUCT(wb_request); ZERO_STRUCT(wb_response); + /* + * This is tricky here. If we set krb5_auth in pam_winbind.conf + * creds for users in trusted domain will be stored the winbindd + * child of the trusted domain. If we ask the primary domain for + * ntlm_ccache_auth, it will fail. So, we have to ask the trusted + * domain's child for ccache_ntlm_auth. that is to say, we have to + * set WBFLAG_PAM_CONTACT_TRUSTDOM in request.flags. + */ + ctrl = get_pam_winbind_config(); + + if (ctrl | WINBIND_KRB5_AUTH) { + wb_request.flags |= WBFLAG_PAM_CONTACT_TRUSTDOM; + } + fstr_sprintf(wb_request.data.ccache_ntlm_auth.user, "%s%c%s", opt_domain, winbind_separator(), opt_username); wb_request.data.ccache_ntlm_auth.uid = geteuid(); @@ -729,7 +817,7 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, NTSTATUS nt_status; if (strlen(buf) < 2) { - DEBUG(1, ("NTLMSSP query [%s] invalid", buf)); + DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); return; } @@ -768,8 +856,7 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, } if (strncmp(buf, "YR", 2) == 0) { - if (state->ntlmssp_state) - ntlmssp_end(&state->ntlmssp_state); + TALLOC_FREE(state->ntlmssp_state); state->svr_state = SERVER_INITIAL; } else if (strncmp(buf, "KK", 2) == 0) { /* No special preprocessing required */ @@ -798,7 +885,7 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, data_blob_free(&request); return; } else { - DEBUG(1, ("NTLMSSP query [%s] invalid", buf)); + DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); return; } @@ -831,13 +918,13 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status))); - ntlmssp_end(&state->ntlmssp_state); + TALLOC_FREE(state->ntlmssp_state); } else if (!NT_STATUS_IS_OK(nt_status)) { x_fprintf(x_stdout, "NA %s\n", nt_errstr(nt_status)); DEBUG(10, ("NTLMSSP %s\n", nt_errstr(nt_status))); } else { x_fprintf(x_stdout, "AF %s\n", - (char *)state->ntlmssp_state->auth_context); + (char *)state->ntlmssp_state->callback_private); DEBUG(10, ("NTLMSSP OK!\n")); if(state->have_session_key) @@ -865,7 +952,7 @@ static void manage_client_ntlmssp_request(struct ntlm_auth_state *state, } if (strlen(buf) < 2) { - DEBUG(1, ("NTLMSSP query [%s] invalid", buf)); + DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); return; } @@ -924,8 +1011,7 @@ static void manage_client_ntlmssp_request(struct ntlm_auth_state *state, } if (strncmp(buf, "YR", 2) == 0) { - if (state->ntlmssp_state) - ntlmssp_end(&state->ntlmssp_state); + TALLOC_FREE(state->ntlmssp_state); state->cli_state = CLIENT_INITIAL; } else if (strncmp(buf, "TT", 2) == 0) { /* No special preprocessing required */ @@ -957,7 +1043,7 @@ static void manage_client_ntlmssp_request(struct ntlm_auth_state *state, data_blob_free(&request); return; } else { - DEBUG(1, ("NTLMSSP query [%s] invalid", buf)); + DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); return; } @@ -1016,14 +1102,12 @@ static void manage_client_ntlmssp_request(struct ntlm_auth_state *state, DEBUG(10, ("NTLMSSP OK!\n")); state->cli_state = CLIENT_FINISHED; - if (state->ntlmssp_state) - ntlmssp_end(&state->ntlmssp_state); + TALLOC_FREE(state->ntlmssp_state); } else { x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status))); state->cli_state = CLIENT_ERROR; - if (state->ntlmssp_state) - ntlmssp_end(&state->ntlmssp_state); + TALLOC_FREE(state->ntlmssp_state); } data_blob_free(&request); @@ -1034,7 +1118,7 @@ static void manage_squid_basic_request(struct ntlm_auth_state *state, { char *user, *pass; user=buf; - + pass=(char *)memchr(buf,' ',length); if (!pass) { DEBUG(2, ("Password not found. Denying access\n")); @@ -1043,12 +1127,12 @@ static void manage_squid_basic_request(struct ntlm_auth_state *state, } *pass='\0'; pass++; - + if (state->helper_mode == SQUID_2_5_BASIC) { rfc1738_unescape(user); rfc1738_unescape(pass); } - + if (check_plaintext_auth(user, pass, False)) { x_fprintf(x_stdout, "OK\n"); } else { @@ -1059,7 +1143,7 @@ static void manage_squid_basic_request(struct ntlm_auth_state *state, static void offer_gss_spnego_mechs(void) { DATA_BLOB token; - SPNEGO_DATA spnego; + struct spnego_data spnego; ssize_t len; char *reply_base64; TALLOC_CTX *ctx = talloc_tos(); @@ -1081,22 +1165,22 @@ static void offer_gss_spnego_mechs(void) { /* Server negTokenInit (mech offerings) */ spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = SMB_XMALLOC_ARRAY(const char *, 2); + spnego.negTokenInit.mechTypes = talloc_array(ctx, const char *, 3); #ifdef HAVE_KRB5 - spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD); - spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP); + spnego.negTokenInit.mechTypes[0] = talloc_strdup(ctx, OID_KERBEROS5_OLD); + spnego.negTokenInit.mechTypes[1] = talloc_strdup(ctx, OID_NTLMSSP); spnego.negTokenInit.mechTypes[2] = NULL; #else - spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP); + spnego.negTokenInit.mechTypes[0] = talloc_strdup(ctx, OID_NTLMSSP); spnego.negTokenInit.mechTypes[1] = NULL; #endif - spnego.negTokenInit.mechListMIC = data_blob(principal, + spnego.negTokenInit.mechListMIC = data_blob_talloc(ctx, principal, strlen(principal)); - len = write_spnego_data(&token, &spnego); - free_spnego_data(&spnego); + len = spnego_write_data(ctx, &token, &spnego); + spnego_free_data(&spnego); if (len == -1) { DEBUG(1, ("Could not write SPNEGO data blob\n")); @@ -1116,8 +1200,8 @@ static void offer_gss_spnego_mechs(void) { static void manage_gss_spnego_request(struct ntlm_auth_state *state, char *buf, int length) { - static NTLMSSP_STATE *ntlmssp_state = NULL; - SPNEGO_DATA request, response; + static struct ntlmssp_state *ntlmssp_state = NULL; + struct spnego_data request, response; DATA_BLOB token; NTSTATUS status; ssize_t len; @@ -1131,18 +1215,17 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, char *reply_argument = NULL; if (strlen(buf) < 2) { - DEBUG(1, ("SPENGO query [%s] invalid", buf)); + DEBUG(1, ("SPENGO query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH SPENGO query invalid\n"); return; } if (strncmp(buf, "YR", 2) == 0) { - if (ntlmssp_state) - ntlmssp_end(&ntlmssp_state); + TALLOC_FREE(ntlmssp_state); } else if (strncmp(buf, "KK", 2) == 0) { ; } else { - DEBUG(1, ("SPENGO query [%s] invalid", buf)); + DEBUG(1, ("SPENGO query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH SPENGO query invalid\n"); return; } @@ -1165,11 +1248,11 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, } token = base64_decode_data_blob(buf + 3); - len = read_spnego_data(token, &request); + len = spnego_read_data(ctx, token, &request); data_blob_free(&token); if (len == -1) { - DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf)); + DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf)); x_fprintf(x_stdout, "BH GSS-SPNEGO query invalid\n"); return; } @@ -1181,7 +1264,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, if ( (request.negTokenInit.mechTypes == NULL) || (request.negTokenInit.mechTypes[0] == NULL) ) { - DEBUG(1, ("Client did not offer any mechanism")); + DEBUG(1, ("Client did not offer any mechanism\n")); x_fprintf(x_stdout, "BH Client did not offer any " "mechanism\n"); return; @@ -1203,7 +1286,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, x_fprintf(x_stdout, "BH Client wants a new " "NTLMSSP challenge, but " "already got one\n"); - ntlmssp_end(&ntlmssp_state); + TALLOC_FREE(ntlmssp_state); return; } @@ -1217,8 +1300,8 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, request.negTokenInit.mechToken.length); response.type = SPNEGO_NEG_TOKEN_TARG; - response.negTokenTarg.supportedMech = SMB_STRDUP(OID_NTLMSSP); - response.negTokenTarg.mechListMIC = data_blob_null; + response.negTokenTarg.supportedMech = talloc_strdup(ctx, OID_NTLMSSP); + response.negTokenTarg.mechListMIC = data_blob_talloc(ctx, NULL, 0); status = ntlmssp_update(ntlmssp_state, request.negTokenInit.mechToken, @@ -1232,7 +1315,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, char *principal; DATA_BLOB ap_rep; DATA_BLOB session_key; - struct PAC_DATA *pac_data = NULL; + struct PAC_LOGON_INFO *logon_info = NULL; if ( request.negTokenInit.mechToken.data == NULL ) { DEBUG(1, ("Client did not provide Kerberos data\n")); @@ -1242,13 +1325,13 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, } response.type = SPNEGO_NEG_TOKEN_TARG; - response.negTokenTarg.supportedMech = SMB_STRDUP(OID_KERBEROS5_OLD); - response.negTokenTarg.mechListMIC = data_blob_null; - response.negTokenTarg.responseToken = data_blob_null; + response.negTokenTarg.supportedMech = talloc_strdup(ctx, OID_KERBEROS5_OLD); + response.negTokenTarg.mechListMIC = data_blob_talloc(ctx, NULL, 0); + response.negTokenTarg.responseToken = data_blob_talloc(ctx, NULL, 0); status = ads_verify_ticket(mem_ctx, lp_realm(), 0, &request.negTokenInit.mechToken, - &principal, &pac_data, &ap_rep, + &principal, &logon_info, &ap_rep, &session_key, True); /* Now in "principal" we have the name we are @@ -1303,17 +1386,17 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, &response.negTokenTarg.responseToken); response.type = SPNEGO_NEG_TOKEN_TARG; - response.negTokenTarg.supportedMech = SMB_STRDUP(OID_NTLMSSP); - response.negTokenTarg.mechListMIC = data_blob_null; + response.negTokenTarg.supportedMech = talloc_strdup(ctx, OID_NTLMSSP); + response.negTokenTarg.mechListMIC = data_blob_talloc(ctx, NULL, 0); if (NT_STATUS_IS_OK(status)) { user = SMB_STRDUP(ntlmssp_state->user); domain = SMB_STRDUP(ntlmssp_state->domain); - ntlmssp_end(&ntlmssp_state); + TALLOC_FREE(ntlmssp_state); } } - free_spnego_data(&request); + spnego_free_data(&request); if (NT_STATUS_IS_OK(status)) { response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; @@ -1339,8 +1422,8 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, SAFE_FREE(user); SAFE_FREE(domain); - len = write_spnego_data(&token, &response); - free_spnego_data(&response); + len = spnego_write_data(ctx, &token, &response); + spnego_free_data(&response); if (len == -1) { DEBUG(1, ("Could not write SPNEGO data blob\n")); @@ -1359,15 +1442,16 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, return; } -static NTLMSSP_STATE *client_ntlmssp_state = NULL; +static struct ntlmssp_state *client_ntlmssp_state = NULL; -static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego) +static bool manage_client_ntlmssp_init(struct spnego_data spnego) { NTSTATUS status; DATA_BLOB null_blob = data_blob_null; DATA_BLOB to_server; char *to_server_base64; const char *my_mechs[] = {OID_NTLMSSP, NULL}; + TALLOC_CTX *ctx = talloc_tos(); DEBUG(10, ("Got spnego negTokenInit with NTLMSSP\n")); @@ -1398,7 +1482,8 @@ static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego) spnego.type = SPNEGO_NEG_TOKEN_INIT; spnego.negTokenInit.mechTypes = my_mechs; - spnego.negTokenInit.reqFlags = 0; + spnego.negTokenInit.reqFlags = data_blob_null; + spnego.negTokenInit.reqFlagsPadding = 0; spnego.negTokenInit.mechListMIC = null_blob; status = ntlmssp_update(client_ntlmssp_state, null_blob, @@ -1408,11 +1493,11 @@ static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego) NT_STATUS_IS_OK(status)) ) { DEBUG(1, ("Expected OK or MORE_PROCESSING_REQUIRED, got: %s\n", nt_errstr(status))); - ntlmssp_end(&client_ntlmssp_state); + TALLOC_FREE(client_ntlmssp_state); return False; } - write_spnego_data(&to_server, &spnego); + spnego_write_data(ctx, &to_server, &spnego); data_blob_free(&spnego.negTokenInit.mechToken); to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server); @@ -1422,13 +1507,14 @@ static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego) return True; } -static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) +static void manage_client_ntlmssp_targ(struct spnego_data spnego) { NTSTATUS status; DATA_BLOB null_blob = data_blob_null; DATA_BLOB request; DATA_BLOB to_server; char *to_server_base64; + TALLOC_CTX *ctx = talloc_tos(); DEBUG(10, ("Got spnego negTokenTarg with NTLMSSP\n")); @@ -1440,20 +1526,20 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) { x_fprintf(x_stdout, "NA\n"); - ntlmssp_end(&client_ntlmssp_state); + TALLOC_FREE(client_ntlmssp_state); return; } if (spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) { x_fprintf(x_stdout, "AF\n"); - ntlmssp_end(&client_ntlmssp_state); + TALLOC_FREE(client_ntlmssp_state); return; } status = ntlmssp_update(client_ntlmssp_state, spnego.negTokenTarg.responseToken, &request); - + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED from " "ntlmssp_client_update, got: %s\n", @@ -1461,7 +1547,7 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) x_fprintf(x_stdout, "BH Expected MORE_PROCESSING_REQUIRED from " "ntlmssp_client_update\n"); data_blob_free(&request); - ntlmssp_end(&client_ntlmssp_state); + TALLOC_FREE(client_ntlmssp_state); return; } @@ -1470,8 +1556,8 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) spnego.negTokenTarg.supportedMech = (char *)OID_NTLMSSP; spnego.negTokenTarg.responseToken = request; spnego.negTokenTarg.mechListMIC = null_blob; - - write_spnego_data(&to_server, &spnego); + + spnego_write_data(ctx, &to_server, &spnego); data_blob_free(&request); to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server); @@ -1483,17 +1569,18 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) #ifdef HAVE_KRB5 -static bool manage_client_krb5_init(SPNEGO_DATA spnego) +static bool manage_client_krb5_init(struct spnego_data spnego) { char *principal; DATA_BLOB tkt, to_server; DATA_BLOB session_key_krb5 = data_blob_null; - SPNEGO_DATA reply; + struct spnego_data reply; char *reply_base64; int retval; const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL}; ssize_t len; + TALLOC_CTX *ctx = talloc_tos(); if ( (spnego.negTokenInit.mechListMIC.data == NULL) || (spnego.negTokenInit.mechListMIC.length == 0) ) { @@ -1513,8 +1600,9 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego) spnego.negTokenInit.mechListMIC.length); principal[spnego.negTokenInit.mechListMIC.length] = '\0'; - retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL, NULL); - + retval = cli_krb5_get_ticket(ctx, principal, 0, + &tkt, &session_key_krb5, + 0, NULL, NULL, NULL); if (retval) { char *user = NULL; @@ -1537,8 +1625,9 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego) return False; } - retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL, NULL); - + retval = cli_krb5_get_ticket(ctx, principal, 0, + &tkt, &session_key_krb5, + 0, NULL, NULL, NULL); if (retval) { DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval))); return False; @@ -1551,11 +1640,12 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego) reply.type = SPNEGO_NEG_TOKEN_INIT; reply.negTokenInit.mechTypes = my_mechs; - reply.negTokenInit.reqFlags = 0; + reply.negTokenInit.reqFlags = data_blob_null; + reply.negTokenInit.reqFlagsPadding = 0; reply.negTokenInit.mechToken = tkt; reply.negTokenInit.mechListMIC = data_blob_null; - len = write_spnego_data(&to_server, &reply); + len = spnego_write_data(ctx, &to_server, &reply); data_blob_free(&tkt); if (len == -1) { @@ -1572,7 +1662,7 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego) return True; } -static void manage_client_krb5_targ(SPNEGO_DATA spnego) +static void manage_client_krb5_targ(struct spnego_data spnego) { switch (spnego.negTokenTarg.negResult) { case SPNEGO_ACCEPT_INCOMPLETE: @@ -1600,8 +1690,9 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state, char *buf, int length) { DATA_BLOB request; - SPNEGO_DATA spnego; + struct spnego_data spnego; ssize_t len; + TALLOC_CTX *ctx = talloc_tos(); if (!opt_username || !*opt_username) { x_fprintf(x_stderr, "username must be specified!\n\n"); @@ -1621,7 +1712,7 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state, /* We asked for a password and obviously got it :-) */ opt_password = SMB_STRNDUP((const char *)request.data, request.length); - + if (opt_password == NULL) { DEBUG(1, ("Out of memory\n")); x_fprintf(x_stdout, "BH Out of memory\n"); @@ -1646,7 +1737,7 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state, /* So we got a server challenge to generate a SPNEGO client-to-server request... */ - len = read_spnego_data(request, &spnego); + len = spnego_read_data(ctx, request, &spnego); data_blob_free(&request); if (len == -1) { @@ -1707,7 +1798,7 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state, "negResult\n"); } - ntlmssp_end(&client_ntlmssp_state); + TALLOC_FREE(client_ntlmssp_state); goto out; } @@ -1732,7 +1823,7 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state, return; out: - free_spnego_data(&spnego); + spnego_free_data(&spnego); return; } @@ -1749,7 +1840,7 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, static char *plaintext_password; static bool ntlm_server_1_user_session_key; static bool ntlm_server_1_lm_session_key; - + if (strequal(buf, ".")) { if (!full_username && !username) { x_fprintf(x_stdout, "Error: No username supplied!\n"); @@ -1779,7 +1870,7 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, if (full_username && !username) { fstring fstr_user; fstring fstr_domain; - + if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) { /* username might be 'tainted', don't print into our new-line deleimianted stream */ x_fprintf(x_stdout, "Error: Could not parse into domain and username\n"); @@ -1796,7 +1887,7 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, if (ntlm_server_1_lm_session_key) flags |= WBFLAG_PAM_LMKEY; - + if (ntlm_server_1_user_session_key) flags |= WBFLAG_PAM_USER_SESSION_KEY; @@ -1865,13 +1956,13 @@ static void manage_ntlm_server_1_request(struct ntlm_auth_state *state, parameter = strstr_m(request, ":: "); if (!parameter) { parameter = strstr_m(request, ": "); - + if (!parameter) { DEBUG(0, ("Parameter not found!\n")); x_fprintf(x_stdout, "Error: Parameter not found!\n.\n"); return; } - + parameter[0] ='\0'; parameter++; parameter[0] ='\0'; @@ -1952,7 +2043,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, new_nt_pswd = data_blob(NULL, 516); old_nt_hash_enc = data_blob(NULL, 16); - + /* Calculate the MD4 hash (NT compatible) of the * password */ E_md4hash(oldpswd, old_nt_hash); @@ -1960,7 +2051,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, /* E_deshash returns false for 'long' passwords (> 14 DOS chars). - + Therefore, don't send a buffer encrypted with the truncated hash (it could allow an even easier @@ -1977,7 +2068,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, encode_pw_buffer(new_lm_pswd.data, newpswd, STR_UNICODE); - SamOEMhash(new_lm_pswd.data, old_nt_hash, 516); + arcfour_crypt(new_lm_pswd.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_lm_hash, old_lm_hash_enc.data); } else { @@ -1989,12 +2080,12 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, encode_pw_buffer(new_nt_pswd.data, newpswd, STR_UNICODE); - - SamOEMhash(new_nt_pswd.data, old_nt_hash, 516); + + arcfour_crypt(new_nt_pswd.data, old_nt_hash, 516); E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.data); } - + if (!full_username && !username) { x_fprintf(x_stdout, "Error: No username supplied!\n"); } else if ((!new_nt_pswd.data || !old_nt_hash_enc.data) && @@ -2003,11 +2094,11 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, "blobs supplied!\n"); } else { char *error_string = NULL; - + if (full_username && !username) { fstring fstr_user; fstring fstr_domain; - + if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) { @@ -2025,7 +2116,7 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, username = smb_xstrdup(fstr_user); domain = smb_xstrdup(fstr_domain); } - + } if(!NT_STATUS_IS_OK(contact_winbind_change_pswd_auth_crap( @@ -2065,13 +2156,13 @@ static void manage_ntlm_change_password_1_request(struct ntlm_auth_state *state, parameter = strstr_m(request, ":: "); if (!parameter) { parameter = strstr_m(request, ": "); - + if (!parameter) { DEBUG(0, ("Parameter not found!\n")); x_fprintf(x_stdout, "Error: Parameter not found!\n.\n"); return; } - + parameter[0] ='\0'; parameter++; parameter[0] ='\0'; @@ -2275,7 +2366,7 @@ static bool check_auth_crap(void) if (request_lm_key && (memcmp(zeros, lm_key, sizeof(lm_key)) != 0)) { - hex_lm_key = hex_encode_talloc(NULL, (const unsigned char *)lm_key, + hex_lm_key = hex_encode_talloc(talloc_tos(), (const unsigned char *)lm_key, sizeof(lm_key)); x_fprintf(x_stdout, "LM_KEY: %s\n", hex_lm_key); TALLOC_FREE(hex_lm_key); @@ -2283,7 +2374,7 @@ static bool check_auth_crap(void) if (request_user_session_key && (memcmp(zeros, user_session_key, sizeof(user_session_key)) != 0)) { - hex_user_session_key = hex_encode_talloc(NULL, (const unsigned char *)user_session_key, + hex_user_session_key = hex_encode_talloc(talloc_tos(), (const unsigned char *)user_session_key, sizeof(user_session_key)); x_fprintf(x_stdout, "NT_KEY: %s\n", hex_user_session_key); TALLOC_FREE(hex_user_session_key); @@ -2307,7 +2398,8 @@ enum { OPT_USER_SESSION_KEY, OPT_DIAGNOSTICS, OPT_REQUIRE_MEMBERSHIP, - OPT_USE_CACHED_CREDS + OPT_USE_CACHED_CREDS, + OPT_PAM_WINBIND_CONF }; int main(int argc, const char **argv) @@ -2344,8 +2436,11 @@ enum { { "request-lm-key", 0, POPT_ARG_NONE, &request_lm_key, OPT_LM_KEY, "Retrieve LM session key"}, { "request-nt-key", 0, POPT_ARG_NONE, &request_user_session_key, OPT_USER_SESSION_KEY, "Retrieve User (NT) session key"}, { "use-cached-creds", 0, POPT_ARG_NONE, &use_cached_creds, OPT_USE_CACHED_CREDS, "Use cached credentials if no password is given"}, - { "diagnostics", 0, POPT_ARG_NONE, &diagnostics, OPT_DIAGNOSTICS, "Perform diagnostics on the authentictaion chain"}, + { "diagnostics", 0, POPT_ARG_NONE, &diagnostics, + OPT_DIAGNOSTICS, + "Perform diagnostics on the authentication chain"}, { "require-membership-of", 0, POPT_ARG_STRING, &require_membership_of, OPT_REQUIRE_MEMBERSHIP, "Require that a user be a member of this group (either name or SID) for authentication to succeed" }, + { "pam-winbind-conf", 0, POPT_ARG_STRING, &opt_pam_winbind_conf, OPT_PAM_WINBIND_CONF, "Require that request must set WBFLAG_PAM_CONTACT_TRUSTDOM when krb5 auth is required" }, POPT_COMMON_CONFIGFILE POPT_COMMON_VERSION POPT_TABLEEND