s4-gensec: Remove obsolete socket_address vars and fns.
[ira/wip.git] / source4 / auth / gensec / gensec.c
1 /* 
2    Unix SMB/CIFS implementation.
3  
4    Generic Authentication Interface
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
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 "system/network.h"
25 #include "lib/events/events.h"
26 #include "lib/socket/socket.h"
27 #include "lib/tsocket/tsocket.h"
28 #include "librpc/rpc/dcerpc.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "param/param.h"
32
33 /* the list of currently registered GENSEC backends */
34 static struct gensec_security_ops **generic_security_ops;
35 static int gensec_num_backends;
36
37 /* Return all the registered mechs.  Don't modify the return pointer,
38  * but you may talloc_reference it if convient */
39 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
40 {
41         return generic_security_ops;
42 }
43
44 bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security)
45 {
46         return lp_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled);
47 }
48
49 /* Sometimes we want to force only kerberos, sometimes we want to
50  * force it's avoidance.  The old list could be either
51  * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
52  * an existing list we have trimmed down) */
53
54 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, 
55                                                        struct gensec_security_ops **old_gensec_list, 
56                                                        struct cli_credentials *creds)
57 {
58         struct gensec_security_ops **new_gensec_list;
59         int i, j, num_mechs_in;
60         enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
61
62         if (creds) {
63                 use_kerberos = cli_credentials_get_kerberos_state(creds);
64         }
65
66         if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
67                 if (!talloc_reference(mem_ctx, old_gensec_list)) {
68                         return NULL;
69                 }
70                 return old_gensec_list;
71         }
72
73         for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
74                 /* noop */
75         }
76
77         new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
78         if (!new_gensec_list) {
79                 return NULL;
80         }
81
82         j = 0;
83         for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
84                 int oid_idx;
85
86                 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
87                         if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
88                                 new_gensec_list[j] = old_gensec_list[i];
89                                 j++;
90                                 break;
91                         }
92                 }
93                 switch (use_kerberos) {
94                 case CRED_DONT_USE_KERBEROS:
95                         if (old_gensec_list[i]->kerberos == false) {
96                                 new_gensec_list[j] = old_gensec_list[i];
97                                 j++;
98                         }
99                         break;
100                 case CRED_MUST_USE_KERBEROS:
101                         if (old_gensec_list[i]->kerberos == true) {
102                                 new_gensec_list[j] = old_gensec_list[i];
103                                 j++;
104                         }
105                         break;
106                 default:
107                         /* Can't happen or invalid parameter */
108                         return NULL;
109                 }
110         }
111         new_gensec_list[j] = NULL; 
112         
113         return new_gensec_list;
114 }
115
116 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
117                                                    TALLOC_CTX *mem_ctx) 
118 {
119         struct gensec_security_ops **backends;
120         backends = gensec_security_all();
121         if (!gensec_security) {
122                 if (!talloc_reference(mem_ctx, backends)) {
123                         return NULL;
124                 }
125                 return backends;
126         } else {
127                 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
128                 if (!creds) {
129                         if (!talloc_reference(mem_ctx, backends)) {
130                                 return NULL;
131                         }
132                         return backends;
133                 }
134                 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
135         }
136 }
137
138 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
139                                                                      uint8_t auth_type)
140 {
141         int i;
142         struct gensec_security_ops **backends;
143         const struct gensec_security_ops *backend;
144         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
145         if (!mem_ctx) {
146                 return NULL;
147         }
148         backends = gensec_security_mechs(gensec_security, mem_ctx);
149         for (i=0; backends && backends[i]; i++) {
150                 if (!gensec_security_ops_enabled(backends[i], gensec_security))
151                                 continue;
152                 if (backends[i]->auth_type == auth_type) {
153                         backend = backends[i];
154                         talloc_free(mem_ctx);
155                         return backend;
156                 }
157         }
158         talloc_free(mem_ctx);
159
160         return NULL;
161 }
162
163 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
164                                                          const char *oid_string)
165 {
166         int i, j;
167         struct gensec_security_ops **backends;
168         const struct gensec_security_ops *backend;
169         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
170         if (!mem_ctx) {
171                 return NULL;
172         }
173         backends = gensec_security_mechs(gensec_security, mem_ctx);
174         for (i=0; backends && backends[i]; i++) {
175                 if (gensec_security != NULL && 
176                                 !gensec_security_ops_enabled(backends[i], 
177                                                                                          gensec_security))
178                     continue;
179                 if (backends[i]->oid) {
180                         for (j=0; backends[i]->oid[j]; j++) { 
181                                 if (backends[i]->oid[j] &&
182                                     (strcmp(backends[i]->oid[j], oid_string) == 0)) {
183                                         backend = backends[i];
184                                         talloc_free(mem_ctx);
185                                         return backend;
186                                 }
187                         }
188                 }
189         }
190         talloc_free(mem_ctx);
191
192         return NULL;
193 }
194
195 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
196                                                                const char *sasl_name)
197 {
198         int i;
199         struct gensec_security_ops **backends;
200         const struct gensec_security_ops *backend;
201         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
202         if (!mem_ctx) {
203                 return NULL;
204         }
205         backends = gensec_security_mechs(gensec_security, mem_ctx);
206         for (i=0; backends && backends[i]; i++) {
207                 if (!gensec_security_ops_enabled(backends[i], gensec_security))
208                     continue;
209                 if (backends[i]->sasl_name 
210                     && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
211                         backend = backends[i];
212                         talloc_free(mem_ctx);
213                         return backend;
214                 }
215         }
216         talloc_free(mem_ctx);
217
218         return NULL;
219 }
220
221 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
222                                                                  const char *name)
223 {
224         int i;
225         struct gensec_security_ops **backends;
226         const struct gensec_security_ops *backend;
227         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
228         if (!mem_ctx) {
229                 return NULL;
230         }
231         backends = gensec_security_mechs(gensec_security, mem_ctx);
232         for (i=0; backends && backends[i]; i++) {
233                 if (gensec_security != NULL && 
234                                 !gensec_security_ops_enabled(backends[i], gensec_security))
235                     continue;
236                 if (backends[i]->name 
237                     && (strcmp(backends[i]->name, name) == 0)) {
238                         backend = backends[i];
239                         talloc_free(mem_ctx);
240                         return backend;
241                 }
242         }
243         talloc_free(mem_ctx);
244         return NULL;
245 }
246
247 /**
248  * Return a unique list of security subsystems from those specified in
249  * the list of SASL names.   
250  *
251  * Use the list of enabled GENSEC mechanisms from the credentials
252  * attached to the gensec_security, and return in our preferred order.
253  */
254
255 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
256                                                                 TALLOC_CTX *mem_ctx, 
257                                                                 const char **sasl_names)
258 {
259         const struct gensec_security_ops **backends_out;
260         struct gensec_security_ops **backends;
261         int i, k, sasl_idx;
262         int num_backends_out = 0;
263
264         if (!sasl_names) {
265                 return NULL;
266         }
267
268         backends = gensec_security_mechs(gensec_security, mem_ctx);
269
270         backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
271         if (!backends_out) {
272                 return NULL;
273         }
274         backends_out[0] = NULL;
275
276         /* Find backends in our preferred order, by walking our list,
277          * then looking in the supplied list */
278         for (i=0; backends && backends[i]; i++) {
279                 if (gensec_security != NULL &&
280                                 !gensec_security_ops_enabled(backends[i], gensec_security))
281                     continue;
282                 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
283                         if (!backends[i]->sasl_name ||
284                             !(strcmp(backends[i]->sasl_name, 
285                                      sasl_names[sasl_idx]) == 0)) {
286                                 continue;
287                         }
288                         
289                         for (k=0; backends_out[k]; k++) {
290                                 if (backends_out[k] == backends[i]) {
291                                         break;
292                                 }
293                         }
294                         
295                         if (k < num_backends_out) {
296                                 /* already in there */
297                                 continue;
298                         }
299                         
300                         backends_out = talloc_realloc(mem_ctx, backends_out, 
301                                                       const struct gensec_security_ops *, 
302                                                       num_backends_out + 2);
303                         if (!backends_out) {
304                                 return NULL;
305                         }
306                         
307                         backends_out[num_backends_out] = backends[i];
308                         num_backends_out++;
309                         backends_out[num_backends_out] = NULL;
310                 }
311         }
312         return backends_out;
313 }
314
315 /**
316  * Return a unique list of security subsystems from those specified in
317  * the OID list.  That is, where two OIDs refer to the same module,
318  * return that module only once. 
319  *
320  * Use the list of enabled GENSEC mechanisms from the credentials
321  * attached to the gensec_security, and return in our preferred order.
322  */
323
324 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
325                                                                       TALLOC_CTX *mem_ctx, 
326                                                                       const char **oid_strings,
327                                                                       const char *skip)
328 {
329         struct gensec_security_ops_wrapper *backends_out;
330         struct gensec_security_ops **backends;
331         int i, j, k, oid_idx;
332         int num_backends_out = 0;
333
334         if (!oid_strings) {
335                 return NULL;
336         }
337
338         backends = gensec_security_mechs(gensec_security, gensec_security);
339
340         backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
341         if (!backends_out) {
342                 return NULL;
343         }
344         backends_out[0].op = NULL;
345         backends_out[0].oid = NULL;
346
347         /* Find backends in our preferred order, by walking our list,
348          * then looking in the supplied list */
349         for (i=0; backends && backends[i]; i++) {
350                 if (gensec_security != NULL && 
351                                 !gensec_security_ops_enabled(backends[i], gensec_security))
352                     continue;
353                 if (!backends[i]->oid) {
354                         continue;
355                 }
356                 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
357                         if (strcmp(oid_strings[oid_idx], skip) == 0) {
358                                 continue;
359                         }
360
361                         for (j=0; backends[i]->oid[j]; j++) { 
362                                 if (!backends[i]->oid[j] ||
363                                     !(strcmp(backends[i]->oid[j], 
364                                             oid_strings[oid_idx]) == 0)) {
365                                         continue;
366                                 }
367                                 
368                                 for (k=0; backends_out[k].op; k++) {
369                                         if (backends_out[k].op == backends[i]) {
370                                                 break;
371                                         }
372                                 }
373                                 
374                                 if (k < num_backends_out) {
375                                         /* already in there */
376                                         continue;
377                                 }
378
379                                 backends_out = talloc_realloc(mem_ctx, backends_out, 
380                                                               struct gensec_security_ops_wrapper, 
381                                                               num_backends_out + 2);
382                                 if (!backends_out) {
383                                         return NULL;
384                                 }
385                                 
386                                 backends_out[num_backends_out].op = backends[i];
387                                 backends_out[num_backends_out].oid = backends[i]->oid[j];
388                                 num_backends_out++;
389                                 backends_out[num_backends_out].op = NULL;
390                                 backends_out[num_backends_out].oid = NULL;
391                         }
392                 }
393         }
394         return backends_out;
395 }
396
397 /**
398  * Return OIDS from the security subsystems listed
399  */
400
401 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
402                                                                                    TALLOC_CTX *mem_ctx, 
403                                            struct gensec_security_ops **ops,                               
404                                            const char *skip) 
405 {
406         int i;
407         int j = 0;
408         int k;
409         const char **oid_list;
410         if (!ops) {
411                 return NULL;
412         }
413         oid_list = talloc_array(mem_ctx, const char *, 1);
414         if (!oid_list) {
415                 return NULL;
416         }
417         
418         for (i=0; ops && ops[i]; i++) {
419                 if (gensec_security != NULL && 
420                         !gensec_security_ops_enabled(ops[i], gensec_security)) {
421                         continue;
422                 }
423                 if (!ops[i]->oid) {
424                         continue;
425                 }
426                 
427                 for (k = 0; ops[i]->oid[k]; k++) {
428                         if (skip && strcmp(skip, ops[i]->oid[k])==0) {
429                         } else {
430                                 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
431                                 if (!oid_list) {
432                                         return NULL;
433                                 }
434                                 oid_list[j] = ops[i]->oid[k];
435                                 j++;
436                         }
437                 }
438         }
439         oid_list[j] = NULL;
440         return oid_list;
441 }
442
443
444 /**
445  * Return OIDS from the security subsystems listed
446  */
447
448 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx, 
449                                                    const struct gensec_security_ops_wrapper *wops)
450 {
451         int i;
452         int j = 0;
453         int k;
454         const char **oid_list;
455         if (!wops) {
456                 return NULL;
457         }
458         oid_list = talloc_array(mem_ctx, const char *, 1);
459         if (!oid_list) {
460                 return NULL;
461         }
462         
463         for (i=0; wops[i].op; i++) {
464                 if (!wops[i].op->oid) {
465                         continue;
466                 }
467                 
468                 for (k = 0; wops[i].op->oid[k]; k++) {
469                         oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
470                         if (!oid_list) {
471                                 return NULL;
472                         }
473                         oid_list[j] = wops[i].op->oid[k];
474                         j++;
475                 }
476         }
477         oid_list[j] = NULL;
478         return oid_list;
479 }
480
481
482 /**
483  * Return all the security subsystems currently enabled on a GENSEC context.
484  * 
485  * This is taken from a list attached to the cli_credentials, and
486  * skips the OID in 'skip'.  (Typically the SPNEGO OID)
487  * 
488  */
489
490 const char **gensec_security_oids(struct gensec_security *gensec_security, 
491                                   TALLOC_CTX *mem_ctx, 
492                                   const char *skip) 
493 {
494         struct gensec_security_ops **ops
495                 = gensec_security_mechs(gensec_security, mem_ctx);
496         return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
497 }
498
499
500
501 /**
502   Start the GENSEC system, returning a context pointer.
503   @param mem_ctx The parent TALLOC memory context.
504   @param gensec_security Returned GENSEC context pointer.
505   @note  The mem_ctx is only a parent and may be NULL.
506   @note, the auth context is moved to be a child of the
507   @ gensec_security return 
508 */
509 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx, 
510                              struct tevent_context *ev,
511                              struct gensec_settings *settings,
512                              struct auth_context *auth_context,
513                              struct gensec_security **gensec_security)
514 {
515         if (ev == NULL) {
516                 DEBUG(0, ("No event context available!\n"));
517                 return NT_STATUS_INTERNAL_ERROR;
518         }
519
520         (*gensec_security) = talloc(mem_ctx, struct gensec_security);
521         NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
522
523         (*gensec_security)->ops = NULL;
524         (*gensec_security)->local_addr = NULL;
525         (*gensec_security)->remote_addr = NULL;
526         (*gensec_security)->private_data = NULL;
527
528         ZERO_STRUCT((*gensec_security)->target);
529
530         (*gensec_security)->subcontext = false;
531         (*gensec_security)->want_features = 0;
532
533         (*gensec_security)->event_ctx = ev;
534         SMB_ASSERT(settings->lp_ctx != NULL);
535         (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
536         (*gensec_security)->auth_context = talloc_steal(*gensec_security, auth_context);
537
538         return NT_STATUS_OK;
539 }
540
541 /** 
542  * Start a GENSEC subcontext, with a copy of the properties of the parent
543  * @param mem_ctx The parent TALLOC memory context.
544  * @param parent The parent GENSEC context 
545  * @param gensec_security Returned GENSEC context pointer.
546  * @note Used by SPNEGO in particular, for the actual implementation mechanism
547  */
548
549 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx, 
550                                  struct gensec_security *parent, 
551                                  struct gensec_security **gensec_security)
552 {
553         (*gensec_security) = talloc(mem_ctx, struct gensec_security);
554         NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
555
556         (**gensec_security) = *parent;
557         (*gensec_security)->ops = NULL;
558         (*gensec_security)->private_data = NULL;
559
560         (*gensec_security)->subcontext = true;
561         (*gensec_security)->want_features = parent->want_features;
562         (*gensec_security)->event_ctx = parent->event_ctx;
563         (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
564         (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
565         (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
566
567         return NT_STATUS_OK;
568 }
569
570 /**
571   Start the GENSEC system, in client mode, returning a context pointer.
572   @param mem_ctx The parent TALLOC memory context.
573   @param gensec_security Returned GENSEC context pointer.
574   @note  The mem_ctx is only a parent and may be NULL.
575 */
576 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx, 
577                              struct gensec_security **gensec_security,
578                              struct tevent_context *ev,
579                              struct gensec_settings *settings)
580 {
581         NTSTATUS status;
582
583         if (settings == NULL) {
584                 DEBUG(0,("gensec_client_start: no settings given!\n"));
585                 return NT_STATUS_INTERNAL_ERROR;
586         }
587
588         status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
589         if (!NT_STATUS_IS_OK(status)) {
590                 return status;
591         }
592         (*gensec_security)->gensec_role = GENSEC_CLIENT;
593
594         return status;
595 }
596
597 /**
598   Start the GENSEC system, in server mode, returning a context pointer.
599   @param mem_ctx The parent TALLOC memory context.
600   @param gensec_security Returned GENSEC context pointer.
601   @note  The mem_ctx is only a parent and may be NULL.
602 */
603 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx, 
604                                       struct tevent_context *ev,
605                                       struct gensec_settings *settings,
606                                       struct auth_context *auth_context,
607                                       struct gensec_security **gensec_security)
608 {
609         NTSTATUS status;
610
611         if (!ev) {
612                 DEBUG(0,("gensec_server_start: no event context given!\n"));
613                 return NT_STATUS_INTERNAL_ERROR;
614         }
615
616         if (!settings) {
617                 DEBUG(0,("gensec_server_start: no settings given!\n"));
618                 return NT_STATUS_INTERNAL_ERROR;
619         }
620
621         status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
622         if (!NT_STATUS_IS_OK(status)) {
623                 return status;
624         }
625         (*gensec_security)->gensec_role = GENSEC_SERVER;
626
627         return status;
628 }
629
630 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security) 
631 {
632         NTSTATUS status;
633         DEBUG(5, ("Starting GENSEC %smechanism %s\n", 
634                   gensec_security->subcontext ? "sub" : "", 
635                   gensec_security->ops->name));
636         switch (gensec_security->gensec_role) {
637         case GENSEC_CLIENT:
638                 if (gensec_security->ops->client_start) {
639                         status = gensec_security->ops->client_start(gensec_security);
640                         if (!NT_STATUS_IS_OK(status)) {
641                                 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
642                                           gensec_security->ops->name, nt_errstr(status))); 
643                         }
644                         return status;
645                 }
646                 break;
647         case GENSEC_SERVER:
648                 if (gensec_security->ops->server_start) {
649                         status = gensec_security->ops->server_start(gensec_security);
650                         if (!NT_STATUS_IS_OK(status)) {
651                                 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
652                                           gensec_security->ops->name, nt_errstr(status))); 
653                         }
654                         return status;
655                 }
656                 break;
657         }
658         return NT_STATUS_INVALID_PARAMETER;
659 }
660
661 /** 
662  * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number 
663  * @param gensec_security GENSEC context pointer.
664  * @param auth_type DCERPC auth type
665  * @param auth_level DCERPC auth level 
666  */
667
668 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security, 
669                                        uint8_t auth_type, uint8_t auth_level) 
670 {
671         gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
672         if (!gensec_security->ops) {
673                 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
674                 return NT_STATUS_INVALID_PARAMETER;
675         }
676         gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
677         gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
678         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
679                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
680         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
681                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
682                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
683         } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
684                 /* Default features */
685         } else {
686                 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n", 
687                          auth_level));
688                 return NT_STATUS_INVALID_PARAMETER;
689         }
690
691         return gensec_start_mech(gensec_security);
692 }
693
694 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype) 
695 {
696         const struct gensec_security_ops *ops;
697         ops = gensec_security_by_authtype(gensec_security, authtype);
698         if (ops) {
699                 return ops->name;
700         }
701         return NULL;
702 }
703         
704
705 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
706                                                                                         const char *oid_string) 
707 {
708         const struct gensec_security_ops *ops;
709         ops = gensec_security_by_oid(gensec_security, oid_string);
710         if (ops) {
711                 return ops->name;
712         }
713         return oid_string;
714 }
715         
716
717 /** 
718  * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
719  *
720  */
721
722 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security, 
723                                   const struct gensec_security_ops *ops) 
724 {
725         gensec_security->ops = ops;
726         return gensec_start_mech(gensec_security);
727 }
728
729 /** 
730  * Start a GENSEC sub-mechanism by OID, used in SPNEGO
731  *
732  * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
733  *       well-known #define to hook it in.
734  */
735
736 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security, 
737                                   const char *mech_oid) 
738 {
739         SMB_ASSERT(gensec_security != NULL);
740
741         gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
742         if (!gensec_security->ops) {
743                 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
744                 return NT_STATUS_INVALID_PARAMETER;
745         }
746         return gensec_start_mech(gensec_security);
747 }
748
749 /** 
750  * Start a GENSEC sub-mechanism by a well know SASL name
751  *
752  */
753
754 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security, 
755                                         const char *sasl_name) 
756 {
757         gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
758         if (!gensec_security->ops) {
759                 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
760                 return NT_STATUS_INVALID_PARAMETER;
761         }
762         return gensec_start_mech(gensec_security);
763 }
764
765 /** 
766  * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
767  *
768  */
769
770 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security, 
771                                                  const char **sasl_names) 
772 {
773         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
774         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
775         const struct gensec_security_ops **ops;
776         int i;
777         if (!mem_ctx) {
778                 return NT_STATUS_NO_MEMORY;
779         }
780         ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
781         if (!ops || !*ops) {
782                 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n", 
783                           str_list_join(mem_ctx, 
784                                         sasl_names, ' ')));
785                 talloc_free(mem_ctx);
786                 return NT_STATUS_INVALID_PARAMETER;
787         }
788         for (i=0; ops[i]; i++) {
789                 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
790                 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
791                         break;
792                 }
793         }
794         talloc_free(mem_ctx);
795         return nt_status;
796 }
797
798 /** 
799  * Start a GENSEC sub-mechanism by an internal name
800  *
801  */
802
803 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security, 
804                                         const char *name) 
805 {
806         gensec_security->ops = gensec_security_by_name(gensec_security, name);
807         if (!gensec_security->ops) {
808                 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
809                 return NT_STATUS_INVALID_PARAMETER;
810         }
811         return gensec_start_mech(gensec_security);
812 }
813
814 /*
815   wrappers for the gensec function pointers
816 */
817 _PUBLIC_ NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security, 
818                               TALLOC_CTX *mem_ctx, 
819                               uint8_t *data, size_t length, 
820                               const uint8_t *whole_pdu, size_t pdu_length, 
821                               const DATA_BLOB *sig)
822 {
823         if (!gensec_security->ops->unseal_packet) {
824                 return NT_STATUS_NOT_IMPLEMENTED;
825         }
826         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
827                 return NT_STATUS_INVALID_PARAMETER;
828         }
829         
830         return gensec_security->ops->unseal_packet(gensec_security, mem_ctx, 
831                                                    data, length, 
832                                                    whole_pdu, pdu_length, 
833                                                    sig);
834 }
835
836 _PUBLIC_ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security, 
837                              TALLOC_CTX *mem_ctx, 
838                              const uint8_t *data, size_t length, 
839                              const uint8_t *whole_pdu, size_t pdu_length, 
840                              const DATA_BLOB *sig)
841 {
842         if (!gensec_security->ops->check_packet) {
843                 return NT_STATUS_NOT_IMPLEMENTED;
844         }
845         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
846                 return NT_STATUS_INVALID_PARAMETER;
847         }
848         
849         return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
850 }
851
852 _PUBLIC_ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security, 
853                             TALLOC_CTX *mem_ctx, 
854                             uint8_t *data, size_t length, 
855                             const uint8_t *whole_pdu, size_t pdu_length, 
856                             DATA_BLOB *sig)
857 {
858         if (!gensec_security->ops->seal_packet) {
859                 return NT_STATUS_NOT_IMPLEMENTED;
860         }
861         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
862                 return NT_STATUS_INVALID_PARAMETER;
863         }
864         
865         return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
866 }
867
868 _PUBLIC_ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security, 
869                             TALLOC_CTX *mem_ctx, 
870                             const uint8_t *data, size_t length, 
871                             const uint8_t *whole_pdu, size_t pdu_length, 
872                             DATA_BLOB *sig)
873 {
874         if (!gensec_security->ops->sign_packet) {
875                 return NT_STATUS_NOT_IMPLEMENTED;
876         }
877         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
878                 return NT_STATUS_INVALID_PARAMETER;
879         }
880         
881         return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
882 }
883
884 _PUBLIC_ size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size) 
885 {
886         if (!gensec_security->ops->sig_size) {
887                 return 0;
888         }
889         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
890                 return 0;
891         }
892         
893         return gensec_security->ops->sig_size(gensec_security, data_size);
894 }
895
896 size_t gensec_max_wrapped_size(struct gensec_security *gensec_security) 
897 {
898         if (!gensec_security->ops->max_wrapped_size) {
899                 return (1 << 17);
900         }
901         
902         return gensec_security->ops->max_wrapped_size(gensec_security);
903 }
904
905 size_t gensec_max_input_size(struct gensec_security *gensec_security) 
906 {
907         if (!gensec_security->ops->max_input_size) {
908                 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
909         }
910         
911         return gensec_security->ops->max_input_size(gensec_security);
912 }
913
914 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security, 
915                      TALLOC_CTX *mem_ctx, 
916                      const DATA_BLOB *in, 
917                      DATA_BLOB *out) 
918 {
919         if (!gensec_security->ops->wrap) {
920                 return NT_STATUS_NOT_IMPLEMENTED;
921         }
922         return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
923 }
924
925 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security, 
926                        TALLOC_CTX *mem_ctx, 
927                        const DATA_BLOB *in, 
928                        DATA_BLOB *out) 
929 {
930         if (!gensec_security->ops->unwrap) {
931                 return NT_STATUS_NOT_IMPLEMENTED;
932         }
933         return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
934 }
935
936 _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security, 
937                             DATA_BLOB *session_key)
938 {
939         if (!gensec_security->ops->session_key) {
940                 return NT_STATUS_NOT_IMPLEMENTED;
941         }
942         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
943                 return NT_STATUS_NO_USER_SESSION_KEY;
944         }
945         
946         return gensec_security->ops->session_key(gensec_security, session_key);
947 }
948
949 /** 
950  * Return the credentials of a logged on user, including session keys
951  * etc.
952  *
953  * Only valid after a successful authentication
954  *
955  * May only be called once per authentication.
956  *
957  */
958
959 _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security, 
960                              struct auth_session_info **session_info)
961 {
962         if (!gensec_security->ops->session_info) {
963                 return NT_STATUS_NOT_IMPLEMENTED;
964         }
965         return gensec_security->ops->session_info(gensec_security, session_info);
966 }
967
968 /**
969  * Next state function for the GENSEC state machine
970  * 
971  * @param gensec_security GENSEC State
972  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
973  * @param in The request, as a DATA_BLOB
974  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
975  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
976  *                or NT_STATUS_OK if the user is authenticated. 
977  */
978
979 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
980                        const DATA_BLOB in, DATA_BLOB *out) 
981 {
982         return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
983 }
984
985 static void gensec_update_async_timed_handler(struct tevent_context *ev, struct tevent_timer *te,
986                                               struct timeval t, void *ptr)
987 {
988         struct gensec_update_request *req = talloc_get_type(ptr, struct gensec_update_request);
989         req->status = req->gensec_security->ops->update(req->gensec_security, req, req->in, &req->out);
990         req->callback.fn(req, req->callback.private_data);
991 }
992
993 /**
994  * Next state function for the GENSEC state machine async version
995  * 
996  * @param gensec_security GENSEC State
997  * @param in The request, as a DATA_BLOB
998  * @param callback The function that will be called when the operation is
999  *                 finished, it should return gensec_update_recv() to get output
1000  * @param private_data A private pointer that will be passed to the callback function
1001  */
1002
1003 _PUBLIC_ void gensec_update_send(struct gensec_security *gensec_security, const DATA_BLOB in,
1004                                  void (*callback)(struct gensec_update_request *req, void *private_data),
1005                                  void *private_data)
1006 {
1007         struct gensec_update_request *req = NULL;
1008         struct tevent_timer *te = NULL;
1009
1010         req = talloc(gensec_security, struct gensec_update_request);
1011         if (!req) goto failed;
1012         req->gensec_security            = gensec_security;
1013         req->in                         = in;
1014         req->out                        = data_blob(NULL, 0);
1015         req->callback.fn                = callback;
1016         req->callback.private_data      = private_data;
1017
1018         te = event_add_timed(gensec_security->event_ctx, req,
1019                              timeval_zero(),
1020                              gensec_update_async_timed_handler, req);
1021         if (!te) goto failed;
1022
1023         return;
1024
1025 failed:
1026         talloc_free(req);
1027         callback(NULL, private_data);
1028 }
1029
1030 /**
1031  * Next state function for the GENSEC state machine
1032  * 
1033  * @param req GENSEC update request state
1034  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
1035  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
1036  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
1037  *                or NT_STATUS_OK if the user is authenticated. 
1038  */
1039 _PUBLIC_ NTSTATUS gensec_update_recv(struct gensec_update_request *req, TALLOC_CTX *out_mem_ctx, DATA_BLOB *out)
1040 {
1041         NTSTATUS status;
1042
1043         NT_STATUS_HAVE_NO_MEMORY(req);
1044
1045         *out = req->out;
1046         talloc_steal(out_mem_ctx, out->data);
1047         status = req->status;
1048
1049         talloc_free(req);
1050         return status;
1051 }
1052
1053 /** 
1054  * Set the requirement for a certain feature on the connection
1055  *
1056  */
1057
1058 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
1059                          uint32_t feature) 
1060 {
1061         if (!gensec_security->ops || !gensec_security->ops->want_feature) {
1062                 gensec_security->want_features |= feature;
1063                 return;
1064         }
1065         gensec_security->ops->want_feature(gensec_security, feature);
1066 }
1067
1068 /** 
1069  * Check the requirement for a certain feature on the connection
1070  *
1071  */
1072
1073 _PUBLIC_ bool gensec_have_feature(struct gensec_security *gensec_security,
1074                          uint32_t feature) 
1075 {
1076         if (!gensec_security->ops->have_feature) {
1077                 return false;
1078         }
1079         
1080         /* We might 'have' features that we don't 'want', because the
1081          * other end demanded them, or we can't neotiate them off */
1082         return gensec_security->ops->have_feature(gensec_security, feature);
1083 }
1084
1085 /** 
1086  * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context 
1087  *
1088  */
1089
1090 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials) 
1091 {
1092         gensec_security->credentials = talloc_reference(gensec_security, credentials);
1093         NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1094         gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1095         return NT_STATUS_OK;
1096 }
1097
1098 /** 
1099  * Return the credentials structure associated with a GENSEC context
1100  *
1101  */
1102
1103 _PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security) 
1104 {
1105         if (!gensec_security) {
1106                 return NULL;
1107         }
1108         return gensec_security->credentials;
1109 }
1110
1111 /** 
1112  * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed 
1113  *
1114  */
1115
1116 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service) 
1117 {
1118         gensec_security->target.service = talloc_strdup(gensec_security, service);
1119         if (!gensec_security->target.service) {
1120                 return NT_STATUS_NO_MEMORY;
1121         }
1122         return NT_STATUS_OK;
1123 }
1124
1125 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security) 
1126 {
1127         if (gensec_security->target.service) {
1128                 return gensec_security->target.service;
1129         }
1130
1131         return "host";
1132 }
1133
1134 /** 
1135  * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed 
1136  *
1137  */
1138
1139 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname) 
1140 {
1141         gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
1142         if (hostname && !gensec_security->target.hostname) {
1143                 return NT_STATUS_NO_MEMORY;
1144         }
1145         return NT_STATUS_OK;
1146 }
1147
1148 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security) 
1149 {
1150         /* We allow the target hostname to be overriden for testing purposes */
1151         if (gensec_security->settings->target_hostname) {
1152                 return gensec_security->settings->target_hostname;
1153         }
1154
1155         if (gensec_security->target.hostname) {
1156                 return gensec_security->target.hostname;
1157         }
1158
1159         /* We could add use the 'set sockaddr' call, and do a reverse
1160          * lookup, but this would be both insecure (compromising the
1161          * way kerberos works) and add DNS timeouts */
1162         return NULL;
1163 }
1164
1165 /**
1166  * Set (and talloc_reference) local and peer socket addresses onto a socket
1167  * context on the GENSEC context.
1168  *
1169  * This is so that kerberos can include these addresses in
1170  * cryptographic tokens, to avoid certain attacks.
1171  */
1172
1173 /**
1174  * @brief Set the local gensec address.
1175  *
1176  * @param  gensec_security   The gensec security context to use.
1177  *
1178  * @param  remote       The local address to set.
1179  *
1180  * @return              On success NT_STATUS_OK is returned or an NT_STATUS
1181  *                      error.
1182  */
1183 _PUBLIC_ NTSTATUS gensec_set_local_address(struct gensec_security *gensec_security,
1184                 const struct tsocket_address *local)
1185 {
1186         TALLOC_FREE(gensec_security->local_addr);
1187         gensec_security->local_addr = tsocket_address_copy(local, gensec_security);
1188         if (gensec_security->local_addr == NULL) {
1189                 return NT_STATUS_NO_MEMORY;
1190         }
1191
1192         return NT_STATUS_OK;
1193 }
1194
1195 /**
1196  * @brief Set the remote gensec address.
1197  *
1198  * @param  gensec_security   The gensec security context to use.
1199  *
1200  * @param  remote       The remote address to set.
1201  *
1202  * @return              On success NT_STATUS_OK is returned or an NT_STATUS
1203  *                      error.
1204  */
1205 _PUBLIC_ NTSTATUS gensec_set_remote_address(struct gensec_security *gensec_security,
1206                 const struct tsocket_address *remote)
1207 {
1208         TALLOC_FREE(gensec_security->remote_addr);
1209         gensec_security->remote_addr = tsocket_address_copy(remote, gensec_security);
1210         if (gensec_security->remote_addr == NULL) {
1211                 return NT_STATUS_NO_MEMORY;
1212         }
1213
1214         return NT_STATUS_OK;
1215 }
1216
1217 /**
1218  * @brief Get the local address from a gensec security context.
1219  *
1220  * @param  gensec_security   The security context to get the address from.
1221  *
1222  * @return              The address as tsocket_address which could be NULL if
1223  *                      no address is set.
1224  */
1225 _PUBLIC_ const struct tsocket_address *gensec_get_local_address(struct gensec_security *gensec_security)
1226 {
1227         if (gensec_security == NULL) {
1228                 return NULL;
1229         }
1230         return gensec_security->local_addr;
1231 }
1232
1233 /**
1234  * @brief Get the remote address from a gensec security context.
1235  *
1236  * @param  gensec_security   The security context to get the address from.
1237  *
1238  * @return              The address as tsocket_address which could be NULL if
1239  *                      no address is set.
1240  */
1241 _PUBLIC_ const struct tsocket_address *gensec_get_remote_address(struct gensec_security *gensec_security)
1242 {
1243         if (gensec_security == NULL) {
1244                 return NULL;
1245         }
1246         return gensec_security->remote_addr;
1247 }
1248
1249
1250 /** 
1251  * Set the target principal (assuming it it known, say from the SPNEGO reply)
1252  *  - ensures it is talloc()ed 
1253  *
1254  */
1255
1256 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal) 
1257 {
1258         gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1259         if (!gensec_security->target.principal) {
1260                 return NT_STATUS_NO_MEMORY;
1261         }
1262         return NT_STATUS_OK;
1263 }
1264
1265 const char *gensec_get_target_principal(struct gensec_security *gensec_security) 
1266 {
1267         if (gensec_security->target.principal) {
1268                 return gensec_security->target.principal;
1269         }
1270
1271         return NULL;
1272 }
1273
1274 /*
1275   register a GENSEC backend. 
1276
1277   The 'name' can be later used by other backends to find the operations
1278   structure for this backend.
1279 */
1280 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
1281 {
1282         if (gensec_security_by_name(NULL, ops->name) != NULL) {
1283                 /* its already registered! */
1284                 DEBUG(0,("GENSEC backend '%s' already registered\n", 
1285                          ops->name));
1286                 return NT_STATUS_OBJECT_NAME_COLLISION;
1287         }
1288
1289         generic_security_ops = talloc_realloc(talloc_autofree_context(), 
1290                                               generic_security_ops, 
1291                                               struct gensec_security_ops *, 
1292                                               gensec_num_backends+2);
1293         if (!generic_security_ops) {
1294                 return NT_STATUS_NO_MEMORY;
1295         }
1296
1297         generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
1298         gensec_num_backends++;
1299         generic_security_ops[gensec_num_backends] = NULL;
1300
1301         DEBUG(3,("GENSEC backend '%s' registered\n", 
1302                  ops->name));
1303
1304         return NT_STATUS_OK;
1305 }
1306
1307 /*
1308   return the GENSEC interface version, and the size of some critical types
1309   This can be used by backends to either detect compilation errors, or provide
1310   multiple implementations for different smbd compilation options in one module
1311 */
1312 const struct gensec_critical_sizes *gensec_interface_version(void)
1313 {
1314         static const struct gensec_critical_sizes critical_sizes = {
1315                 GENSEC_INTERFACE_VERSION,
1316                 sizeof(struct gensec_security_ops),
1317                 sizeof(struct gensec_security),
1318         };
1319
1320         return &critical_sizes;
1321 }
1322
1323 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
1324         return (*gs2)->priority - (*gs1)->priority;
1325 }
1326
1327 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
1328 {
1329         return lp_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1330 }
1331
1332 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
1333 {
1334         return lp_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1335 }
1336
1337 /*
1338   initialise the GENSEC subsystem
1339 */
1340 _PUBLIC_ NTSTATUS gensec_init(struct loadparm_context *lp_ctx)
1341 {
1342         static bool initialized = false;
1343         extern NTSTATUS gensec_sasl_init(void);
1344         extern NTSTATUS gensec_krb5_init(void);
1345         extern NTSTATUS gensec_schannel_init(void);
1346         extern NTSTATUS gensec_spnego_init(void);
1347         extern NTSTATUS gensec_gssapi_init(void);
1348         extern NTSTATUS gensec_ntlmssp_init(void);
1349
1350         init_module_fn static_init[] = { STATIC_gensec_MODULES };
1351         init_module_fn *shared_init;
1352
1353         if (initialized) return NT_STATUS_OK;
1354         initialized = true;
1355         
1356         shared_init = load_samba_modules(NULL, lp_ctx, "gensec");
1357
1358         run_init_functions(static_init);
1359         run_init_functions(shared_init);
1360
1361         talloc_free(shared_init);
1362
1363         qsort(generic_security_ops, gensec_num_backends, sizeof(*generic_security_ops), QSORT_CAST sort_gensec);
1364         
1365         return NT_STATUS_OK;
1366 }