libcli/auth Make the source3/ implementation of the NTLMSSP server common
[amitay/samba.git] / libcli / auth / ntlmssp_server.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    handle NLTMSSP, server side
5
6    Copyright (C) Andrew Tridgell      2001
7    Copyright (C) Andrew Bartlett 2001-2010
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "../libcli/auth/ntlmssp.h"
25 #include "../libcli/auth/ntlmssp_private.h"
26 #include "../librpc/gen_ndr/ndr_ntlmssp.h"
27 #include "../libcli/auth/ntlmssp_ndr.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "../lib/crypto/crypto.h"
30
31 /**
32  * Determine correct target name flags for reply, given server role
33  * and negotiated flags
34  *
35  * @param ntlmssp_state NTLMSSP State
36  * @param neg_flags The flags from the packet
37  * @param chal_flags The flags to be set in the reply packet
38  * @return The 'target name' string.
39  */
40
41 const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,
42                                 uint32_t neg_flags, uint32_t *chal_flags)
43 {
44         if (neg_flags & NTLMSSP_REQUEST_TARGET) {
45                 *chal_flags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
46                 *chal_flags |= NTLMSSP_REQUEST_TARGET;
47                 if (ntlmssp_state->server.is_standalone) {
48                         *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
49                         return ntlmssp_state->server.netbios_name;
50                 } else {
51                         *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
52                         return ntlmssp_state->server.netbios_domain;
53                 };
54         } else {
55                 return "";
56         }
57 }
58
59 /**
60  * Next state function for the Negotiate packet
61  *
62  * @param ntlmssp_state NTLMSSP state
63  * @param out_mem_ctx Memory context for *out
64  * @param in The request, as a DATA_BLOB.  reply.data must be NULL
65  * @param out The reply, as an allocated DATA_BLOB, caller to free.
66  * @return Errors or MORE_PROCESSING_REQUIRED if (normal) a reply is required.
67  */
68
69 NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
70                                   TALLOC_CTX *out_mem_ctx,
71                                   const DATA_BLOB request, DATA_BLOB *reply)
72 {
73         DATA_BLOB struct_blob;
74         uint32_t neg_flags = 0;
75         uint32_t ntlmssp_command, chal_flags;
76         uint8_t cryptkey[8];
77         const char *target_name;
78         NTSTATUS status;
79
80         /* parse the NTLMSSP packet */
81 #if 0
82         file_save("ntlmssp_negotiate.dat", request.data, request.length);
83 #endif
84
85         if (request.length) {
86                 if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",
87                                                           "NTLMSSP",
88                                                           &ntlmssp_command,
89                                                           &neg_flags)) {
90                         DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",
91                                 (unsigned int)request.length));
92                         dump_data(2, request.data, request.length);
93                         return NT_STATUS_INVALID_PARAMETER;
94                 }
95                 debug_ntlmssp_flags(neg_flags);
96
97                 if (DEBUGLEVEL >= 10) {
98                         struct NEGOTIATE_MESSAGE *negotiate = talloc(
99                                 ntlmssp_state, struct NEGOTIATE_MESSAGE);
100                         if (negotiate != NULL) {
101                                 status = ntlmssp_pull_NEGOTIATE_MESSAGE(
102                                         &request, negotiate, negotiate);
103                                 if (NT_STATUS_IS_OK(status)) {
104                                         NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
105                                                         negotiate);
106                                 }
107                                 TALLOC_FREE(negotiate);
108                         }
109                 }
110         }
111
112         ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, ntlmssp_state->allow_lm_key);
113
114         /* Ask our caller what challenge they would like in the packet */
115         status = ntlmssp_state->get_challenge(ntlmssp_state, cryptkey);
116         if (!NT_STATUS_IS_OK(status)) {
117                 DEBUG(1, ("ntlmssp_server_negotiate: backend doesn't give a challenge: %s\n",
118                           nt_errstr(status)));
119                 return status;
120         }
121
122         /* Check if we may set the challenge */
123         if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {
124                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
125         }
126
127         /* The flags we send back are not just the negotiated flags,
128          * they are also 'what is in this packet'.  Therfore, we
129          * operate on 'chal_flags' from here on
130          */
131
132         chal_flags = ntlmssp_state->neg_flags;
133
134         /* get the right name to fill in as 'target' */
135         target_name = ntlmssp_target_name(ntlmssp_state,
136                                           neg_flags, &chal_flags);
137         if (target_name == NULL)
138                 return NT_STATUS_INVALID_PARAMETER;
139
140         ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
141         ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state,
142                                                         cryptkey, 8);
143
144         /* This creates the 'blob' of names that appears at the end of the packet */
145         if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
146         {
147                 msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
148                           MsvAvNbDomainName, target_name,
149                           MsvAvNbComputerName, ntlmssp_state->server.netbios_name,
150                           MsvAvDnsDomainName, ntlmssp_state->server.dns_domain,
151                           MsvAvDnsComputerName, ntlmssp_state->server.dns_name,
152                           MsvAvEOL, "");
153         } else {
154                 struct_blob = data_blob_null;
155         }
156
157         {
158                 /* Marshal the packet in the right format, be it unicode or ASCII */
159                 const char *gen_string;
160                 DATA_BLOB version_blob = data_blob_null;
161
162                 if (chal_flags & NTLMSSP_NEGOTIATE_VERSION) {
163                         enum ndr_err_code err;
164                         struct VERSION vers;
165
166                         /* "What Windows returns" as a version number. */
167                         ZERO_STRUCT(vers);
168                         vers.ProductMajorVersion = NTLMSSP_WINDOWS_MAJOR_VERSION_6;
169                         vers.ProductMinorVersion = NTLMSSP_WINDOWS_MINOR_VERSION_1;
170                         vers.ProductBuild = 0;
171                         vers.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;
172
173                         err = ndr_push_struct_blob(&version_blob,
174                                                 ntlmssp_state,
175                                                 &vers,
176                                                 (ndr_push_flags_fn_t)ndr_push_VERSION);
177
178                         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
179                                 data_blob_free(&struct_blob);
180                                 return NT_STATUS_NO_MEMORY;
181                         }
182                 }
183
184                 if (ntlmssp_state->unicode) {
185                         gen_string = "CdUdbddBb";
186                 } else {
187                         gen_string = "CdAdbddBb";
188                 }
189
190                 msrpc_gen(out_mem_ctx, reply, gen_string,
191                         "NTLMSSP",
192                         NTLMSSP_CHALLENGE,
193                         target_name,
194                         chal_flags,
195                         cryptkey, 8,
196                         0, 0,
197                         struct_blob.data, struct_blob.length,
198                         version_blob.data, version_blob.length);
199
200                 data_blob_free(&version_blob);
201
202                 if (DEBUGLEVEL >= 10) {
203                         struct CHALLENGE_MESSAGE *challenge = talloc(
204                                 ntlmssp_state, struct CHALLENGE_MESSAGE);
205                         if (challenge != NULL) {
206                                 challenge->NegotiateFlags = chal_flags;
207                                 status = ntlmssp_pull_CHALLENGE_MESSAGE(
208                                         reply, challenge, challenge);
209                                 if (NT_STATUS_IS_OK(status)) {
210                                         NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
211                                                         challenge);
212                                 }
213                                 TALLOC_FREE(challenge);
214                         }
215                 }
216         }
217
218         data_blob_free(&struct_blob);
219
220         ntlmssp_state->expected_state = NTLMSSP_AUTH;
221
222         return NT_STATUS_MORE_PROCESSING_REQUIRED;
223 }
224
225 struct ntlmssp_server_auth_state {
226         DATA_BLOB user_session_key;
227         DATA_BLOB lm_session_key;
228         /* internal variables used by KEY_EXCH (client-supplied user session key */
229         DATA_BLOB encrypted_session_key;
230         bool doing_ntlm2;
231         /* internal variables used by NTLM2 */
232         uint8_t session_nonce[16];
233 };
234
235 /**
236  * Next state function for the Authenticate packet
237  *
238  * @param ntlmssp_state NTLMSSP State
239  * @param request The request, as a DATA_BLOB
240  * @return Errors or NT_STATUS_OK.
241  */
242
243 static NTSTATUS ntlmssp_server_preauth(struct ntlmssp_state *ntlmssp_state,
244                                        struct ntlmssp_server_auth_state *state,
245                                        const DATA_BLOB request)
246 {
247         uint32_t ntlmssp_command, auth_flags;
248         NTSTATUS nt_status;
249
250         uint8_t session_nonce_hash[16];
251
252         const char *parse_string;
253
254 #if 0
255         file_save("ntlmssp_auth.dat", request.data, request.length);
256 #endif
257
258         if (ntlmssp_state->unicode) {
259                 parse_string = "CdBBUUUBd";
260         } else {
261                 parse_string = "CdBBAAABd";
262         }
263
264         /* zero these out */
265         data_blob_free(&ntlmssp_state->session_key);
266         data_blob_free(&ntlmssp_state->lm_resp);
267         data_blob_free(&ntlmssp_state->nt_resp);
268
269         ntlmssp_state->user = NULL;
270         ntlmssp_state->domain = NULL;
271         ntlmssp_state->client.netbios_name = NULL;
272
273         /* now the NTLMSSP encoded auth hashes */
274         if (!msrpc_parse(ntlmssp_state, &request, parse_string,
275                          "NTLMSSP",
276                          &ntlmssp_command,
277                          &ntlmssp_state->lm_resp,
278                          &ntlmssp_state->nt_resp,
279                          &ntlmssp_state->domain,
280                          &ntlmssp_state->user,
281                          &ntlmssp_state->client.netbios_name,
282                          &state->encrypted_session_key,
283                          &auth_flags)) {
284                 DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
285                 dump_data(10, request.data, request.length);
286
287                 /* zero this out */
288                 data_blob_free(&state->encrypted_session_key);
289                 auth_flags = 0;
290
291                 /* Try again with a shorter string (Win9X truncates this packet) */
292                 if (ntlmssp_state->unicode) {
293                         parse_string = "CdBBUUU";
294                 } else {
295                         parse_string = "CdBBAAA";
296                 }
297
298                 /* now the NTLMSSP encoded auth hashes */
299                 if (!msrpc_parse(ntlmssp_state, &request, parse_string,
300                                  "NTLMSSP",
301                                  &ntlmssp_command,
302                                  &ntlmssp_state->lm_resp,
303                                  &ntlmssp_state->nt_resp,
304                                  &ntlmssp_state->domain,
305                                  &ntlmssp_state->user,
306                                  &ntlmssp_state->client.netbios_name)) {
307                         DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));
308                         dump_data(2, request.data, request.length);
309
310                         return NT_STATUS_INVALID_PARAMETER;
311                 }
312         }
313
314         talloc_steal(state, state->encrypted_session_key.data);
315
316         if (auth_flags)
317                 ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, ntlmssp_state->allow_lm_key);
318
319         if (DEBUGLEVEL >= 10) {
320                 struct AUTHENTICATE_MESSAGE *authenticate = talloc(
321                         ntlmssp_state, struct AUTHENTICATE_MESSAGE);
322                 if (authenticate != NULL) {
323                         NTSTATUS status;
324                         authenticate->NegotiateFlags = auth_flags;
325                         status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
326                                 &request, authenticate, authenticate);
327                         if (NT_STATUS_IS_OK(status)) {
328                                 NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
329                                                 authenticate);
330                         }
331                         TALLOC_FREE(authenticate);
332                 }
333         }
334
335         DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
336                  ntlmssp_state->user, ntlmssp_state->domain,
337                  ntlmssp_state->client.netbios_name,
338                  (unsigned long)ntlmssp_state->lm_resp.length,
339                  (unsigned long)ntlmssp_state->nt_resp.length));
340
341 #if 0
342         file_save("nthash1.dat",  &ntlmssp_state->nt_resp.data,  &ntlmssp_state->nt_resp.length);
343         file_save("lmhash1.dat",  &ntlmssp_state->lm_resp.data,  &ntlmssp_state->lm_resp.length);
344 #endif
345
346         /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a
347            client challenge
348
349            However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
350         */
351         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
352                 if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
353                         struct MD5Context md5_session_nonce_ctx;
354                         state->doing_ntlm2 = true;
355
356                         memcpy(state->session_nonce, ntlmssp_state->internal_chal.data, 8);
357                         memcpy(&state->session_nonce[8], ntlmssp_state->lm_resp.data, 8);
358
359                         SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);
360
361                         MD5Init(&md5_session_nonce_ctx);
362                         MD5Update(&md5_session_nonce_ctx, state->session_nonce, 16);
363                         MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
364
365                         ntlmssp_state->chal = data_blob_talloc(
366                                 ntlmssp_state, session_nonce_hash, 8);
367
368                         /* LM response is no longer useful */
369                         data_blob_free(&ntlmssp_state->lm_resp);
370
371                         /* We changed the effective challenge - set it */
372                         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) {
373                                 return nt_status;
374                         }
375
376                         /* LM Key is incompatible. */
377                         ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
378                 }
379         }
380         return NT_STATUS_OK;
381 }
382
383 /**
384  * Next state function for the Authenticate packet
385  * (after authentication - figures out the session keys etc)
386  *
387  * @param ntlmssp_state NTLMSSP State
388  * @return Errors or NT_STATUS_OK.
389  */
390
391 static NTSTATUS ntlmssp_server_postauth(struct ntlmssp_state *ntlmssp_state,
392                                         struct ntlmssp_server_auth_state *state)
393 {
394         DATA_BLOB user_session_key = state->user_session_key;
395         DATA_BLOB lm_session_key = state->lm_session_key;
396         NTSTATUS nt_status;
397         DATA_BLOB session_key = data_blob(NULL, 0);
398
399         dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);
400         dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);
401
402         /* Handle the different session key derivation for NTLM2 */
403         if (state->doing_ntlm2) {
404                 if (user_session_key.data && user_session_key.length == 16) {
405                         session_key = data_blob_talloc(ntlmssp_state,
406                                                        NULL, 16);
407                         hmac_md5(user_session_key.data, state->session_nonce,
408                                  sizeof(state->session_nonce), session_key.data);
409                         DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
410                         dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
411
412                 } else {
413                         DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
414                         session_key = data_blob_null;
415                 }
416         } else if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
417                 /* Ensure we can never get here on NTLMv2 */
418                 && (ntlmssp_state->nt_resp.length == 0 || ntlmssp_state->nt_resp.length == 24)) {
419
420                 if (lm_session_key.data && lm_session_key.length >= 8) {
421                         if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
422                                 session_key = data_blob_talloc(ntlmssp_state,
423                                                                NULL, 16);
424                                 if (session_key.data == NULL) {
425                                         return NT_STATUS_NO_MEMORY;
426                                 }
427                                 SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data,
428                                                           session_key.data);
429                                 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
430                         } else {
431                                 static const uint8_t zeros[24] = {0, };
432                                 session_key = data_blob_talloc(
433                                         ntlmssp_state, NULL, 16);
434                                 if (session_key.data == NULL) {
435                                         return NT_STATUS_NO_MEMORY;
436                                 }
437                                 SMBsesskeygen_lm_sess_key(zeros, zeros,
438                                                           session_key.data);
439                                 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
440                         }
441                         dump_data_pw("LM session key:\n", session_key.data,
442                                      session_key.length);
443                 } else {
444                         /* LM Key not selected */
445                         ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
446
447                         DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
448                         session_key = data_blob_null;
449                 }
450
451         } else if (user_session_key.data) {
452                 session_key = user_session_key;
453                 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
454                 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
455
456                 /* LM Key not selected */
457                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
458
459         } else if (lm_session_key.data) {
460                 /* Very weird to have LM key, but no user session key, but anyway.. */
461                 session_key = lm_session_key;
462                 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
463                 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
464
465                 /* LM Key not selected */
466                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
467
468         } else {
469                 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
470                 session_key = data_blob_null;
471
472                 /* LM Key not selected */
473                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
474         }
475
476         /* With KEY_EXCH, the client supplies the proposed session key,
477            but encrypts it with the long-term key */
478         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
479                 if (!state->encrypted_session_key.data
480                     || state->encrypted_session_key.length != 16) {
481                         data_blob_free(&state->encrypted_session_key);
482                         DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",
483                                   (unsigned)state->encrypted_session_key.length));
484                         return NT_STATUS_INVALID_PARAMETER;
485                 } else if (!session_key.data || session_key.length != 16) {
486                         DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
487                                   (unsigned int)session_key.length));
488                         ntlmssp_state->session_key = session_key;
489                 } else {
490                         dump_data_pw("KEY_EXCH session key (enc):\n",
491                                      state->encrypted_session_key.data,
492                                      state->encrypted_session_key.length);
493                         arcfour_crypt(state->encrypted_session_key.data,
494                                       session_key.data,
495                                       state->encrypted_session_key.length);
496                         ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state,
497                                                                       state->encrypted_session_key.data,
498                                                                       state->encrypted_session_key.length);
499                         dump_data_pw("KEY_EXCH session key:\n",
500                                      state->encrypted_session_key.data,
501                                      state->encrypted_session_key.length);
502                         talloc_free(session_key.data);
503                 }
504         } else {
505                 ntlmssp_state->session_key = session_key;
506         }
507
508         if (ntlmssp_state->session_key.length) {
509                 nt_status = ntlmssp_sign_init(ntlmssp_state);
510         }
511
512         ntlmssp_state->expected_state = NTLMSSP_DONE;
513
514         return nt_status;
515 }
516
517
518 /**
519  * Next state function for the Authenticate packet
520  *
521  * @param gensec_security GENSEC state
522  * @param out_mem_ctx Memory context for *out
523  * @param in The request, as a DATA_BLOB.  reply.data must be NULL
524  * @param out The reply, as an allocated DATA_BLOB, caller to free.
525  * @return Errors or NT_STATUS_OK if authentication sucessful
526  */
527
528 NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
529                              TALLOC_CTX *out_mem_ctx,
530                              const DATA_BLOB in, DATA_BLOB *out)
531 {
532         struct ntlmssp_server_auth_state *state;
533         NTSTATUS nt_status;
534
535         /* zero the outbound NTLMSSP packet */
536         *out = data_blob_null;
537
538         state = talloc_zero(ntlmssp_state, struct ntlmssp_server_auth_state);
539         if (state == NULL) {
540                 return NT_STATUS_NO_MEMORY;
541         }
542
543         nt_status = ntlmssp_server_preauth(ntlmssp_state, state, in);
544         if (!NT_STATUS_IS_OK(nt_status)) {
545                 TALLOC_FREE(state);
546                 return nt_status;
547         }
548
549         /*
550          * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
551          * is required (by "ntlm auth = no" and "lm auth = no" being set in the
552          * smb.conf file) and no NTLMv2 response was sent then the password check
553          * will fail here. JRA.
554          */
555
556         /* Finally, actually ask if the password is OK */
557         nt_status = ntlmssp_state->check_password(ntlmssp_state,
558                                                   &state->user_session_key,
559                                                   &state->lm_session_key);
560         if (!NT_STATUS_IS_OK(nt_status)) {
561                 TALLOC_FREE(state);
562                 return nt_status;
563         }
564
565         /* When we get more async in the auth code behind
566            ntlmssp_state->check_password, the ntlmssp_server_postpath
567            can be done in a callback */
568
569         nt_status = ntlmssp_server_postauth(ntlmssp_state, state);
570         if (!NT_STATUS_IS_OK(nt_status)) {
571                 TALLOC_FREE(state);
572                 return nt_status;
573         }
574
575         TALLOC_FREE(state);
576         return NT_STATUS_OK;
577 }