diff options
Diffstat (limited to 'source3/utils/ntlm_auth.c')
-rw-r--r-- | source3/utils/ntlm_auth.c | 142 |
1 files changed, 124 insertions, 18 deletions
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 38ed9f7c9b..f8145b4a6d 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -34,6 +34,7 @@ #include "../lib/crypto/arcfour.h" #include "libads/kerberos_proto.h" #include "nsswitch/winbind_client.h" +#include "librpc/gen_ndr/krb5pac.h" #ifndef PAM_WINBIND_CONFIG_FILE #define PAM_WINBIND_CONFIG_FILE "/etc/security/pam_winbind.conf" @@ -812,15 +813,17 @@ static NTSTATUS do_ccache_ntlm_auth(DATA_BLOB initial_msg, DATA_BLOB challenge_m return NT_STATUS_MORE_PROCESSING_REQUIRED; } -static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, - char *buf, int length) +static void manage_squid_ntlmssp_request_int(struct ntlm_auth_state *state, + char *buf, int length, + TALLOC_CTX *mem_ctx, + char **response) { DATA_BLOB request, reply; NTSTATUS nt_status; if (strlen(buf) < 2) { DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); - x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); + *response = talloc_strdup(mem_ctx, "BH NTLMSSP query invalid"); return; } @@ -830,7 +833,7 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, TALLOC_FREE(state->want_feature_list); state->want_feature_list = talloc_strdup(state->mem_ctx, buf+3); - x_fprintf(x_stdout, "OK\n"); + *response = talloc_strdup(mem_ctx, "OK"); return; } request = base64_decode_data_blob(buf + 3); @@ -847,12 +850,12 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, if (opt_password == NULL) { DEBUG(1, ("Out of memory\n")); - x_fprintf(x_stdout, "BH Out of memory\n"); + *response = talloc_strdup(mem_ctx, "BH Out of memory"); data_blob_free(&request); return; } - x_fprintf(x_stdout, "OK\n"); + *response = talloc_strdup(mem_ctx, "OK"); data_blob_free(&request); return; } @@ -866,10 +869,11 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, DEBUG(10, ("Requested negotiated NTLMSSP flags\n")); if (state->svr_state == SERVER_FINISHED) { - x_fprintf(x_stdout, "GF 0x%08x\n", state->neg_flags); + *response = talloc_asprintf(mem_ctx, "GF 0x%08x", + state->neg_flags); } else { - x_fprintf(x_stdout, "BH\n"); + *response = talloc_strdup(mem_ctx, "BH\n"); } data_blob_free(&request); return; @@ -878,17 +882,18 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, if(state->have_session_key) { char *key64 = base64_encode_data_blob(state->mem_ctx, state->session_key); - x_fprintf(x_stdout, "GK %s\n", key64?key64:"<NULL>"); + *response = talloc_asprintf(mem_ctx, "GK %s", + key64 ? key64 : "<NULL>"); TALLOC_FREE(key64); } else { - x_fprintf(x_stdout, "BH\n"); + *response = talloc_strdup(mem_ctx, "BH"); } data_blob_free(&request); return; } else { DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); - x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); + *response = talloc_strdup(mem_ctx, "BH NTLMSSP query invalid"); return; } @@ -896,7 +901,8 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, nt_status = ntlm_auth_start_ntlmssp_server( &state->ntlmssp_state); if (!NT_STATUS_IS_OK(nt_status)) { - x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); + *response = talloc_asprintf( + mem_ctx, "BH %s", nt_errstr(nt_status)); return; } ntlmssp_want_feature_list(state->ntlmssp_state, @@ -911,22 +917,25 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { char *reply_base64 = base64_encode_data_blob(state->mem_ctx, reply); - x_fprintf(x_stdout, "TT %s\n", reply_base64); + *response = talloc_asprintf(mem_ctx, "TT %s", reply_base64); TALLOC_FREE(reply_base64); data_blob_free(&reply); state->svr_state = SERVER_CHALLENGE; DEBUG(10, ("NTLMSSP challenge\n")); } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) { - x_fprintf(x_stdout, "BH %s\n", nt_errstr(nt_status)); + *response = talloc_asprintf(mem_ctx, "BH %s", + nt_errstr(nt_status)); DEBUG(0, ("NTLMSSP BH: %s\n", nt_errstr(nt_status))); TALLOC_FREE(state->ntlmssp_state); } else if (!NT_STATUS_IS_OK(nt_status)) { - x_fprintf(x_stdout, "NA %s\n", nt_errstr(nt_status)); + *response = talloc_asprintf(mem_ctx, "NA %s", + 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->callback_private); + *response = talloc_asprintf( + mem_ctx, "AF %s", + (char *)state->ntlmssp_state->callback_private); DEBUG(10, ("NTLMSSP OK!\n")); if(state->have_session_key) @@ -942,6 +951,22 @@ static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, data_blob_free(&request); } +static void manage_squid_ntlmssp_request(struct ntlm_auth_state *state, + char *buf, int length) +{ + char *response; + + manage_squid_ntlmssp_request_int(state, buf, length, + talloc_tos(), &response); + + if (response == NULL) { + x_fprintf(x_stdout, "BH Out of memory\n"); + return; + } + x_fprintf(x_stdout, "%s\n", response); + TALLOC_FREE(response); +} + static void manage_client_ntlmssp_request(struct ntlm_auth_state *state, char *buf, int length) { @@ -1199,6 +1224,45 @@ static void offer_gss_spnego_mechs(void) { return; } +bool spnego_parse_krb5_wrap(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2]) +{ + bool ret; + ASN1_DATA *data; + int data_remaining; + + data = asn1_init(talloc_tos()); + if (data == NULL) { + return false; + } + + asn1_load(data, blob); + asn1_start_tag(data, ASN1_APPLICATION(0)); + asn1_check_OID(data, OID_KERBEROS5); + + data_remaining = asn1_tag_remaining(data); + + if (data_remaining < 3) { + data->has_error = True; + } else { + asn1_read(data, tok_id, 2); + data_remaining -= 2; + *ticket = data_blob_talloc(ctx, NULL, data_remaining); + asn1_read(data, ticket->data, ticket->length); + } + + asn1_end_tag(data); + + ret = !data->has_error; + + if (data->has_error) { + data_blob_free(ticket); + } + + asn1_free(data); + + return ret; +} + static void manage_gss_spnego_request(struct ntlm_auth_state *state, char *buf, int length) { @@ -1250,6 +1314,31 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, } token = base64_decode_data_blob(buf + 3); + + if ((token.length >= 7) + && (strncmp((char *)token.data, "NTLMSSP", 7) == 0)) { + char *reply; + + DEBUG(10, ("Could not parse GSS-SPNEGO, trying raw " + "ntlmssp\n")); + + manage_squid_ntlmssp_request_int(state, buf, length, + talloc_tos(), &reply); + if (reply == NULL) { + x_fprintf(x_stdout, "BH Out of memory\n"); + return; + } + + if (strncmp(reply, "AF ", 3) == 0) { + x_fprintf(x_stdout, "AF * %s\n", reply+3); + } else { + x_fprintf(x_stdout, "%s *\n", reply); + } + + TALLOC_FREE(reply); + return; + } + len = spnego_read_data(ctx, token, &request); data_blob_free(&token); @@ -1318,6 +1407,8 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, DATA_BLOB ap_rep; DATA_BLOB session_key; struct PAC_LOGON_INFO *logon_info = NULL; + DATA_BLOB ticket; + uint8_t tok_id[2]; if ( request.negTokenInit.mechToken.data == NULL ) { DEBUG(1, ("Client did not provide Kerberos data\n")); @@ -1326,13 +1417,23 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, return; } + dump_data(10, request.negTokenInit.mechToken.data, + request.negTokenInit.mechToken.length); + + if (!spnego_parse_krb5_wrap(ctx, request.negTokenInit.mechToken, + &ticket, tok_id)) { + DEBUG(1, ("spnego_parse_krb5_wrap failed\n")); + x_fprintf(x_stdout, "BH spnego_parse_krb5_wrap failed\n"); + return; + } + response.type = SPNEGO_NEG_TOKEN_TARG; 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, + &ticket, &principal, &logon_info, &ap_rep, &session_key, True); @@ -1356,6 +1457,9 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, domain = SMB_STRDUP(domain); user = SMB_STRDUP(principal); + netsamlogon_cache_store( + user, &logon_info->info3); + data_blob_free(&ap_rep); } @@ -2319,7 +2423,9 @@ static void squid_stream(enum stdio_helper_mode stdio_mode, stdio_helper_functio state->helper_mode = stdio_mode; while(1) { + TALLOC_CTX *frame = talloc_stackframe(); manage_squid_request(state, fn); + TALLOC_FREE(frame); } } |