The branch, v3-5-test has been updated via ab69b55 s3:ntlm_auth: support clients which offer a spnego mechs we don't support (bug #7855) via e00cb88 s3:ntlm_auth: free session key, as we don't use it (at least for now) via 7c3bb9a s3:ntlm_auth: fix memory leak in the raw ntlmssp code path via 7cb3d84 s3: Correctly unwrap the krb ticket in gss-spnego (cherry picked from commit 547b268cfaa2e791bf92e8804bfa504c4e37050b) via 7652f2a s3: Fall back to raw NTLMSSP for the gss-spnego protocol via 8443abe s3: Split off output generation from manage_squid_ntlmssp_request (cherry picked from commit de2c143f4d540f695db5c7fe8685614c03977365) via 0d9b2e9 s3: Wrap the ntlm_auth loop with a talloc_stackframe (cherry picked from commit ae483bbe9af526623189cefe7735f3f2813da6d7) via 498f1c8 s3: Fix some debug msgs in ntlm_auth (cherry picked from commit 6400f3ee62108e3dd1e6c1013ccea9fb4b08d562) via 63fa349 ntlm_auth: Fix a valgrind error (cherry picked from commit 69db4b4ccf051b05517e6eb9039ab48f90608075) from a966463 Fix bso#3185, return false when EOF is encountered in param name.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test - Log ----------------------------------------------------------------- commit ab69b55011eea73d7c8827fc339feb905474f201 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Dec 2 00:39:23 2010 +0100 s3:ntlm_auth: support clients which offer a spnego mechs we don't support (bug #7855) Before we rejected the authentication if we don't support the first spnego mech the client offered. We now negotiate the first mech we support. This fix works arround problems, when a client sends the NEGOEX (1.3.6.1.4.1.311.2.2.30) oid, which we don't support. metze (cherry picked from commit f802075f08fe0d86f3d176f2302236aeb5834f3d) Modified to work in the v3-5-test branch, e.g. use ntlmssp_end() The last 9 patches address bug #7855 (ntlm_auth only handles the first spnego mech). commit e00cb883107753380272e128955ae5ad3057fd40 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Dec 1 05:59:16 2010 +0100 s3:ntlm_auth: free session key, as we don't use it (at least for now) metze (cherry picked from commit ee4f5ac6182969bcab91955e6d6581e408d222f1) commit 7c3bb9af54b40dbd24b781186607339c76a25a85 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Dec 1 05:50:59 2010 +0100 s3:ntlm_auth: fix memory leak in the raw ntlmssp code path metze (cherry picked from commit 9a56ade6b1d627126418c75de4602610b4482503) commit 7cb3d84fc11490c97d7d84a3231e2d9f6b2d69fe Author: Stefan Metzmacher <me...@samba.org> Date: Tue Nov 30 10:52:52 2010 +0100 s3: Correctly unwrap the krb ticket in gss-spnego (cherry picked from commit 547b268cfaa2e791bf92e8804bfa504c4e37050b) Signed-off-by: Stefan Metzmacher <me...@samba.org> renamed to _spnego_parse_krb5_wrap() metze commit 7652f2a782559bb0346b0976929b5b5b5377dcbc Author: Volker Lendecke <v...@samba.org> Date: Thu Sep 16 10:22:00 2010 +0200 s3: Fall back to raw NTLMSSP for the gss-spnego protocol This is to handle the mod_auth_ntlm_winbind protocol sending "Negotiate" to IE, which sends raw NTLMSSP instead of a SPNEGO wrapped NTLMSSP blob. (cherry picked from commit 70ab7eb5303a5ff058939541dd5bc1f81113a48e) Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 8443abede7c3f6deb7a7c584937d9e28eb9274da Author: Stefan Metzmacher <me...@samba.org> Date: Tue Nov 30 10:46:28 2010 +0100 s3: Split off output generation from manage_squid_ntlmssp_request (cherry picked from commit de2c143f4d540f695db5c7fe8685614c03977365) Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 0d9b2e954d61c9f6211c867348a817e42bd4b12f Author: Volker Lendecke <v...@samba.org> Date: Thu Sep 16 10:36:21 2010 +0200 s3: Wrap the ntlm_auth loop with a talloc_stackframe (cherry picked from commit ae483bbe9af526623189cefe7735f3f2813da6d7) Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 498f1c87e6c9bc136da696bae5e9a71df9b8233e Author: Volker Lendecke <v...@samba.org> Date: Wed Sep 15 10:29:44 2010 +0200 s3: Fix some debug msgs in ntlm_auth (cherry picked from commit 6400f3ee62108e3dd1e6c1013ccea9fb4b08d562) Signed-off-by: Stefan Metzmacher <me...@samba.org> commit 63fa349916d72c158b1fc4ab7a60b9a909a15131 Author: Volker Lendecke <v...@samba.org> Date: Mon Sep 13 18:09:20 2010 +0200 ntlm_auth: Fix a valgrind error (cherry picked from commit 69db4b4ccf051b05517e6eb9039ab48f90608075) Signed-off-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/Makefile.in | 2 +- source3/utils/ntlm_auth.c | 417 ++++++++++++++++++++++++++++++++------------- 2 files changed, 296 insertions(+), 123 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/Makefile.in b/source3/Makefile.in index 9e960c9..8cdecef 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1315,7 +1315,7 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ $(LIBADS_SERVER_OBJ) \ $(PASSDB_OBJ) $(LIBTSOCKET_OBJ) $(GROUPDB_OBJ) \ $(SMBLDAP_OBJ) $(LIBNMB_OBJ) \ - $(LDB_OBJ) $(WBCOMMON_OBJ) \ + $(LDB_OBJ) $(WBCOMMON_OBJ) $(SLCACHE_OBJ) \ $(LIBNDR_GEN_OBJ0) $(LIBNDR_GEN_OBJ1) @BUILD_INIPARSER@ diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index afd0b99..a85f123 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; -- Samba Shared Repository