diff options
Diffstat (limited to 'source3/utils/ntlm_auth.c')
-rw-r--r-- | source3/utils/ntlm_auth.c | 417 |
1 files changed, 295 insertions, 122 deletions
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index afd0b994a7..a85f123048 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -76,6 +76,8 @@ struct ntlm_auth_state { struct ntlmssp_state *ntlmssp_state; uint32_t neg_flags; char *want_feature_list; + char *spnego_mech; + char *spnego_mech_oid; bool have_session_key; DATA_BLOB session_key; DATA_BLOB initial_message; @@ -778,15 +780,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", buf)); - x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); + DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); + *response = talloc_strdup(mem_ctx, "BH NTLMSSP query invalid"); return; } @@ -796,7 +800,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); @@ -813,12 +817,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; } @@ -833,10 +837,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; @@ -845,17 +850,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", buf)); - x_fprintf(x_stdout, "BH NTLMSSP query invalid\n"); + DEBUG(1, ("NTLMSSP query [%s] invalid\n", buf)); + *response = talloc_strdup(mem_ctx, "BH NTLMSSP query invalid"); return; } @@ -863,7 +869,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, @@ -878,22 +885,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))); ntlmssp_end(&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->auth_context); + *response = talloc_asprintf( + mem_ctx, "AF %s", + (char *)state->ntlmssp_state->auth_context); DEBUG(10, ("NTLMSSP OK!\n")); if(state->have_session_key) @@ -909,6 +919,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) { @@ -921,7 +947,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; } @@ -1013,7 +1039,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; } @@ -1137,11 +1163,12 @@ static void offer_gss_spnego_mechs(void) { /* Server negTokenInit (mech offerings) */ spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = talloc_array(ctx, const char *, 2); + spnego.negTokenInit.mechTypes = talloc_array(ctx, const char *, 4); #ifdef HAVE_KRB5 spnego.negTokenInit.mechTypes[0] = talloc_strdup(ctx, OID_KERBEROS5_OLD); - spnego.negTokenInit.mechTypes[1] = talloc_strdup(ctx, OID_NTLMSSP); - spnego.negTokenInit.mechTypes[2] = NULL; + spnego.negTokenInit.mechTypes[1] = talloc_strdup(ctx, OID_KERBEROS5); + spnego.negTokenInit.mechTypes[2] = talloc_strdup(ctx, OID_NTLMSSP); + spnego.negTokenInit.mechTypes[3] = NULL; #else spnego.negTokenInit.mechTypes[0] = talloc_strdup(ctx, OID_NTLMSSP); spnego.negTokenInit.mechTypes[1] = NULL; @@ -1169,12 +1196,52 @@ static void offer_gss_spnego_mechs(void) { return; } +static 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) { - static NTLMSSP_STATE *ntlmssp_state = NULL; struct spnego_data request, response; DATA_BLOB token; + DATA_BLOB raw_in_token = data_blob_null; + DATA_BLOB raw_out_token = data_blob_null; NTSTATUS status; ssize_t len; TALLOC_CTX *ctx = talloc_tos(); @@ -1185,20 +1252,23 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, const char *reply_code; char *reply_base64; char *reply_argument = NULL; + char *supportedMech = 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); + if (state->ntlmssp_state) + ntlmssp_end(&state->ntlmssp_state); + TALLOC_FREE(state->spnego_mech); + TALLOC_FREE(state->spnego_mech_oid); } 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; } @@ -1221,166 +1291,269 @@ 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; + + data_blob_free(&token); + + 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; + } + + ZERO_STRUCT(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; } if (request.type == SPNEGO_NEG_TOKEN_INIT) { +#ifdef HAVE_KRB5 + int krb5_idx = -1; +#endif + int ntlm_idx = -1; + int used_idx = -1; + int i; + + if (state->spnego_mech) { + DEBUG(1, ("Client restarted SPNEGO with NegTokenInit " + "while mech[%s] was already negotiated\n", + state->spnego_mech)); + x_fprintf(x_stdout, "BH Client send NegTokenInit twice\n"); + return; + } /* Second request from Client. This is where the client offers its mechanism to use. */ 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; } status = NT_STATUS_UNSUCCESSFUL; - if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) { + for (i = 0; request.negTokenInit.mechTypes[i] != NULL; i++) { + DEBUG(10,("got mech[%d][%s]\n", + i, request.negTokenInit.mechTypes[i])); +#ifdef HAVE_KRB5 + if (strcmp(request.negTokenInit.mechTypes[i], OID_KERBEROS5_OLD) == 0) { + krb5_idx = i; + break; + } + if (strcmp(request.negTokenInit.mechTypes[i], OID_KERBEROS5) == 0) { + krb5_idx = i; + break; + } +#endif + if (strcmp(request.negTokenInit.mechTypes[i], OID_NTLMSSP) == 0) { + ntlm_idx = i; + break; + } + } - if ( request.negTokenInit.mechToken.data == NULL ) { - DEBUG(1, ("Client did not provide NTLMSSP data\n")); - x_fprintf(x_stdout, "BH Client did not provide " - "NTLMSSP data\n"); + used_idx = ntlm_idx; +#ifdef HAVE_KRB5 + if (krb5_idx != -1) { + ntlm_idx = -1; + used_idx = krb5_idx; + } +#endif + if (ntlm_idx > -1) { + state->spnego_mech = talloc_strdup(state, "ntlmssp"); + if (state->spnego_mech == NULL) { + x_fprintf(x_stdout, "BH Out of memory\n"); return; } - if ( ntlmssp_state != NULL ) { + if (state->ntlmssp_state) { DEBUG(1, ("Client wants a new NTLMSSP challenge, but " "already got one\n")); x_fprintf(x_stdout, "BH Client wants a new " "NTLMSSP challenge, but " "already got one\n"); - ntlmssp_end(&ntlmssp_state); + ntlmssp_end(&state->ntlmssp_state); return; } - if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) { + status = ntlm_auth_start_ntlmssp_server(&state->ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { x_fprintf(x_stdout, "BH %s\n", nt_errstr(status)); return; } - - DEBUG(10, ("got NTLMSSP packet:\n")); - dump_data(10, request.negTokenInit.mechToken.data, - request.negTokenInit.mechToken.length); - - response.type = SPNEGO_NEG_TOKEN_TARG; - 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, - &response.negTokenTarg.responseToken); } #ifdef HAVE_KRB5 - if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) { - - TALLOC_CTX *mem_ctx = talloc_init("manage_gss_spnego_request"); - char *principal; - DATA_BLOB ap_rep; - DATA_BLOB session_key; - struct PAC_DATA *pac_data = NULL; - - if ( request.negTokenInit.mechToken.data == NULL ) { - DEBUG(1, ("Client did not provide Kerberos data\n")); - x_fprintf(x_stdout, "BH Client did not provide " - "Kerberos data\n"); + if (krb5_idx > -1) { + state->spnego_mech = talloc_strdup(state, "krb5"); + if (state->spnego_mech == NULL) { + x_fprintf(x_stdout, "BH Out of memory\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, - &principal, &pac_data, &ap_rep, - &session_key, True); - - /* Now in "principal" we have the name we are - authenticated as. */ - - if (NT_STATUS_IS_OK(status)) { - - domain = strchr_m(principal, '@'); - - if (domain == NULL) { - DEBUG(1, ("Did not get a valid principal " - "from ads_verify_ticket\n")); - x_fprintf(x_stdout, "BH Did not get a " - "valid principal from " - "ads_verify_ticket\n"); - return; - } - - *domain++ = '\0'; - domain = SMB_STRDUP(domain); - user = SMB_STRDUP(principal); - - data_blob_free(&ap_rep); - } - - TALLOC_FREE(mem_ctx); } #endif + if (used_idx > -1) { + state->spnego_mech_oid = talloc_strdup(state, + request.negTokenInit.mechTypes[used_idx]); + if (state->spnego_mech_oid == NULL) { + x_fprintf(x_stdout, "BH Out of memory\n"); + return; + } + supportedMech = talloc_strdup(ctx, state->spnego_mech_oid); + if (supportedMech == NULL) { + x_fprintf(x_stdout, "BH Out of memory\n"); + return; + } + status = NT_STATUS_MORE_PROCESSING_REQUIRED; + } else { + status = NT_STATUS_NOT_SUPPORTED; + } + if (used_idx == 0) { + status = NT_STATUS_OK; + raw_in_token = request.negTokenInit.mechToken; + } } else { + if (state->spnego_mech == NULL) { + DEBUG(1,("Got netTokenTarg without negTokenInit\n")); + x_fprintf(x_stdout, "BH Got a negTokenTarg without " + "negTokenInit\n"); + return; + } - if ( (request.negTokenTarg.supportedMech == NULL) || - ( strcmp(request.negTokenTarg.supportedMech, OID_NTLMSSP) != 0 ) ) { - /* Kerberos should never send a negTokenTarg, OID_NTLMSSP - is the only one we support that sends this stuff */ - DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n", - request.negTokenTarg.supportedMech)); - x_fprintf(x_stdout, "BH Got a negTokenTarg for " - "something non-NTLMSSP\n"); + if ((request.negTokenTarg.supportedMech != NULL) && + (strcmp(request.negTokenTarg.supportedMech, state->spnego_mech_oid) != 0 ) ) { + DEBUG(1, ("Got a negTokenTarg with mech[%s] while [%s] was already negotiated\n", + request.negTokenTarg.supportedMech, + state->spnego_mech_oid)); + x_fprintf(x_stdout, "BH Got a negTokenTarg with speficied mech\n"); return; } - if (request.negTokenTarg.responseToken.data == NULL) { - DEBUG(1, ("Got a negTokenTarg without a responseToken!\n")); - x_fprintf(x_stdout, "BH Got a negTokenTarg without a " - "responseToken!\n"); + status = NT_STATUS_OK; + raw_in_token = request.negTokenTarg.responseToken; + } + + if (!NT_STATUS_IS_OK(status)) { + /* error or more processing */ + } else if (strcmp(state->spnego_mech, "ntlmssp") == 0) { + + DEBUG(10, ("got NTLMSSP packet:\n")); + dump_data(10, raw_in_token.data, raw_in_token.length); + + status = ntlmssp_update(state->ntlmssp_state, + raw_in_token, + &raw_out_token); + if (NT_STATUS_IS_OK(status)) { + user = talloc_strdup(ctx, state->ntlmssp_state->user); + domain = talloc_strdup(ctx, state->ntlmssp_state->domain); + } + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + ntlmssp_end(&state->ntlmssp_state); + } +#ifdef HAVE_KRB5 + } else if (strcmp(state->spnego_mech, "krb5") == 0) { + char *principal; + DATA_BLOB ap_rep; + DATA_BLOB session_key; + struct PAC_DATA *pac_data = NULL; + DATA_BLOB ticket; + uint8_t tok_id[2]; + + if (!_spnego_parse_krb5_wrap(ctx, raw_in_token, + &ticket, tok_id)) { + DEBUG(1, ("spnego_parse_krb5_wrap failed\n")); + x_fprintf(x_stdout, "BH spnego_parse_krb5_wrap failed\n"); return; } - status = ntlmssp_update(ntlmssp_state, - request.negTokenTarg.responseToken, - &response.negTokenTarg.responseToken); + status = ads_verify_ticket(ctx, lp_realm(), 0, + &ticket, + &principal, &pac_data, &ap_rep, + &session_key, True); - response.type = SPNEGO_NEG_TOKEN_TARG; - response.negTokenTarg.supportedMech = talloc_strdup(ctx, OID_NTLMSSP); - response.negTokenTarg.mechListMIC = data_blob_talloc(ctx, NULL, 0); + /* Now in "principal" we have the name we are authenticated as. */ if (NT_STATUS_IS_OK(status)) { - user = SMB_STRDUP(ntlmssp_state->user); - domain = SMB_STRDUP(ntlmssp_state->domain); - ntlmssp_end(&ntlmssp_state); + + domain = strchr_m(principal, '@'); + + if (domain == NULL) { + DEBUG(1, ("Did not get a valid principal " + "from ads_verify_ticket\n")); + x_fprintf(x_stdout, "BH Did not get a " + "valid principal from " + "ads_verify_ticket\n"); + return; + } + + *domain++ = '\0'; + domain = talloc_strdup(ctx, domain); + user = talloc_strdup(ctx, principal); + + if (pac_data) { + struct PAC_LOGON_INFO *logon_info; + logon_info = get_logon_info_from_pac( + pac_data); + if (logon_info) { + netsamlogon_cache_store( + user, + &logon_info->info3); + } + } + + data_blob_free(&ap_rep); + data_blob_free(&session_key); } + data_blob_free(&ticket); +#endif } spnego_free_data(&request); + ZERO_STRUCT(response); + response.type = SPNEGO_NEG_TOKEN_TARG; if (NT_STATUS_IS_OK(status)) { + TALLOC_FREE(state->spnego_mech); + TALLOC_FREE(state->spnego_mech_oid); response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; + response.negTokenTarg.responseToken = raw_out_token; reply_code = "AF"; reply_argument = talloc_asprintf(ctx, "%s\\%s", domain, user); } else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + response.negTokenTarg.supportedMech = supportedMech; + response.negTokenTarg.responseToken = raw_out_token; response.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; reply_code = "TT"; reply_argument = talloc_strdup(ctx, "*"); } else { + TALLOC_FREE(state->spnego_mech); + TALLOC_FREE(state->spnego_mech_oid); + data_blob_free(&raw_out_token); response.negTokenTarg.negResult = SPNEGO_REJECT; reply_code = "NA"; reply_argument = talloc_strdup(ctx, nt_errstr(status)); @@ -1389,12 +1562,10 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state, if (!reply_argument) { DEBUG(1, ("Could not write SPNEGO data blob\n")); x_fprintf(x_stdout, "BH Could not write SPNEGO data blob\n"); + spnego_free_data(&response); return; } - SAFE_FREE(user); - SAFE_FREE(domain); - len = spnego_write_data(ctx, &token, &response); spnego_free_data(&response); @@ -2288,7 +2459,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); } } |