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/>.
24 #include "system/network.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"
35 /* the list of currently registered GENSEC backends */
36 static const struct gensec_security_ops **generic_security_ops;
37 static int gensec_num_backends;
39 /* Return all the registered mechs. Don't modify the return pointer,
40 * but you may talloc_referen it if convient */
41 _PUBLIC_ const struct gensec_security_ops * const *gensec_security_all(void)
43 return generic_security_ops;
46 bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security)
48 return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled);
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)
56 * The intended logic is:
58 * if we are in the default AUTO have kerberos:
59 * - take a reference to the master list
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
67 * Once we get things like NegoEx or moonshot, this will of course get
71 _PUBLIC_ const struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
72 const struct gensec_security_ops * const *old_gensec_list,
73 struct cli_credentials *creds)
75 const 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;
80 use_kerberos = cli_credentials_get_kerberos_state(creds);
83 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
87 new_gensec_list = talloc_array(mem_ctx,
88 const struct gensec_security_ops *,
90 if (!new_gensec_list) {
95 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
99 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
100 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
106 switch (use_kerberos) {
107 case CRED_AUTO_USE_KERBEROS:
111 case CRED_DONT_USE_KERBEROS:
112 if (old_gensec_list[i]->kerberos == false) {
118 case CRED_MUST_USE_KERBEROS:
119 if (old_gensec_list[i]->kerberos == true) {
125 /* Can't happen or invalid parameter */
133 new_gensec_list[j] = old_gensec_list[i];
136 new_gensec_list[j] = NULL;
138 return new_gensec_list;
141 _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs(
142 struct gensec_security *gensec_security,
145 struct cli_credentials *creds = NULL;
146 const struct gensec_security_ops * const *backends = gensec_security_all();
148 if (gensec_security != NULL) {
149 creds = gensec_get_credentials(gensec_security);
151 if (gensec_security->settings->backends) {
152 backends = gensec_security->settings->backends;
156 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
160 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
164 const struct gensec_security_ops **backends;
165 const struct gensec_security_ops *backend;
166 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
170 backends = gensec_security_mechs(gensec_security, mem_ctx);
171 for (i=0; backends && backends[i]; i++) {
172 if (!gensec_security_ops_enabled(backends[i], gensec_security))
174 if (backends[i]->auth_type == auth_type) {
175 backend = backends[i];
176 talloc_free(mem_ctx);
180 talloc_free(mem_ctx);
185 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
186 struct gensec_security *gensec_security,
187 const char *oid_string)
190 const struct gensec_security_ops **backends;
191 const struct gensec_security_ops *backend;
192 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
196 backends = gensec_security_mechs(gensec_security, mem_ctx);
197 for (i=0; backends && backends[i]; i++) {
198 if (gensec_security != NULL &&
199 !gensec_security_ops_enabled(backends[i],
202 if (backends[i]->oid) {
203 for (j=0; backends[i]->oid[j]; j++) {
204 if (backends[i]->oid[j] &&
205 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
206 backend = backends[i];
207 talloc_free(mem_ctx);
213 talloc_free(mem_ctx);
218 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
219 struct gensec_security *gensec_security,
220 const char *sasl_name)
223 const struct gensec_security_ops **backends;
224 const struct gensec_security_ops *backend;
225 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
229 backends = gensec_security_mechs(gensec_security, mem_ctx);
230 for (i=0; backends && backends[i]; i++) {
231 if (!gensec_security_ops_enabled(backends[i], gensec_security))
233 if (backends[i]->sasl_name
234 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
235 backend = backends[i];
236 talloc_free(mem_ctx);
240 talloc_free(mem_ctx);
245 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
246 struct gensec_security *gensec_security,
250 const struct gensec_security_ops **backends;
251 const struct gensec_security_ops *backend;
252 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
256 backends = gensec_security_mechs(gensec_security, mem_ctx);
257 for (i=0; backends && backends[i]; i++) {
258 if (!gensec_security_ops_enabled(backends[i], gensec_security))
260 if (backends[i]->auth_type == auth_type) {
261 backend = backends[i];
262 talloc_free(mem_ctx);
266 talloc_free(mem_ctx);
271 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
275 const struct gensec_security_ops **backends;
276 const struct gensec_security_ops *backend;
277 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
281 backends = gensec_security_mechs(gensec_security, mem_ctx);
282 for (i=0; backends && backends[i]; i++) {
283 if (gensec_security != NULL &&
284 !gensec_security_ops_enabled(backends[i], gensec_security))
286 if (backends[i]->name
287 && (strcmp(backends[i]->name, name) == 0)) {
288 backend = backends[i];
289 talloc_free(mem_ctx);
293 talloc_free(mem_ctx);
298 * Return a unique list of security subsystems from those specified in
299 * the list of SASL names.
301 * Use the list of enabled GENSEC mechanisms from the credentials
302 * attached to the gensec_security, and return in our preferred order.
305 static const struct gensec_security_ops **gensec_security_by_sasl_list(
306 struct gensec_security *gensec_security,
308 const char **sasl_names)
310 const struct gensec_security_ops **backends_out;
311 const struct gensec_security_ops **backends;
313 int num_backends_out = 0;
319 backends = gensec_security_mechs(gensec_security, mem_ctx);
321 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
325 backends_out[0] = NULL;
327 /* Find backends in our preferred order, by walking our list,
328 * then looking in the supplied list */
329 for (i=0; backends && backends[i]; i++) {
330 if (gensec_security != NULL &&
331 !gensec_security_ops_enabled(backends[i], gensec_security))
333 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
334 if (!backends[i]->sasl_name ||
335 !(strcmp(backends[i]->sasl_name,
336 sasl_names[sasl_idx]) == 0)) {
340 for (k=0; backends_out[k]; k++) {
341 if (backends_out[k] == backends[i]) {
346 if (k < num_backends_out) {
347 /* already in there */
351 backends_out = talloc_realloc(mem_ctx, backends_out,
352 const struct gensec_security_ops *,
353 num_backends_out + 2);
358 backends_out[num_backends_out] = backends[i];
360 backends_out[num_backends_out] = NULL;
367 * Return a unique list of security subsystems from those specified in
368 * the OID list. That is, where two OIDs refer to the same module,
369 * return that module only once.
371 * Use the list of enabled GENSEC mechanisms from the credentials
372 * attached to the gensec_security, and return in our preferred order.
375 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
376 struct gensec_security *gensec_security,
378 const char * const *oid_strings,
381 struct gensec_security_ops_wrapper *backends_out;
382 const struct gensec_security_ops **backends;
383 int i, j, k, oid_idx;
384 int num_backends_out = 0;
390 backends = gensec_security_mechs(gensec_security, gensec_security);
392 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
396 backends_out[0].op = NULL;
397 backends_out[0].oid = NULL;
399 /* Find backends in our preferred order, by walking our list,
400 * then looking in the supplied list */
401 for (i=0; backends && backends[i]; i++) {
402 if (gensec_security != NULL &&
403 !gensec_security_ops_enabled(backends[i], gensec_security))
405 if (!backends[i]->oid) {
408 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
409 if (strcmp(oid_strings[oid_idx], skip) == 0) {
413 for (j=0; backends[i]->oid[j]; j++) {
414 if (!backends[i]->oid[j] ||
415 !(strcmp(backends[i]->oid[j],
416 oid_strings[oid_idx]) == 0)) {
420 for (k=0; backends_out[k].op; k++) {
421 if (backends_out[k].op == backends[i]) {
426 if (k < num_backends_out) {
427 /* already in there */
431 backends_out = talloc_realloc(mem_ctx, backends_out,
432 struct gensec_security_ops_wrapper,
433 num_backends_out + 2);
438 backends_out[num_backends_out].op = backends[i];
439 backends_out[num_backends_out].oid = backends[i]->oid[j];
441 backends_out[num_backends_out].op = NULL;
442 backends_out[num_backends_out].oid = NULL;
450 * Return OIDS from the security subsystems listed
453 static const char **gensec_security_oids_from_ops(
454 struct gensec_security *gensec_security,
456 const struct gensec_security_ops * const *ops,
462 const char **oid_list;
466 oid_list = talloc_array(mem_ctx, const char *, 1);
471 for (i=0; ops && ops[i]; i++) {
472 if (gensec_security != NULL &&
473 !gensec_security_ops_enabled(ops[i], gensec_security)) {
480 for (k = 0; ops[i]->oid[k]; k++) {
481 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
483 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
487 oid_list[j] = ops[i]->oid[k];
498 * Return OIDS from the security subsystems listed
501 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
502 const struct gensec_security_ops_wrapper *wops)
507 const char **oid_list;
511 oid_list = talloc_array(mem_ctx, const char *, 1);
516 for (i=0; wops[i].op; i++) {
517 if (!wops[i].op->oid) {
521 for (k = 0; wops[i].op->oid[k]; k++) {
522 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
526 oid_list[j] = wops[i].op->oid[k];
536 * Return all the security subsystems currently enabled on a GENSEC context.
538 * This is taken from a list attached to the cli_credentials, and
539 * skips the OID in 'skip'. (Typically the SPNEGO OID)
543 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
547 const struct gensec_security_ops **ops;
549 ops = gensec_security_mechs(gensec_security, mem_ctx);
551 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
555 Start the GENSEC system, returning a context pointer.
556 @param mem_ctx The parent TALLOC memory context.
557 @param gensec_security Returned GENSEC context pointer.
558 @note The mem_ctx is only a parent and may be NULL.
559 @note, the auth context is moved to be a referenced pointer of the
560 @ gensec_security return
562 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
563 struct gensec_settings *settings,
564 struct auth4_context *auth_context,
565 struct gensec_security **gensec_security)
567 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
568 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
570 (*gensec_security)->max_update_size = 0;
572 SMB_ASSERT(settings->lp_ctx != NULL);
573 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
575 /* We need to reference this, not steal, as the caller may be
576 * python, which won't like it if we steal it's object away
578 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
584 * Start a GENSEC subcontext, with a copy of the properties of the parent
585 * @param mem_ctx The parent TALLOC memory context.
586 * @param parent The parent GENSEC context
587 * @param gensec_security Returned GENSEC context pointer.
588 * @note Used by SPNEGO in particular, for the actual implementation mechanism
591 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
592 struct gensec_security *parent,
593 struct gensec_security **gensec_security)
595 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
596 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
598 (**gensec_security) = *parent;
599 (*gensec_security)->ops = NULL;
600 (*gensec_security)->private_data = NULL;
602 (*gensec_security)->subcontext = true;
603 (*gensec_security)->want_features = parent->want_features;
604 (*gensec_security)->max_update_size = parent->max_update_size;
605 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
606 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
607 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
608 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
614 Start the GENSEC system, in client mode, returning a context pointer.
615 @param mem_ctx The parent TALLOC memory context.
616 @param gensec_security Returned GENSEC context pointer.
617 @note The mem_ctx is only a parent and may be NULL.
619 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
620 struct gensec_security **gensec_security,
621 struct gensec_settings *settings)
625 if (settings == NULL) {
626 DEBUG(0,("gensec_client_start: no settings given!\n"));
627 return NT_STATUS_INTERNAL_ERROR;
630 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
631 if (!NT_STATUS_IS_OK(status)) {
634 (*gensec_security)->gensec_role = GENSEC_CLIENT;
642 Start the GENSEC system, in server mode, returning a context pointer.
643 @param mem_ctx The parent TALLOC memory context.
644 @param gensec_security Returned GENSEC context pointer.
645 @note The mem_ctx is only a parent and may be NULL.
647 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
648 struct gensec_settings *settings,
649 struct auth4_context *auth_context,
650 struct gensec_security **gensec_security)
655 DEBUG(0,("gensec_server_start: no settings given!\n"));
656 return NT_STATUS_INTERNAL_ERROR;
659 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
660 if (!NT_STATUS_IS_OK(status)) {
663 (*gensec_security)->gensec_role = GENSEC_SERVER;
668 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
671 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
672 gensec_security->subcontext ? "sub" : "",
673 gensec_security->ops->name));
674 switch (gensec_security->gensec_role) {
676 if (gensec_security->ops->client_start) {
677 status = gensec_security->ops->client_start(gensec_security);
678 if (!NT_STATUS_IS_OK(status)) {
679 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
680 gensec_security->ops->name, nt_errstr(status)));
686 if (gensec_security->ops->server_start) {
687 status = gensec_security->ops->server_start(gensec_security);
688 if (!NT_STATUS_IS_OK(status)) {
689 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
690 gensec_security->ops->name, nt_errstr(status)));
696 return NT_STATUS_INVALID_PARAMETER;
700 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
704 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
705 const struct gensec_security_ops *ops)
707 gensec_security->ops = ops;
708 return gensec_start_mech(gensec_security);
713 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
714 * @param gensec_security GENSEC context pointer.
715 * @param auth_type DCERPC auth type
716 * @param auth_level DCERPC auth level
719 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
720 uint8_t auth_type, uint8_t auth_level)
722 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
723 if (!gensec_security->ops) {
724 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
725 return NT_STATUS_INVALID_PARAMETER;
727 gensec_security->dcerpc_auth_level = auth_level;
728 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
729 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
730 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
731 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
732 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
733 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
734 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
735 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
736 /* Default features */
738 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
740 return NT_STATUS_INVALID_PARAMETER;
743 return gensec_start_mech(gensec_security);
746 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
748 const struct gensec_security_ops *ops;
749 ops = gensec_security_by_authtype(gensec_security, authtype);
757 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
758 const char *oid_string)
760 const struct gensec_security_ops *ops;
761 ops = gensec_security_by_oid(gensec_security, oid_string);
769 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
771 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
772 * well-known #define to hook it in.
775 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
776 const char *mech_oid)
778 SMB_ASSERT(gensec_security != NULL);
780 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
781 if (!gensec_security->ops) {
782 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
783 return NT_STATUS_INVALID_PARAMETER;
785 return gensec_start_mech(gensec_security);
789 * Start a GENSEC sub-mechanism by a well know SASL name
793 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
794 const char *sasl_name)
796 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
797 if (!gensec_security->ops) {
798 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
799 return NT_STATUS_INVALID_PARAMETER;
801 return gensec_start_mech(gensec_security);
805 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
809 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
810 const char **sasl_names)
812 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
813 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
814 const struct gensec_security_ops **ops;
817 return NT_STATUS_NO_MEMORY;
819 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
821 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
822 str_list_join(mem_ctx,
824 talloc_free(mem_ctx);
825 return NT_STATUS_INVALID_PARAMETER;
827 for (i=0; ops[i]; i++) {
828 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
829 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
833 talloc_free(mem_ctx);
838 * Start a GENSEC sub-mechanism by an internal name
842 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
845 gensec_security->ops = gensec_security_by_name(gensec_security, name);
846 if (!gensec_security->ops) {
847 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
848 return NT_STATUS_INVALID_PARAMETER;
850 return gensec_start_mech(gensec_security);
854 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
858 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
860 gensec_security->credentials = talloc_reference(gensec_security, credentials);
861 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
862 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
867 register a GENSEC backend.
869 The 'name' can be later used by other backends to find the operations
870 structure for this backend.
872 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
874 if (gensec_security_by_name(NULL, ops->name) != NULL) {
875 /* its already registered! */
876 DEBUG(0,("GENSEC backend '%s' already registered\n",
878 return NT_STATUS_OBJECT_NAME_COLLISION;
881 generic_security_ops = talloc_realloc(talloc_autofree_context(),
882 generic_security_ops,
883 const struct gensec_security_ops *,
884 gensec_num_backends+2);
885 if (!generic_security_ops) {
886 return NT_STATUS_NO_MEMORY;
889 generic_security_ops[gensec_num_backends] = ops;
890 gensec_num_backends++;
891 generic_security_ops[gensec_num_backends] = NULL;
893 DEBUG(3,("GENSEC backend '%s' registered\n",
900 return the GENSEC interface version, and the size of some critical types
901 This can be used by backends to either detect compilation errors, or provide
902 multiple implementations for different smbd compilation options in one module
904 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
906 static const struct gensec_critical_sizes critical_sizes = {
907 GENSEC_INTERFACE_VERSION,
908 sizeof(struct gensec_security_ops),
909 sizeof(struct gensec_security),
912 return &critical_sizes;
915 static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
916 return (*gs2)->priority - (*gs1)->priority;
919 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
921 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
924 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
926 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
930 initialise the GENSEC subsystem
932 _PUBLIC_ NTSTATUS gensec_init(void)
934 static bool initialized = false;
935 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
936 #ifdef STATIC_gensec_MODULES
937 STATIC_gensec_MODULES_PROTO;
938 init_module_fn static_init[] = { STATIC_gensec_MODULES };
940 init_module_fn *static_init = NULL;
942 init_module_fn *shared_init;
944 if (initialized) return NT_STATUS_OK;
947 shared_init = load_samba_modules(NULL, "gensec");
949 run_init_functions(static_init);
950 run_init_functions(shared_init);
952 talloc_free(shared_init);
954 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);