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