d400685a49a04d820444b102835629b8fd6ed97f
[kai/samba-autobuild/.git] / source4 / auth / gensec / gensec_start.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 "../lib/util/tevent_ntstatus.h"
29 #include "librpc/rpc/dcerpc.h"
30 #include "auth/credentials/credentials.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/gensec/gensec_proto.h"
33 #include "auth/auth.h"
34 #include "auth/system_session_proto.h"
35 #include "param/param.h"
36 #include "lib/util/tsort.h"
37 #include "auth/gensec/gensec_toplevel_proto.h"
38 #include "lib/util/samba_modules.h"
39
40 /* the list of currently registered GENSEC backends */
41 static struct gensec_security_ops **generic_security_ops;
42 static int gensec_num_backends;
43
44 /* Return all the registered mechs.  Don't modify the return pointer,
45  * but you may talloc_reference it if convient */
46 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
47 {
48         return generic_security_ops;
49 }
50
51 bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security)
52 {
53         return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled);
54 }
55
56 /* Sometimes we want to force only kerberos, sometimes we want to
57  * force it's avoidance.  The old list could be either
58  * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
59  * an existing list we have trimmed down) */
60
61 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
62                                                        struct gensec_security_ops **old_gensec_list,
63                                                        struct cli_credentials *creds)
64 {
65         struct gensec_security_ops **new_gensec_list;
66         int i, j, num_mechs_in;
67         enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
68
69         if (creds) {
70                 use_kerberos = cli_credentials_get_kerberos_state(creds);
71         }
72
73         if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
74                 if (!talloc_reference(mem_ctx, old_gensec_list)) {
75                         return NULL;
76                 }
77                 return old_gensec_list;
78         }
79
80         for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
81                 /* noop */
82         }
83
84         new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
85         if (!new_gensec_list) {
86                 return NULL;
87         }
88
89         j = 0;
90         for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
91                 int oid_idx;
92
93                 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
94                         if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
95                                 new_gensec_list[j] = old_gensec_list[i];
96                                 j++;
97                                 break;
98                         }
99                 }
100                 switch (use_kerberos) {
101                 case CRED_DONT_USE_KERBEROS:
102                         if (old_gensec_list[i]->kerberos == false) {
103                                 new_gensec_list[j] = old_gensec_list[i];
104                                 j++;
105                         }
106                         break;
107                 case CRED_MUST_USE_KERBEROS:
108                         if (old_gensec_list[i]->kerberos == true) {
109                                 new_gensec_list[j] = old_gensec_list[i];
110                                 j++;
111                         }
112                         break;
113                 default:
114                         /* Can't happen or invalid parameter */
115                         return NULL;
116                 }
117         }
118         new_gensec_list[j] = NULL;
119
120         return new_gensec_list;
121 }
122
123 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
124                                                    TALLOC_CTX *mem_ctx)
125 {
126         struct gensec_security_ops **backends;
127         backends = gensec_security_all();
128         if (!gensec_security) {
129                 if (!talloc_reference(mem_ctx, backends)) {
130                         return NULL;
131                 }
132                 return backends;
133         } else {
134                 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
135                 if (!creds) {
136                         if (!talloc_reference(mem_ctx, backends)) {
137                                 return NULL;
138                         }
139                         return backends;
140                 }
141                 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
142         }
143 }
144
145 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
146                                                                      uint8_t auth_type)
147 {
148         int i;
149         struct gensec_security_ops **backends;
150         const struct gensec_security_ops *backend;
151         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
152         if (!mem_ctx) {
153                 return NULL;
154         }
155         backends = gensec_security_mechs(gensec_security, mem_ctx);
156         for (i=0; backends && backends[i]; i++) {
157                 if (!gensec_security_ops_enabled(backends[i], gensec_security))
158                                 continue;
159                 if (backends[i]->auth_type == auth_type) {
160                         backend = backends[i];
161                         talloc_free(mem_ctx);
162                         return backend;
163                 }
164         }
165         talloc_free(mem_ctx);
166
167         return NULL;
168 }
169
170 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
171                                                          const char *oid_string)
172 {
173         int i, j;
174         struct gensec_security_ops **backends;
175         const struct gensec_security_ops *backend;
176         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
177         if (!mem_ctx) {
178                 return NULL;
179         }
180         backends = gensec_security_mechs(gensec_security, mem_ctx);
181         for (i=0; backends && backends[i]; i++) {
182                 if (gensec_security != NULL &&
183                                 !gensec_security_ops_enabled(backends[i],
184                                                                                          gensec_security))
185                     continue;
186                 if (backends[i]->oid) {
187                         for (j=0; backends[i]->oid[j]; j++) {
188                                 if (backends[i]->oid[j] &&
189                                     (strcmp(backends[i]->oid[j], oid_string) == 0)) {
190                                         backend = backends[i];
191                                         talloc_free(mem_ctx);
192                                         return backend;
193                                 }
194                         }
195                 }
196         }
197         talloc_free(mem_ctx);
198
199         return NULL;
200 }
201
202 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
203                                                                const char *sasl_name)
204 {
205         int i;
206         struct gensec_security_ops **backends;
207         const struct gensec_security_ops *backend;
208         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
209         if (!mem_ctx) {
210                 return NULL;
211         }
212         backends = gensec_security_mechs(gensec_security, mem_ctx);
213         for (i=0; backends && backends[i]; i++) {
214                 if (!gensec_security_ops_enabled(backends[i], gensec_security))
215                     continue;
216                 if (backends[i]->sasl_name
217                     && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
218                         backend = backends[i];
219                         talloc_free(mem_ctx);
220                         return backend;
221                 }
222         }
223         talloc_free(mem_ctx);
224
225         return NULL;
226 }
227
228 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
229                                                                  const char *name)
230 {
231         int i;
232         struct gensec_security_ops **backends;
233         const struct gensec_security_ops *backend;
234         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
235         if (!mem_ctx) {
236                 return NULL;
237         }
238         backends = gensec_security_mechs(gensec_security, mem_ctx);
239         for (i=0; backends && backends[i]; i++) {
240                 if (gensec_security != NULL &&
241                                 !gensec_security_ops_enabled(backends[i], gensec_security))
242                     continue;
243                 if (backends[i]->name
244                     && (strcmp(backends[i]->name, name) == 0)) {
245                         backend = backends[i];
246                         talloc_free(mem_ctx);
247                         return backend;
248                 }
249         }
250         talloc_free(mem_ctx);
251         return NULL;
252 }
253
254 /**
255  * Return a unique list of security subsystems from those specified in
256  * the list of SASL names.
257  *
258  * Use the list of enabled GENSEC mechanisms from the credentials
259  * attached to the gensec_security, and return in our preferred order.
260  */
261
262 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
263                                                                 TALLOC_CTX *mem_ctx,
264                                                                 const char **sasl_names)
265 {
266         const struct gensec_security_ops **backends_out;
267         struct gensec_security_ops **backends;
268         int i, k, sasl_idx;
269         int num_backends_out = 0;
270
271         if (!sasl_names) {
272                 return NULL;
273         }
274
275         backends = gensec_security_mechs(gensec_security, mem_ctx);
276
277         backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
278         if (!backends_out) {
279                 return NULL;
280         }
281         backends_out[0] = NULL;
282
283         /* Find backends in our preferred order, by walking our list,
284          * then looking in the supplied list */
285         for (i=0; backends && backends[i]; i++) {
286                 if (gensec_security != NULL &&
287                                 !gensec_security_ops_enabled(backends[i], gensec_security))
288                     continue;
289                 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
290                         if (!backends[i]->sasl_name ||
291                             !(strcmp(backends[i]->sasl_name,
292                                      sasl_names[sasl_idx]) == 0)) {
293                                 continue;
294                         }
295
296                         for (k=0; backends_out[k]; k++) {
297                                 if (backends_out[k] == backends[i]) {
298                                         break;
299                                 }
300                         }
301
302                         if (k < num_backends_out) {
303                                 /* already in there */
304                                 continue;
305                         }
306
307                         backends_out = talloc_realloc(mem_ctx, backends_out,
308                                                       const struct gensec_security_ops *,
309                                                       num_backends_out + 2);
310                         if (!backends_out) {
311                                 return NULL;
312                         }
313
314                         backends_out[num_backends_out] = backends[i];
315                         num_backends_out++;
316                         backends_out[num_backends_out] = NULL;
317                 }
318         }
319         return backends_out;
320 }
321
322 /**
323  * Return a unique list of security subsystems from those specified in
324  * the OID list.  That is, where two OIDs refer to the same module,
325  * return that module only once.
326  *
327  * Use the list of enabled GENSEC mechanisms from the credentials
328  * attached to the gensec_security, and return in our preferred order.
329  */
330
331 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
332                                                                       TALLOC_CTX *mem_ctx,
333                                                                       const char **oid_strings,
334                                                                       const char *skip)
335 {
336         struct gensec_security_ops_wrapper *backends_out;
337         struct gensec_security_ops **backends;
338         int i, j, k, oid_idx;
339         int num_backends_out = 0;
340
341         if (!oid_strings) {
342                 return NULL;
343         }
344
345         backends = gensec_security_mechs(gensec_security, gensec_security);
346
347         backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
348         if (!backends_out) {
349                 return NULL;
350         }
351         backends_out[0].op = NULL;
352         backends_out[0].oid = NULL;
353
354         /* Find backends in our preferred order, by walking our list,
355          * then looking in the supplied list */
356         for (i=0; backends && backends[i]; i++) {
357                 if (gensec_security != NULL &&
358                                 !gensec_security_ops_enabled(backends[i], gensec_security))
359                     continue;
360                 if (!backends[i]->oid) {
361                         continue;
362                 }
363                 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
364                         if (strcmp(oid_strings[oid_idx], skip) == 0) {
365                                 continue;
366                         }
367
368                         for (j=0; backends[i]->oid[j]; j++) {
369                                 if (!backends[i]->oid[j] ||
370                                     !(strcmp(backends[i]->oid[j],
371                                             oid_strings[oid_idx]) == 0)) {
372                                         continue;
373                                 }
374
375                                 for (k=0; backends_out[k].op; k++) {
376                                         if (backends_out[k].op == backends[i]) {
377                                                 break;
378                                         }
379                                 }
380
381                                 if (k < num_backends_out) {
382                                         /* already in there */
383                                         continue;
384                                 }
385
386                                 backends_out = talloc_realloc(mem_ctx, backends_out,
387                                                               struct gensec_security_ops_wrapper,
388                                                               num_backends_out + 2);
389                                 if (!backends_out) {
390                                         return NULL;
391                                 }
392
393                                 backends_out[num_backends_out].op = backends[i];
394                                 backends_out[num_backends_out].oid = backends[i]->oid[j];
395                                 num_backends_out++;
396                                 backends_out[num_backends_out].op = NULL;
397                                 backends_out[num_backends_out].oid = NULL;
398                         }
399                 }
400         }
401         return backends_out;
402 }
403
404 /**
405  * Return OIDS from the security subsystems listed
406  */
407
408 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
409                                                                                    TALLOC_CTX *mem_ctx,
410                                            struct gensec_security_ops **ops,
411                                            const char *skip)
412 {
413         int i;
414         int j = 0;
415         int k;
416         const char **oid_list;
417         if (!ops) {
418                 return NULL;
419         }
420         oid_list = talloc_array(mem_ctx, const char *, 1);
421         if (!oid_list) {
422                 return NULL;
423         }
424
425         for (i=0; ops && ops[i]; i++) {
426                 if (gensec_security != NULL &&
427                         !gensec_security_ops_enabled(ops[i], gensec_security)) {
428                         continue;
429                 }
430                 if (!ops[i]->oid) {
431                         continue;
432                 }
433
434                 for (k = 0; ops[i]->oid[k]; k++) {
435                         if (skip && strcmp(skip, ops[i]->oid[k])==0) {
436                         } else {
437                                 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
438                                 if (!oid_list) {
439                                         return NULL;
440                                 }
441                                 oid_list[j] = ops[i]->oid[k];
442                                 j++;
443                         }
444                 }
445         }
446         oid_list[j] = NULL;
447         return oid_list;
448 }
449
450
451 /**
452  * Return OIDS from the security subsystems listed
453  */
454
455 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
456                                                    const struct gensec_security_ops_wrapper *wops)
457 {
458         int i;
459         int j = 0;
460         int k;
461         const char **oid_list;
462         if (!wops) {
463                 return NULL;
464         }
465         oid_list = talloc_array(mem_ctx, const char *, 1);
466         if (!oid_list) {
467                 return NULL;
468         }
469
470         for (i=0; wops[i].op; i++) {
471                 if (!wops[i].op->oid) {
472                         continue;
473                 }
474
475                 for (k = 0; wops[i].op->oid[k]; k++) {
476                         oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
477                         if (!oid_list) {
478                                 return NULL;
479                         }
480                         oid_list[j] = wops[i].op->oid[k];
481                         j++;
482                 }
483         }
484         oid_list[j] = NULL;
485         return oid_list;
486 }
487
488
489 /**
490  * Return all the security subsystems currently enabled on a GENSEC context.
491  *
492  * This is taken from a list attached to the cli_credentials, and
493  * skips the OID in 'skip'.  (Typically the SPNEGO OID)
494  *
495  */
496
497 const char **gensec_security_oids(struct gensec_security *gensec_security,
498                                   TALLOC_CTX *mem_ctx,
499                                   const char *skip)
500 {
501         struct gensec_security_ops **ops
502                 = gensec_security_mechs(gensec_security, mem_ctx);
503         return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
504 }
505
506 /**
507   Start the GENSEC system, returning a context pointer.
508   @param mem_ctx The parent TALLOC memory context.
509   @param gensec_security Returned GENSEC context pointer.
510   @note  The mem_ctx is only a parent and may be NULL.
511   @note, the auth context is moved to be a referenced pointer of the
512   @ gensec_security return
513 */
514 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
515                              struct tevent_context *ev,
516                              struct gensec_settings *settings,
517                              struct auth4_context *auth_context,
518                              struct gensec_security **gensec_security)
519 {
520         if (ev == NULL) {
521                 DEBUG(0, ("No event context available!\n"));
522                 return NT_STATUS_INTERNAL_ERROR;
523         }
524
525         (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
526         NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
527
528         (*gensec_security)->event_ctx = ev;
529         SMB_ASSERT(settings->lp_ctx != NULL);
530         (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
531
532         /* We need to reference this, not steal, as the caller may be
533          * python, which won't like it if we steal it's object away
534          * from it */
535         (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
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_zero(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)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
563         (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
564         (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
565
566         return NT_STATUS_OK;
567 }
568
569 /**
570   Start the GENSEC system, in client mode, returning a context pointer.
571   @param mem_ctx The parent TALLOC memory context.
572   @param gensec_security Returned GENSEC context pointer.
573   @note  The mem_ctx is only a parent and may be NULL.
574 */
575 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
576                              struct gensec_security **gensec_security,
577                              struct tevent_context *ev,
578                              struct gensec_settings *settings)
579 {
580         NTSTATUS status;
581
582         if (settings == NULL) {
583                 DEBUG(0,("gensec_client_start: no settings given!\n"));
584                 return NT_STATUS_INTERNAL_ERROR;
585         }
586
587         status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
588         if (!NT_STATUS_IS_OK(status)) {
589                 return status;
590         }
591         (*gensec_security)->gensec_role = GENSEC_CLIENT;
592
593         return status;
594 }
595
596
597
598 /**
599   Start the GENSEC system, in server mode, returning a context pointer.
600   @param mem_ctx The parent TALLOC memory context.
601   @param gensec_security Returned GENSEC context pointer.
602   @note  The mem_ctx is only a parent and may be NULL.
603 */
604 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
605                                       struct tevent_context *ev,
606                                       struct gensec_settings *settings,
607                                       struct auth4_context *auth_context,
608                                       struct gensec_security **gensec_security)
609 {
610         NTSTATUS status;
611
612         if (!ev) {
613                 DEBUG(0,("gensec_server_start: no event context given!\n"));
614                 return NT_STATUS_INTERNAL_ERROR;
615         }
616
617         if (!settings) {
618                 DEBUG(0,("gensec_server_start: no settings given!\n"));
619                 return NT_STATUS_INTERNAL_ERROR;
620         }
621
622         status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
623         if (!NT_STATUS_IS_OK(status)) {
624                 return status;
625         }
626         (*gensec_security)->gensec_role = GENSEC_SERVER;
627
628         return status;
629 }
630
631 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
632 {
633         NTSTATUS status;
634         DEBUG(5, ("Starting GENSEC %smechanism %s\n",
635                   gensec_security->subcontext ? "sub" : "",
636                   gensec_security->ops->name));
637         switch (gensec_security->gensec_role) {
638         case GENSEC_CLIENT:
639                 if (gensec_security->ops->client_start) {
640                         status = gensec_security->ops->client_start(gensec_security);
641                         if (!NT_STATUS_IS_OK(status)) {
642                                 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
643                                           gensec_security->ops->name, nt_errstr(status)));
644                         }
645                         return status;
646                 }
647                 break;
648         case GENSEC_SERVER:
649                 if (gensec_security->ops->server_start) {
650                         status = gensec_security->ops->server_start(gensec_security);
651                         if (!NT_STATUS_IS_OK(status)) {
652                                 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
653                                           gensec_security->ops->name, nt_errstr(status)));
654                         }
655                         return status;
656                 }
657                 break;
658         }
659         return NT_STATUS_INVALID_PARAMETER;
660 }
661
662 /**
663  * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
664  *
665  */
666
667 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
668                                   const struct gensec_security_ops *ops)
669 {
670         gensec_security->ops = ops;
671         return gensec_start_mech(gensec_security);
672 }
673
674
675 /**
676  * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
677  * @param gensec_security GENSEC context pointer.
678  * @param auth_type DCERPC auth type
679  * @param auth_level DCERPC auth level
680  */
681
682 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
683                                        uint8_t auth_type, uint8_t auth_level)
684 {
685         gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
686         if (!gensec_security->ops) {
687                 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
688                 return NT_STATUS_INVALID_PARAMETER;
689         }
690         gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
691         gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
692         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
693                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
694         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
695                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
696                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
697         } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
698                 /* Default features */
699         } else {
700                 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
701                          auth_level));
702                 return NT_STATUS_INVALID_PARAMETER;
703         }
704
705         return gensec_start_mech(gensec_security);
706 }
707
708 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
709 {
710         const struct gensec_security_ops *ops;
711         ops = gensec_security_by_authtype(gensec_security, authtype);
712         if (ops) {
713                 return ops->name;
714         }
715         return NULL;
716 }
717
718
719 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
720                                                                                         const char *oid_string)
721 {
722         const struct gensec_security_ops *ops;
723         ops = gensec_security_by_oid(gensec_security, oid_string);
724         if (ops) {
725                 return ops->name;
726         }
727         return oid_string;
728 }
729
730 /**
731  * Start a GENSEC sub-mechanism by OID, used in SPNEGO
732  *
733  * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
734  *       well-known #define to hook it in.
735  */
736
737 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
738                                   const char *mech_oid)
739 {
740         SMB_ASSERT(gensec_security != NULL);
741
742         gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
743         if (!gensec_security->ops) {
744                 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
745                 return NT_STATUS_INVALID_PARAMETER;
746         }
747         return gensec_start_mech(gensec_security);
748 }
749
750 /**
751  * Start a GENSEC sub-mechanism by a well know SASL name
752  *
753  */
754
755 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
756                                         const char *sasl_name)
757 {
758         gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
759         if (!gensec_security->ops) {
760                 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
761                 return NT_STATUS_INVALID_PARAMETER;
762         }
763         return gensec_start_mech(gensec_security);
764 }
765
766 /**
767  * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
768  *
769  */
770
771 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
772                                                  const char **sasl_names)
773 {
774         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
775         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
776         const struct gensec_security_ops **ops;
777         int i;
778         if (!mem_ctx) {
779                 return NT_STATUS_NO_MEMORY;
780         }
781         ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
782         if (!ops || !*ops) {
783                 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
784                           str_list_join(mem_ctx,
785                                         sasl_names, ' ')));
786                 talloc_free(mem_ctx);
787                 return NT_STATUS_INVALID_PARAMETER;
788         }
789         for (i=0; ops[i]; i++) {
790                 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
791                 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
792                         break;
793                 }
794         }
795         talloc_free(mem_ctx);
796         return nt_status;
797 }
798
799 /**
800  * Start a GENSEC sub-mechanism by an internal name
801  *
802  */
803
804 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
805                                         const char *name)
806 {
807         gensec_security->ops = gensec_security_by_name(gensec_security, name);
808         if (!gensec_security->ops) {
809                 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
810                 return NT_STATUS_INVALID_PARAMETER;
811         }
812         return gensec_start_mech(gensec_security);
813 }
814
815 /**
816  * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
817  *
818  */
819
820 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
821 {
822         gensec_security->credentials = talloc_reference(gensec_security, credentials);
823         NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
824         gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
825         return NT_STATUS_OK;
826 }
827
828 NTSTATUS gensec_generate_session_info(TALLOC_CTX *mem_ctx,
829                                       struct gensec_security *gensec_security,
830                                       struct auth_user_info_dc *user_info_dc,
831                                       struct auth_session_info **session_info)
832 {
833         NTSTATUS nt_status;
834         uint32_t session_info_flags = 0;
835
836         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
837                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
838         }
839
840         session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
841         if (user_info_dc->info->authenticated) {
842                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
843         }
844
845         if (gensec_security->auth_context) {
846                 nt_status = gensec_security->auth_context->generate_session_info(mem_ctx, gensec_security->auth_context,
847                                                                                  user_info_dc,
848                                                                                  session_info_flags,
849                                                                                  session_info);
850         } else {
851                 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
852                 nt_status = auth_generate_session_info(mem_ctx,
853                                                        NULL,
854                                                        NULL,
855                                                        user_info_dc, session_info_flags,
856                                                        session_info);
857         }
858         return nt_status;
859 }
860
861 /*
862   register a GENSEC backend.
863
864   The 'name' can be later used by other backends to find the operations
865   structure for this backend.
866 */
867 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
868 {
869         if (gensec_security_by_name(NULL, ops->name) != NULL) {
870                 /* its already registered! */
871                 DEBUG(0,("GENSEC backend '%s' already registered\n",
872                          ops->name));
873                 return NT_STATUS_OBJECT_NAME_COLLISION;
874         }
875
876         generic_security_ops = talloc_realloc(talloc_autofree_context(),
877                                               generic_security_ops,
878                                               struct gensec_security_ops *,
879                                               gensec_num_backends+2);
880         if (!generic_security_ops) {
881                 return NT_STATUS_NO_MEMORY;
882         }
883
884         generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
885         gensec_num_backends++;
886         generic_security_ops[gensec_num_backends] = NULL;
887
888         DEBUG(3,("GENSEC backend '%s' registered\n",
889                  ops->name));
890
891         return NT_STATUS_OK;
892 }
893
894 /*
895   return the GENSEC interface version, and the size of some critical types
896   This can be used by backends to either detect compilation errors, or provide
897   multiple implementations for different smbd compilation options in one module
898 */
899 const struct gensec_critical_sizes *gensec_interface_version(void)
900 {
901         static const struct gensec_critical_sizes critical_sizes = {
902                 GENSEC_INTERFACE_VERSION,
903                 sizeof(struct gensec_security_ops),
904                 sizeof(struct gensec_security),
905         };
906
907         return &critical_sizes;
908 }
909
910 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
911         return (*gs2)->priority - (*gs1)->priority;
912 }
913
914 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
915 {
916         return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
917 }
918
919 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
920 {
921         return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
922 }
923
924 /*
925   initialise the GENSEC subsystem
926 */
927 _PUBLIC_ NTSTATUS gensec_init(void)
928 {
929         static bool initialized = false;
930 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
931         STATIC_gensec_MODULES_PROTO;
932         init_module_fn static_init[] = { STATIC_gensec_MODULES };
933         init_module_fn *shared_init;
934
935         if (initialized) return NT_STATUS_OK;
936         initialized = true;
937
938         shared_init = load_samba_modules(NULL, "gensec");
939
940         run_init_functions(static_init);
941         run_init_functions(shared_init);
942
943         talloc_free(shared_init);
944
945         TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
946
947         return NT_STATUS_OK;
948 }