ldb_tdb: Warn when reindexing is done
[Samba/vl.git] / auth / gensec / gensec_start.c
blobe46f0ee85107f51ab80fa29c509e7c9a1d3d84b0
1 /*
2 Unix SMB/CIFS implementation.
4 Generic Authentication Interface
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
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.
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.
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/>.
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 "lib/param/param.h"
31 #include "lib/util/tsort.h"
32 #include "lib/util/samba_modules.h"
34 /* the list of currently registered GENSEC backends */
35 static struct gensec_security_ops **generic_security_ops;
36 static int gensec_num_backends;
38 /* Return all the registered mechs. Don't modify the return pointer,
39 * but you may talloc_reference it if convient */
40 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
42 return generic_security_ops;
45 bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security)
47 return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled);
50 /* Sometimes we want to force only kerberos, sometimes we want to
51 * force it's avoidance. The old list could be either
52 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
53 * an existing list we have trimmed down)
55 * The intended logic is:
57 * if we are in the default AUTO have kerberos:
58 * - take a reference to the master list
59 * otherwise
60 * - always add spnego then:
61 * - if we 'MUST' have kerberos:
62 * only add kerberos mechs
63 * - if we 'DONT' want kerberos':
64 * only add non-kerberos mechs
66 * Once we get things like NegoEx or moonshot, this will of course get
67 * more compplex.
70 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
71 struct gensec_security_ops **old_gensec_list,
72 struct cli_credentials *creds)
74 struct gensec_security_ops **new_gensec_list;
75 int i, j, num_mechs_in;
76 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
78 if (creds) {
79 use_kerberos = cli_credentials_get_kerberos_state(creds);
82 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
83 if (!talloc_reference(mem_ctx, old_gensec_list)) {
84 return NULL;
86 return old_gensec_list;
89 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
90 /* noop */
93 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
94 if (!new_gensec_list) {
95 return NULL;
98 j = 0;
99 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
100 int oid_idx;
101 bool found_spnego = false;
102 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
103 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
104 new_gensec_list[j] = old_gensec_list[i];
105 j++;
106 found_spnego = true;
107 break;
110 if (found_spnego) {
111 continue;
113 switch (use_kerberos) {
114 case CRED_DONT_USE_KERBEROS:
115 if (old_gensec_list[i]->kerberos == false) {
116 new_gensec_list[j] = old_gensec_list[i];
117 j++;
119 break;
120 case CRED_MUST_USE_KERBEROS:
121 if (old_gensec_list[i]->kerberos == true) {
122 new_gensec_list[j] = old_gensec_list[i];
123 j++;
125 break;
126 default:
127 /* Can't happen or invalid parameter */
128 return NULL;
131 new_gensec_list[j] = NULL;
133 return new_gensec_list;
136 _PUBLIC_ struct gensec_security_ops **gensec_security_mechs(
137 struct gensec_security *gensec_security,
138 TALLOC_CTX *mem_ctx)
140 struct gensec_security_ops **backends;
141 if (!gensec_security) {
142 backends = gensec_security_all();
143 if (!talloc_reference(mem_ctx, backends)) {
144 return NULL;
146 return backends;
147 } else {
148 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
149 if (gensec_security->settings->backends) {
150 backends = gensec_security->settings->backends;
151 } else {
152 backends = gensec_security_all();
154 if (!creds) {
155 if (!talloc_reference(mem_ctx, backends)) {
156 return NULL;
158 return backends;
160 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
164 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
165 uint8_t auth_type)
167 int i;
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;
174 backends = gensec_security_mechs(gensec_security, mem_ctx);
175 for (i=0; backends && backends[i]; i++) {
176 if (!gensec_security_ops_enabled(backends[i], gensec_security))
177 continue;
178 if (backends[i]->auth_type == auth_type) {
179 backend = backends[i];
180 talloc_free(mem_ctx);
181 return backend;
184 talloc_free(mem_ctx);
186 return NULL;
189 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
190 struct gensec_security *gensec_security,
191 const char *oid_string)
193 int i, j;
194 struct gensec_security_ops **backends;
195 const struct gensec_security_ops *backend;
196 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
197 if (!mem_ctx) {
198 return NULL;
200 backends = gensec_security_mechs(gensec_security, mem_ctx);
201 for (i=0; backends && backends[i]; i++) {
202 if (gensec_security != NULL &&
203 !gensec_security_ops_enabled(backends[i],
204 gensec_security))
205 continue;
206 if (backends[i]->oid) {
207 for (j=0; backends[i]->oid[j]; j++) {
208 if (backends[i]->oid[j] &&
209 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
210 backend = backends[i];
211 talloc_free(mem_ctx);
212 return backend;
217 talloc_free(mem_ctx);
219 return NULL;
222 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
223 struct gensec_security *gensec_security,
224 const char *sasl_name)
226 int i;
227 struct gensec_security_ops **backends;
228 const struct gensec_security_ops *backend;
229 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
230 if (!mem_ctx) {
231 return NULL;
233 backends = gensec_security_mechs(gensec_security, mem_ctx);
234 for (i=0; backends && backends[i]; i++) {
235 if (!gensec_security_ops_enabled(backends[i], gensec_security))
236 continue;
237 if (backends[i]->sasl_name
238 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
239 backend = backends[i];
240 talloc_free(mem_ctx);
241 return backend;
244 talloc_free(mem_ctx);
246 return NULL;
249 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
250 const char *name)
252 int i;
253 struct gensec_security_ops **backends;
254 const struct gensec_security_ops *backend;
255 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
256 if (!mem_ctx) {
257 return NULL;
259 backends = gensec_security_mechs(gensec_security, mem_ctx);
260 for (i=0; backends && backends[i]; i++) {
261 if (gensec_security != NULL &&
262 !gensec_security_ops_enabled(backends[i], gensec_security))
263 continue;
264 if (backends[i]->name
265 && (strcmp(backends[i]->name, name) == 0)) {
266 backend = backends[i];
267 talloc_free(mem_ctx);
268 return backend;
271 talloc_free(mem_ctx);
272 return NULL;
276 * Return a unique list of security subsystems from those specified in
277 * the list of SASL names.
279 * Use the list of enabled GENSEC mechanisms from the credentials
280 * attached to the gensec_security, and return in our preferred order.
283 static const struct gensec_security_ops **gensec_security_by_sasl_list(
284 struct gensec_security *gensec_security,
285 TALLOC_CTX *mem_ctx,
286 const char **sasl_names)
288 const struct gensec_security_ops **backends_out;
289 struct gensec_security_ops **backends;
290 int i, k, sasl_idx;
291 int num_backends_out = 0;
293 if (!sasl_names) {
294 return NULL;
297 backends = gensec_security_mechs(gensec_security, mem_ctx);
299 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
300 if (!backends_out) {
301 return NULL;
303 backends_out[0] = NULL;
305 /* Find backends in our preferred order, by walking our list,
306 * then looking in the supplied list */
307 for (i=0; backends && backends[i]; i++) {
308 if (gensec_security != NULL &&
309 !gensec_security_ops_enabled(backends[i], gensec_security))
310 continue;
311 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
312 if (!backends[i]->sasl_name ||
313 !(strcmp(backends[i]->sasl_name,
314 sasl_names[sasl_idx]) == 0)) {
315 continue;
318 for (k=0; backends_out[k]; k++) {
319 if (backends_out[k] == backends[i]) {
320 break;
324 if (k < num_backends_out) {
325 /* already in there */
326 continue;
329 backends_out = talloc_realloc(mem_ctx, backends_out,
330 const struct gensec_security_ops *,
331 num_backends_out + 2);
332 if (!backends_out) {
333 return NULL;
336 backends_out[num_backends_out] = backends[i];
337 num_backends_out++;
338 backends_out[num_backends_out] = NULL;
341 return backends_out;
345 * Return a unique list of security subsystems from those specified in
346 * the OID list. That is, where two OIDs refer to the same module,
347 * return that module only once.
349 * Use the list of enabled GENSEC mechanisms from the credentials
350 * attached to the gensec_security, and return in our preferred order.
353 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
354 struct gensec_security *gensec_security,
355 TALLOC_CTX *mem_ctx,
356 const char **oid_strings,
357 const char *skip)
359 struct gensec_security_ops_wrapper *backends_out;
360 struct gensec_security_ops **backends;
361 int i, j, k, oid_idx;
362 int num_backends_out = 0;
364 if (!oid_strings) {
365 return NULL;
368 backends = gensec_security_mechs(gensec_security, gensec_security);
370 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
371 if (!backends_out) {
372 return NULL;
374 backends_out[0].op = NULL;
375 backends_out[0].oid = NULL;
377 /* Find backends in our preferred order, by walking our list,
378 * then looking in the supplied list */
379 for (i=0; backends && backends[i]; i++) {
380 if (gensec_security != NULL &&
381 !gensec_security_ops_enabled(backends[i], gensec_security))
382 continue;
383 if (!backends[i]->oid) {
384 continue;
386 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
387 if (strcmp(oid_strings[oid_idx], skip) == 0) {
388 continue;
391 for (j=0; backends[i]->oid[j]; j++) {
392 if (!backends[i]->oid[j] ||
393 !(strcmp(backends[i]->oid[j],
394 oid_strings[oid_idx]) == 0)) {
395 continue;
398 for (k=0; backends_out[k].op; k++) {
399 if (backends_out[k].op == backends[i]) {
400 break;
404 if (k < num_backends_out) {
405 /* already in there */
406 continue;
409 backends_out = talloc_realloc(mem_ctx, backends_out,
410 struct gensec_security_ops_wrapper,
411 num_backends_out + 2);
412 if (!backends_out) {
413 return NULL;
416 backends_out[num_backends_out].op = backends[i];
417 backends_out[num_backends_out].oid = backends[i]->oid[j];
418 num_backends_out++;
419 backends_out[num_backends_out].op = NULL;
420 backends_out[num_backends_out].oid = NULL;
424 return backends_out;
428 * Return OIDS from the security subsystems listed
431 static const char **gensec_security_oids_from_ops(
432 struct gensec_security *gensec_security,
433 TALLOC_CTX *mem_ctx,
434 struct gensec_security_ops **ops,
435 const char *skip)
437 int i;
438 int j = 0;
439 int k;
440 const char **oid_list;
441 if (!ops) {
442 return NULL;
444 oid_list = talloc_array(mem_ctx, const char *, 1);
445 if (!oid_list) {
446 return NULL;
449 for (i=0; ops && ops[i]; i++) {
450 if (gensec_security != NULL &&
451 !gensec_security_ops_enabled(ops[i], gensec_security)) {
452 continue;
454 if (!ops[i]->oid) {
455 continue;
458 for (k = 0; ops[i]->oid[k]; k++) {
459 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
460 } else {
461 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
462 if (!oid_list) {
463 return NULL;
465 oid_list[j] = ops[i]->oid[k];
466 j++;
470 oid_list[j] = NULL;
471 return oid_list;
476 * Return OIDS from the security subsystems listed
479 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
480 const struct gensec_security_ops_wrapper *wops)
482 int i;
483 int j = 0;
484 int k;
485 const char **oid_list;
486 if (!wops) {
487 return NULL;
489 oid_list = talloc_array(mem_ctx, const char *, 1);
490 if (!oid_list) {
491 return NULL;
494 for (i=0; wops[i].op; i++) {
495 if (!wops[i].op->oid) {
496 continue;
499 for (k = 0; wops[i].op->oid[k]; k++) {
500 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
501 if (!oid_list) {
502 return NULL;
504 oid_list[j] = wops[i].op->oid[k];
505 j++;
508 oid_list[j] = NULL;
509 return oid_list;
514 * Return all the security subsystems currently enabled on a GENSEC context.
516 * This is taken from a list attached to the cli_credentials, and
517 * skips the OID in 'skip'. (Typically the SPNEGO OID)
521 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
522 TALLOC_CTX *mem_ctx,
523 const char *skip)
525 struct gensec_security_ops **ops
526 = gensec_security_mechs(gensec_security, mem_ctx);
527 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
531 Start the GENSEC system, returning a context pointer.
532 @param mem_ctx The parent TALLOC memory context.
533 @param gensec_security Returned GENSEC context pointer.
534 @note The mem_ctx is only a parent and may be NULL.
535 @note, the auth context is moved to be a referenced pointer of the
536 @ gensec_security return
538 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
539 struct gensec_settings *settings,
540 struct auth4_context *auth_context,
541 struct gensec_security **gensec_security)
543 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
544 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
546 (*gensec_security)->max_update_size = 0;
548 SMB_ASSERT(settings->lp_ctx != NULL);
549 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
551 /* We need to reference this, not steal, as the caller may be
552 * python, which won't like it if we steal it's object away
553 * from it */
554 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
556 return NT_STATUS_OK;
560 * Start a GENSEC subcontext, with a copy of the properties of the parent
561 * @param mem_ctx The parent TALLOC memory context.
562 * @param parent The parent GENSEC context
563 * @param gensec_security Returned GENSEC context pointer.
564 * @note Used by SPNEGO in particular, for the actual implementation mechanism
567 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
568 struct gensec_security *parent,
569 struct gensec_security **gensec_security)
571 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
572 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
574 (**gensec_security) = *parent;
575 (*gensec_security)->ops = NULL;
576 (*gensec_security)->private_data = NULL;
578 (*gensec_security)->subcontext = true;
579 (*gensec_security)->want_features = parent->want_features;
580 (*gensec_security)->max_update_size = parent->max_update_size;
581 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
582 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
583 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
584 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
586 return NT_STATUS_OK;
590 Start the GENSEC system, in client mode, returning a context pointer.
591 @param mem_ctx The parent TALLOC memory context.
592 @param gensec_security Returned GENSEC context pointer.
593 @note The mem_ctx is only a parent and may be NULL.
595 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
596 struct gensec_security **gensec_security,
597 struct gensec_settings *settings)
599 NTSTATUS status;
601 if (settings == NULL) {
602 DEBUG(0,("gensec_client_start: no settings given!\n"));
603 return NT_STATUS_INTERNAL_ERROR;
606 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
607 if (!NT_STATUS_IS_OK(status)) {
608 return status;
610 (*gensec_security)->gensec_role = GENSEC_CLIENT;
612 return status;
618 Start the GENSEC system, in server mode, returning a context pointer.
619 @param mem_ctx The parent TALLOC memory context.
620 @param gensec_security Returned GENSEC context pointer.
621 @note The mem_ctx is only a parent and may be NULL.
623 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
624 struct gensec_settings *settings,
625 struct auth4_context *auth_context,
626 struct gensec_security **gensec_security)
628 NTSTATUS status;
630 if (!settings) {
631 DEBUG(0,("gensec_server_start: no settings given!\n"));
632 return NT_STATUS_INTERNAL_ERROR;
635 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
636 if (!NT_STATUS_IS_OK(status)) {
637 return status;
639 (*gensec_security)->gensec_role = GENSEC_SERVER;
641 return status;
644 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
646 NTSTATUS status;
647 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
648 gensec_security->subcontext ? "sub" : "",
649 gensec_security->ops->name));
650 switch (gensec_security->gensec_role) {
651 case GENSEC_CLIENT:
652 if (gensec_security->ops->client_start) {
653 status = gensec_security->ops->client_start(gensec_security);
654 if (!NT_STATUS_IS_OK(status)) {
655 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
656 gensec_security->ops->name, nt_errstr(status)));
658 return status;
660 break;
661 case GENSEC_SERVER:
662 if (gensec_security->ops->server_start) {
663 status = gensec_security->ops->server_start(gensec_security);
664 if (!NT_STATUS_IS_OK(status)) {
665 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
666 gensec_security->ops->name, nt_errstr(status)));
668 return status;
670 break;
672 return NT_STATUS_INVALID_PARAMETER;
676 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
680 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
681 const struct gensec_security_ops *ops)
683 gensec_security->ops = ops;
684 return gensec_start_mech(gensec_security);
689 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
690 * @param gensec_security GENSEC context pointer.
691 * @param auth_type DCERPC auth type
692 * @param auth_level DCERPC auth level
695 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
696 uint8_t auth_type, uint8_t auth_level)
698 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
699 if (!gensec_security->ops) {
700 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
701 return NT_STATUS_INVALID_PARAMETER;
703 gensec_security->dcerpc_auth_level = auth_level;
704 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
705 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
706 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
707 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
708 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
709 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
710 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
711 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
712 /* Default features */
713 } else {
714 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
715 auth_level));
716 return NT_STATUS_INVALID_PARAMETER;
719 return gensec_start_mech(gensec_security);
722 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
724 const struct gensec_security_ops *ops;
725 ops = gensec_security_by_authtype(gensec_security, authtype);
726 if (ops) {
727 return ops->name;
729 return NULL;
733 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
734 const char *oid_string)
736 const struct gensec_security_ops *ops;
737 ops = gensec_security_by_oid(gensec_security, oid_string);
738 if (ops) {
739 return ops->name;
741 return oid_string;
745 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
747 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
748 * well-known #define to hook it in.
751 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
752 const char *mech_oid)
754 SMB_ASSERT(gensec_security != NULL);
756 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
757 if (!gensec_security->ops) {
758 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
759 return NT_STATUS_INVALID_PARAMETER;
761 return gensec_start_mech(gensec_security);
765 * Start a GENSEC sub-mechanism by a well know SASL name
769 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
770 const char *sasl_name)
772 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
773 if (!gensec_security->ops) {
774 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
775 return NT_STATUS_INVALID_PARAMETER;
777 return gensec_start_mech(gensec_security);
781 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
785 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
786 const char **sasl_names)
788 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
789 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
790 const struct gensec_security_ops **ops;
791 int i;
792 if (!mem_ctx) {
793 return NT_STATUS_NO_MEMORY;
795 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
796 if (!ops || !*ops) {
797 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
798 str_list_join(mem_ctx,
799 sasl_names, ' ')));
800 talloc_free(mem_ctx);
801 return NT_STATUS_INVALID_PARAMETER;
803 for (i=0; ops[i]; i++) {
804 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
805 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
806 break;
809 talloc_free(mem_ctx);
810 return nt_status;
814 * Start a GENSEC sub-mechanism by an internal name
818 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
819 const char *name)
821 gensec_security->ops = gensec_security_by_name(gensec_security, name);
822 if (!gensec_security->ops) {
823 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
824 return NT_STATUS_INVALID_PARAMETER;
826 return gensec_start_mech(gensec_security);
830 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
834 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
836 gensec_security->credentials = talloc_reference(gensec_security, credentials);
837 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
838 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
839 return NT_STATUS_OK;
843 register a GENSEC backend.
845 The 'name' can be later used by other backends to find the operations
846 structure for this backend.
848 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
850 if (gensec_security_by_name(NULL, ops->name) != NULL) {
851 /* its already registered! */
852 DEBUG(0,("GENSEC backend '%s' already registered\n",
853 ops->name));
854 return NT_STATUS_OBJECT_NAME_COLLISION;
857 generic_security_ops = talloc_realloc(talloc_autofree_context(),
858 generic_security_ops,
859 struct gensec_security_ops *,
860 gensec_num_backends+2);
861 if (!generic_security_ops) {
862 return NT_STATUS_NO_MEMORY;
865 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
866 gensec_num_backends++;
867 generic_security_ops[gensec_num_backends] = NULL;
869 DEBUG(3,("GENSEC backend '%s' registered\n",
870 ops->name));
872 return NT_STATUS_OK;
876 return the GENSEC interface version, and the size of some critical types
877 This can be used by backends to either detect compilation errors, or provide
878 multiple implementations for different smbd compilation options in one module
880 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
882 static const struct gensec_critical_sizes critical_sizes = {
883 GENSEC_INTERFACE_VERSION,
884 sizeof(struct gensec_security_ops),
885 sizeof(struct gensec_security),
888 return &critical_sizes;
891 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
892 return (*gs2)->priority - (*gs1)->priority;
895 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
897 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
900 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
902 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
906 initialise the GENSEC subsystem
908 _PUBLIC_ NTSTATUS gensec_init(void)
910 static bool initialized = false;
911 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
912 #ifdef STATIC_gensec_MODULES
913 STATIC_gensec_MODULES_PROTO;
914 init_module_fn static_init[] = { STATIC_gensec_MODULES };
915 #else
916 init_module_fn *static_init = NULL;
917 #endif
918 init_module_fn *shared_init;
920 if (initialized) return NT_STATUS_OK;
921 initialized = true;
923 shared_init = load_samba_modules(NULL, "gensec");
925 run_init_functions(static_init);
926 run_init_functions(shared_init);
928 talloc_free(shared_init);
930 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
932 return NT_STATUS_OK;