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