r4470: Try not to have GSSAPI built unless we detected krb5. We should split
[samba.git] / source4 / libcli / auth / gensec_ntlmssp.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    dcerpc authentication operations
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "auth/auth.h"
26
27 struct gensec_ntlmssp_state {
28         struct auth_context *auth_context;
29         struct auth_serversupplied_info *server_info;
30         struct ntlmssp_state *ntlmssp_state;
31         uint32 have_features;
32 };
33
34
35 /**
36  * Return the challenge as determined by the authentication subsystem 
37  * @return an 8 byte random challenge
38  */
39
40 static const uint8_t *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
41 {
42         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
43
44         return gensec_ntlmssp_state->auth_context->get_ntlm_challenge(gensec_ntlmssp_state->auth_context);
45 }
46
47 /**
48  * Some authentication methods 'fix' the challenge, so we may not be able to set it
49  *
50  * @return If the effective challenge used by the auth subsystem may be modified
51  */
52 static BOOL auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
53 {
54         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
55
56         return gensec_ntlmssp_state->auth_context->challenge_may_be_modified;
57 }
58
59 /**
60  * NTLM2 authentication modifies the effective challenge, 
61  * @param challenge The new challenge value
62  */
63 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
64 {
65         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
66         struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
67
68         SMB_ASSERT(challenge->length == 8);
69
70         auth_context->challenge = data_blob_talloc(auth_context, 
71                                                    challenge->data, challenge->length);
72
73         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
74
75         DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
76         DEBUG(5, ("challenge is: \n"));
77         dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
78         return NT_STATUS_OK;
79 }
80
81 /**
82  * Check the password on an NTLMSSP login.  
83  *
84  * Return the session keys used on the connection.
85  */
86
87 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
88 {
89         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ntlmssp_state->auth_context;
90         struct auth_usersupplied_info *user_info = NULL;
91         NTSTATUS nt_status;
92
93 #if 0
94         /* the client has given us its machine name (which we otherwise would not get on port 445).
95            we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
96
97         set_remote_machine_name(gensec_ntlmssp_state->ntlmssp_state->workstation, True);
98
99         /* setup the string used by %U */
100         /* sub_set_smb_name checks for weird internally */
101         sub_set_smb_name(gensec_ntlmssp_state->ntlmssp_state->user);
102
103         reload_services(True);
104
105 #endif
106         nt_status = make_user_info_map(ntlmssp_state,
107                                        &user_info, 
108                                        gensec_ntlmssp_state->ntlmssp_state->user, 
109                                        gensec_ntlmssp_state->ntlmssp_state->domain, 
110                                        gensec_ntlmssp_state->ntlmssp_state->workstation, 
111                                        gensec_ntlmssp_state->ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->lm_resp : NULL, 
112                                        gensec_ntlmssp_state->ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->ntlmssp_state->nt_resp : NULL, 
113                                        NULL, NULL, NULL,
114                                        True);
115
116         if (!NT_STATUS_IS_OK(nt_status)) {
117                 return nt_status;
118         }
119
120         nt_status = gensec_ntlmssp_state->
121                 auth_context->check_ntlm_password(gensec_ntlmssp_state->auth_context, 
122                                                   user_info, 
123                                                   gensec_ntlmssp_state, 
124                                                   &gensec_ntlmssp_state->server_info); 
125
126         free_user_info(&user_info);
127
128         if (!NT_STATUS_IS_OK(nt_status)) {
129                 return nt_status;
130         }
131         if (gensec_ntlmssp_state->server_info->user_session_key.length) {
132                 DEBUG(10, ("Got NT session key of length %u\n", gensec_ntlmssp_state->server_info->user_session_key.length));
133                 *user_session_key = data_blob_talloc(ntlmssp_state, 
134                                                    gensec_ntlmssp_state->server_info->user_session_key.data,
135                                                    gensec_ntlmssp_state->server_info->user_session_key.length);
136         }
137         if (gensec_ntlmssp_state->server_info->lm_session_key.length) {
138                 DEBUG(10, ("Got LM session key of length %u\n", gensec_ntlmssp_state->server_info->lm_session_key.length));
139                 *lm_session_key = data_blob_talloc(ntlmssp_state, 
140                                                    gensec_ntlmssp_state->server_info->lm_session_key.data,
141                                                    gensec_ntlmssp_state->server_info->lm_session_key.length);
142         }
143         return nt_status;
144 }
145
146 static int gensec_ntlmssp_destroy(void *ptr)
147 {
148         struct gensec_ntlmssp_state *gensec_ntlmssp_state = ptr;
149
150         if (gensec_ntlmssp_state->ntlmssp_state) {
151                 ntlmssp_end(&gensec_ntlmssp_state->ntlmssp_state);
152         }
153
154         if (gensec_ntlmssp_state->auth_context) {
155                 free_auth_context(&gensec_ntlmssp_state->auth_context);
156         }
157         if (gensec_ntlmssp_state->server_info) {
158                 free_server_info(&gensec_ntlmssp_state->server_info);
159         }
160         return 0;
161 }
162
163 static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
164 {
165         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
166         
167         gensec_ntlmssp_state = talloc_p(gensec_security, struct gensec_ntlmssp_state);
168         if (!gensec_ntlmssp_state) {
169                 return NT_STATUS_NO_MEMORY;
170         }
171
172         gensec_ntlmssp_state->ntlmssp_state = NULL;
173         gensec_ntlmssp_state->auth_context = NULL;
174         gensec_ntlmssp_state->server_info = NULL;
175         gensec_ntlmssp_state->have_features = 0;
176
177         talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy); 
178
179         gensec_security->private_data = gensec_ntlmssp_state;
180         return NT_STATUS_OK;
181 }
182
183 static NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
184 {
185         NTSTATUS nt_status;
186         NTSTATUS status;
187         struct ntlmssp_state *ntlmssp_state;
188         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
189
190         status = gensec_ntlmssp_start(gensec_security);
191         if (!NT_STATUS_IS_OK(status)) {
192                 return status;
193         }
194
195         gensec_ntlmssp_state = gensec_security->private_data;
196
197         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(gensec_ntlmssp_state,
198                                                               &gensec_ntlmssp_state->ntlmssp_state))) {
199                 return nt_status;
200         }
201
202         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
203                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
204         }
205         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
206                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
207         }
208
209         ntlmssp_state = gensec_ntlmssp_state->ntlmssp_state;
210         nt_status = make_auth_context_subsystem(gensec_ntlmssp_state, &gensec_ntlmssp_state->auth_context);
211         if (!NT_STATUS_IS_OK(nt_status)) {
212                 return nt_status;
213         }
214
215         ntlmssp_state->auth_context = gensec_ntlmssp_state;
216         ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
217         ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
218         ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
219         ntlmssp_state->check_password = auth_ntlmssp_check_password;
220         ntlmssp_state->server_role = lp_server_role();
221         
222         return NT_STATUS_OK;
223 }
224
225 static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
226 {
227         struct gensec_ntlmssp_state *gensec_ntlmssp_state;
228         char *password = NULL;
229         
230         NTSTATUS status;
231         status = gensec_ntlmssp_start(gensec_security);
232         if (!NT_STATUS_IS_OK(status)) {
233                 return status;
234         }
235
236         gensec_ntlmssp_state = gensec_security->private_data;
237         status = ntlmssp_client_start(gensec_ntlmssp_state,
238                                       &gensec_ntlmssp_state->ntlmssp_state);
239         if (!NT_STATUS_IS_OK(status)) {
240                 return status;
241         }
242
243         if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
244                 /*
245                  * We need to set this to allow a later SetPassword
246                  * via the SAMR pipe to succeed. Strange.... We could
247                  * also add  NTLMSSP_NEGOTIATE_SEAL here. JRA.
248                  * 
249                  * Without this, Windows will not create the master key
250                  * that it thinks is only used for NTLMSSP signing and 
251                  * sealing.  (It is actually pulled out and used directly) 
252                  */
253                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
254         }
255         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
256                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
257         }
258         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
259                 gensec_ntlmssp_state->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
260         }
261
262         status = ntlmssp_set_domain(gensec_ntlmssp_state->ntlmssp_state, 
263                                     gensec_security->user.domain);
264         if (!NT_STATUS_IS_OK(status)) {
265                 return status;
266         }
267         
268         status = ntlmssp_set_username(gensec_ntlmssp_state->ntlmssp_state, 
269                                       gensec_security->user.name);
270         if (!NT_STATUS_IS_OK(status)) {
271                 return status;
272         }
273
274         if (gensec_security->user.name) {
275                 status = gensec_get_password(gensec_security, gensec_ntlmssp_state, &password);
276                 if (!NT_STATUS_IS_OK(status)) {
277                         return status;
278                 }
279         }
280
281         if (password) {
282                 status = ntlmssp_set_password(gensec_ntlmssp_state->ntlmssp_state, 
283                                               password);
284                 if (!NT_STATUS_IS_OK(status)) {
285                         return status;
286                 }
287         }
288
289         gensec_security->private_data = gensec_ntlmssp_state;
290
291         return status;
292 }
293
294 /*
295   wrappers for the ntlmssp_*() functions
296 */
297 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
298                                              TALLOC_CTX *mem_ctx, 
299                                              uint8_t *data, size_t length, 
300                                              const uint8_t *whole_pdu, size_t pdu_length, 
301                                              DATA_BLOB *sig)
302 {
303         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
304
305         return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
306 }
307
308 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
309                                             TALLOC_CTX *mem_ctx, 
310                                             const uint8_t *data, size_t length, 
311                                             const uint8_t *whole_pdu, size_t pdu_length, 
312                                             const DATA_BLOB *sig)
313 {
314         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
315
316         return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
317 }
318
319 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 
320                                            TALLOC_CTX *mem_ctx, 
321                                            uint8_t *data, size_t length, 
322                                            const uint8_t *whole_pdu, size_t pdu_length, 
323                                            DATA_BLOB *sig)
324 {
325         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
326
327         return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
328 }
329
330 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 
331                                            TALLOC_CTX *mem_ctx, 
332                                            const uint8_t *data, size_t length, 
333                                            const uint8_t *whole_pdu, size_t pdu_length, 
334                                            DATA_BLOB *sig)
335 {
336         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
337
338         return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
339 }
340
341 static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
342 {
343         return NTLMSSP_SIG_SIZE;
344 }
345
346 static NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security, 
347                                     TALLOC_CTX *mem_ctx, 
348                                     const DATA_BLOB *in, 
349                                     DATA_BLOB *out)
350 {
351         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
352         DATA_BLOB sig;
353         NTSTATUS nt_status;
354
355         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
356
357                 *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
358                 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
359
360                 nt_status = ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
361                                                 out->data + NTLMSSP_SIG_SIZE, 
362                                                 out->length - NTLMSSP_SIG_SIZE, 
363                                                 out->data + NTLMSSP_SIG_SIZE, 
364                                                 out->length - NTLMSSP_SIG_SIZE, 
365                                                 &sig);
366
367                 if (NT_STATUS_IS_OK(nt_status)) {
368                         memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
369                 }
370                 return nt_status;
371
372         } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
373                    || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
374
375                 *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
376                 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
377
378                 nt_status = ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
379                                                 out->data + NTLMSSP_SIG_SIZE, 
380                                                 out->length - NTLMSSP_SIG_SIZE, 
381                                                 out->data + NTLMSSP_SIG_SIZE, 
382                                                 out->length - NTLMSSP_SIG_SIZE, 
383                                                 &sig);
384
385                 if (NT_STATUS_IS_OK(nt_status)) {
386                         memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
387                 }
388                 return nt_status;
389
390         } else {
391                 *out = *in;
392                 return NT_STATUS_OK;
393         }
394 }
395
396
397 static NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security, 
398                                       TALLOC_CTX *mem_ctx, 
399                                       const DATA_BLOB *in, 
400                                       DATA_BLOB *out)
401 {
402         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
403         DATA_BLOB sig;
404
405         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
406                 if (in->length < NTLMSSP_SIG_SIZE) {
407                         return NT_STATUS_INVALID_PARAMETER;
408                 }
409                 sig.data = in->data;
410                 sig.length = NTLMSSP_SIG_SIZE;
411
412                 *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
413                 
414                 return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
415                                              out->data, out->length, 
416                                              out->data, out->length, 
417                                              &sig);
418                                                   
419         } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
420                    || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
421                 if (in->length < NTLMSSP_SIG_SIZE) {
422                         return NT_STATUS_INVALID_PARAMETER;
423                 }
424                 sig.data = in->data;
425                 sig.length = NTLMSSP_SIG_SIZE;
426
427                 *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
428                 
429                 return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
430                                             out->data, out->length, 
431                                             out->data, out->length, 
432                                             &sig);
433         } else {
434                 *out = *in;
435                 return NT_STATUS_OK;
436         }
437 }
438
439 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
440                                            DATA_BLOB *session_key)
441 {
442         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
443
444         return ntlmssp_session_key(gensec_ntlmssp_state->ntlmssp_state, session_key);
445 }
446
447 /**
448  * Next state function for the wrapped NTLMSSP state machine
449  * 
450  * @param gensec_security GENSEC state, initialised to NTLMSSP
451  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
452  * @param in The request, as a DATA_BLOB
453  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
454  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
455  *                or NT_STATUS_OK if the user is authenticated. 
456  */
457
458 static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
459                                       const DATA_BLOB in, DATA_BLOB *out) 
460 {
461         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
462         NTSTATUS status;
463
464         status = ntlmssp_update(gensec_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
465
466         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
467                 return status;
468         }
469         
470         gensec_ntlmssp_state->have_features = 0;
471
472         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
473                 gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SIGN;
474         }
475
476         if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
477                 gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SEAL;
478         }
479
480         if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) {
481                 gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SESSION_KEY;
482         }
483
484         return status;
485 }
486
487 /** 
488  * Return the credentials of a logged on user, including session keys
489  * etc.
490  *
491  * Only valid after a successful authentication
492  *
493  * May only be called once per authentication.
494  *
495  */
496
497 static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
498                                             struct auth_session_info **session_info) 
499 {
500         NTSTATUS nt_status;
501         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
502         nt_status = make_session_info(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info, session_info);
503
504         if (!NT_STATUS_IS_OK(nt_status)) {
505                 return nt_status;
506         }
507
508         (*session_info)->session_key = data_blob_talloc(*session_info, 
509                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.data,
510                                                         gensec_ntlmssp_state->ntlmssp_state->session_key.length);
511
512         (*session_info)->workstation = talloc_strdup(*session_info, 
513                                                      gensec_ntlmssp_state->ntlmssp_state->workstation);
514
515         return NT_STATUS_OK;
516 }
517
518 static BOOL gensec_ntlmssp_have_feature(struct gensec_security *gensec_security,
519                                         uint32 feature)
520 {
521         struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
522         if (gensec_ntlmssp_state->have_features & feature) {
523                 return True;
524         }
525
526         return False;
527 }
528
529 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
530         .name           = "ntlmssp",
531         .sasl_name      = "NTLM",
532         .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
533         .oid            = GENSEC_OID_NTLMSSP,
534         .client_start   = gensec_ntlmssp_client_start,
535         .server_start   = gensec_ntlmssp_server_start,
536         .update         = gensec_ntlmssp_update,
537         .seal_packet    = gensec_ntlmssp_seal_packet,
538         .sig_size       = gensec_ntlmssp_sig_size,
539         .sign_packet    = gensec_ntlmssp_sign_packet,
540         .check_packet   = gensec_ntlmssp_check_packet,
541         .unseal_packet  = gensec_ntlmssp_unseal_packet,
542         .wrap           = gensec_ntlmssp_wrap,
543         .unwrap         = gensec_ntlmssp_unwrap,
544         .session_key    = gensec_ntlmssp_session_key,
545         .session_info   = gensec_ntlmssp_session_info,
546         .have_feature   = gensec_ntlmssp_have_feature
547 };
548
549
550 NTSTATUS gensec_ntlmssp_init(void)
551 {
552         NTSTATUS ret;
553         ret = gensec_register(&gensec_ntlmssp_security_ops);
554         if (!NT_STATUS_IS_OK(ret)) {
555                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
556                         gensec_ntlmssp_security_ops.name));
557                 return ret;
558         }
559
560         return ret;
561 }