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 "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 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
56 struct gensec_security_ops **old_gensec_list,
57 struct cli_credentials *creds)
59 struct gensec_security_ops **new_gensec_list;
60 int i, j, num_mechs_in;
61 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
64 use_kerberos = cli_credentials_get_kerberos_state(creds);
67 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
68 if (!talloc_reference(mem_ctx, old_gensec_list)) {
71 return old_gensec_list;
74 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
78 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
79 if (!new_gensec_list) {
84 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
87 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
88 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
89 new_gensec_list[j] = old_gensec_list[i];
94 switch (use_kerberos) {
95 case CRED_DONT_USE_KERBEROS:
96 if (old_gensec_list[i]->kerberos == false) {
97 new_gensec_list[j] = old_gensec_list[i];
101 case CRED_MUST_USE_KERBEROS:
102 if (old_gensec_list[i]->kerberos == true) {
103 new_gensec_list[j] = old_gensec_list[i];
108 /* Can't happen or invalid parameter */
112 new_gensec_list[j] = NULL;
114 return new_gensec_list;
117 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
120 struct gensec_security_ops **backends;
121 backends = gensec_security_all();
122 if (!gensec_security) {
123 if (!talloc_reference(mem_ctx, backends)) {
128 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
130 if (!talloc_reference(mem_ctx, backends)) {
135 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
139 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
143 struct gensec_security_ops **backends;
144 const struct gensec_security_ops *backend;
145 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
149 backends = gensec_security_mechs(gensec_security, mem_ctx);
150 for (i=0; backends && backends[i]; i++) {
151 if (!gensec_security_ops_enabled(backends[i], gensec_security))
153 if (backends[i]->auth_type == auth_type) {
154 backend = backends[i];
155 talloc_free(mem_ctx);
159 talloc_free(mem_ctx);
164 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
165 const char *oid_string)
168 struct gensec_security_ops **backends;
169 const struct gensec_security_ops *backend;
170 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
174 backends = gensec_security_mechs(gensec_security, mem_ctx);
175 for (i=0; backends && backends[i]; i++) {
176 if (gensec_security != NULL &&
177 !gensec_security_ops_enabled(backends[i],
180 if (backends[i]->oid) {
181 for (j=0; backends[i]->oid[j]; j++) {
182 if (backends[i]->oid[j] &&
183 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
184 backend = backends[i];
185 talloc_free(mem_ctx);
191 talloc_free(mem_ctx);
196 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
197 const char *sasl_name)
200 struct gensec_security_ops **backends;
201 const struct gensec_security_ops *backend;
202 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
206 backends = gensec_security_mechs(gensec_security, mem_ctx);
207 for (i=0; backends && backends[i]; i++) {
208 if (!gensec_security_ops_enabled(backends[i], gensec_security))
210 if (backends[i]->sasl_name
211 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
212 backend = backends[i];
213 talloc_free(mem_ctx);
217 talloc_free(mem_ctx);
222 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
226 struct gensec_security_ops **backends;
227 const struct gensec_security_ops *backend;
228 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
232 backends = gensec_security_mechs(gensec_security, mem_ctx);
233 for (i=0; backends && backends[i]; i++) {
234 if (gensec_security != NULL &&
235 !gensec_security_ops_enabled(backends[i], gensec_security))
237 if (backends[i]->name
238 && (strcmp(backends[i]->name, name) == 0)) {
239 backend = backends[i];
240 talloc_free(mem_ctx);
244 talloc_free(mem_ctx);
249 * Return a unique list of security subsystems from those specified in
250 * the list of SASL names.
252 * Use the list of enabled GENSEC mechanisms from the credentials
253 * attached to the gensec_security, and return in our preferred order.
256 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
258 const char **sasl_names)
260 const struct gensec_security_ops **backends_out;
261 struct gensec_security_ops **backends;
263 int num_backends_out = 0;
269 backends = gensec_security_mechs(gensec_security, mem_ctx);
271 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
275 backends_out[0] = NULL;
277 /* Find backends in our preferred order, by walking our list,
278 * then looking in the supplied list */
279 for (i=0; backends && backends[i]; i++) {
280 if (gensec_security != NULL &&
281 !gensec_security_ops_enabled(backends[i], gensec_security))
283 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
284 if (!backends[i]->sasl_name ||
285 !(strcmp(backends[i]->sasl_name,
286 sasl_names[sasl_idx]) == 0)) {
290 for (k=0; backends_out[k]; k++) {
291 if (backends_out[k] == backends[i]) {
296 if (k < num_backends_out) {
297 /* already in there */
301 backends_out = talloc_realloc(mem_ctx, backends_out,
302 const struct gensec_security_ops *,
303 num_backends_out + 2);
308 backends_out[num_backends_out] = backends[i];
310 backends_out[num_backends_out] = NULL;
317 * Return a unique list of security subsystems from those specified in
318 * the OID list. That is, where two OIDs refer to the same module,
319 * return that module only once.
321 * Use the list of enabled GENSEC mechanisms from the credentials
322 * attached to the gensec_security, and return in our preferred order.
325 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
327 const char **oid_strings,
330 struct gensec_security_ops_wrapper *backends_out;
331 struct gensec_security_ops **backends;
332 int i, j, k, oid_idx;
333 int num_backends_out = 0;
339 backends = gensec_security_mechs(gensec_security, gensec_security);
341 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
345 backends_out[0].op = NULL;
346 backends_out[0].oid = NULL;
348 /* Find backends in our preferred order, by walking our list,
349 * then looking in the supplied list */
350 for (i=0; backends && backends[i]; i++) {
351 if (gensec_security != NULL &&
352 !gensec_security_ops_enabled(backends[i], gensec_security))
354 if (!backends[i]->oid) {
357 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
358 if (strcmp(oid_strings[oid_idx], skip) == 0) {
362 for (j=0; backends[i]->oid[j]; j++) {
363 if (!backends[i]->oid[j] ||
364 !(strcmp(backends[i]->oid[j],
365 oid_strings[oid_idx]) == 0)) {
369 for (k=0; backends_out[k].op; k++) {
370 if (backends_out[k].op == backends[i]) {
375 if (k < num_backends_out) {
376 /* already in there */
380 backends_out = talloc_realloc(mem_ctx, backends_out,
381 struct gensec_security_ops_wrapper,
382 num_backends_out + 2);
387 backends_out[num_backends_out].op = backends[i];
388 backends_out[num_backends_out].oid = backends[i]->oid[j];
390 backends_out[num_backends_out].op = NULL;
391 backends_out[num_backends_out].oid = NULL;
399 * Return OIDS from the security subsystems listed
402 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
404 struct gensec_security_ops **ops,
410 const char **oid_list;
414 oid_list = talloc_array(mem_ctx, const char *, 1);
419 for (i=0; ops && ops[i]; i++) {
420 if (gensec_security != NULL &&
421 !gensec_security_ops_enabled(ops[i], gensec_security)) {
428 for (k = 0; ops[i]->oid[k]; k++) {
429 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
431 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
435 oid_list[j] = ops[i]->oid[k];
446 * Return OIDS from the security subsystems listed
449 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
450 const struct gensec_security_ops_wrapper *wops)
455 const char **oid_list;
459 oid_list = talloc_array(mem_ctx, const char *, 1);
464 for (i=0; wops[i].op; i++) {
465 if (!wops[i].op->oid) {
469 for (k = 0; wops[i].op->oid[k]; k++) {
470 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
474 oid_list[j] = wops[i].op->oid[k];
484 * Return all the security subsystems currently enabled on a GENSEC context.
486 * This is taken from a list attached to the cli_credentials, and
487 * skips the OID in 'skip'. (Typically the SPNEGO OID)
491 const char **gensec_security_oids(struct gensec_security *gensec_security,
495 struct gensec_security_ops **ops
496 = gensec_security_mechs(gensec_security, mem_ctx);
497 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
501 Start the GENSEC system, returning a context pointer.
502 @param mem_ctx The parent TALLOC memory context.
503 @param gensec_security Returned GENSEC context pointer.
504 @note The mem_ctx is only a parent and may be NULL.
505 @note, the auth context is moved to be a referenced pointer of the
506 @ gensec_security return
508 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
509 struct tevent_context *ev,
510 struct gensec_settings *settings,
511 struct auth4_context *auth_context,
512 struct gensec_security **gensec_security)
514 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
515 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
517 (*gensec_security)->event_ctx = ev;
518 SMB_ASSERT(settings->lp_ctx != NULL);
519 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
521 /* We need to reference this, not steal, as the caller may be
522 * python, which won't like it if we steal it's object away
524 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
530 * Start a GENSEC subcontext, with a copy of the properties of the parent
531 * @param mem_ctx The parent TALLOC memory context.
532 * @param parent The parent GENSEC context
533 * @param gensec_security Returned GENSEC context pointer.
534 * @note Used by SPNEGO in particular, for the actual implementation mechanism
537 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
538 struct gensec_security *parent,
539 struct gensec_security **gensec_security)
541 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
542 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
544 (**gensec_security) = *parent;
545 (*gensec_security)->ops = NULL;
546 (*gensec_security)->private_data = NULL;
548 (*gensec_security)->subcontext = true;
549 (*gensec_security)->want_features = parent->want_features;
550 (*gensec_security)->event_ctx = parent->event_ctx;
551 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
552 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
553 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
559 Start the GENSEC system, in client mode, returning a context pointer.
560 @param mem_ctx The parent TALLOC memory context.
561 @param gensec_security Returned GENSEC context pointer.
562 @note The mem_ctx is only a parent and may be NULL.
564 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
565 struct gensec_security **gensec_security,
566 struct tevent_context *ev,
567 struct gensec_settings *settings)
571 if (settings == NULL) {
572 DEBUG(0,("gensec_client_start: no settings given!\n"));
573 return NT_STATUS_INTERNAL_ERROR;
576 status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
577 if (!NT_STATUS_IS_OK(status)) {
580 (*gensec_security)->gensec_role = GENSEC_CLIENT;
588 Start the GENSEC system, in server mode, returning a context pointer.
589 @param mem_ctx The parent TALLOC memory context.
590 @param gensec_security Returned GENSEC context pointer.
591 @note The mem_ctx is only a parent and may be NULL.
593 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
594 struct tevent_context *ev,
595 struct gensec_settings *settings,
596 struct auth4_context *auth_context,
597 struct gensec_security **gensec_security)
602 DEBUG(0,("gensec_server_start: no settings given!\n"));
603 return NT_STATUS_INTERNAL_ERROR;
606 status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
607 if (!NT_STATUS_IS_OK(status)) {
610 (*gensec_security)->gensec_role = GENSEC_SERVER;
615 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
618 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
619 gensec_security->subcontext ? "sub" : "",
620 gensec_security->ops->name));
621 switch (gensec_security->gensec_role) {
623 if (gensec_security->ops->client_start) {
624 status = gensec_security->ops->client_start(gensec_security);
625 if (!NT_STATUS_IS_OK(status)) {
626 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
627 gensec_security->ops->name, nt_errstr(status)));
633 if (gensec_security->ops->server_start) {
634 status = gensec_security->ops->server_start(gensec_security);
635 if (!NT_STATUS_IS_OK(status)) {
636 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
637 gensec_security->ops->name, nt_errstr(status)));
643 return NT_STATUS_INVALID_PARAMETER;
647 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
651 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
652 const struct gensec_security_ops *ops)
654 gensec_security->ops = ops;
655 return gensec_start_mech(gensec_security);
660 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
661 * @param gensec_security GENSEC context pointer.
662 * @param auth_type DCERPC auth type
663 * @param auth_level DCERPC auth level
666 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
667 uint8_t auth_type, uint8_t auth_level)
669 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
670 if (!gensec_security->ops) {
671 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
672 return NT_STATUS_INVALID_PARAMETER;
674 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
675 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
676 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
677 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
678 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
679 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
680 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
681 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
682 /* Default features */
684 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
686 return NT_STATUS_INVALID_PARAMETER;
689 return gensec_start_mech(gensec_security);
692 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
694 const struct gensec_security_ops *ops;
695 ops = gensec_security_by_authtype(gensec_security, authtype);
703 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
704 const char *oid_string)
706 const struct gensec_security_ops *ops;
707 ops = gensec_security_by_oid(gensec_security, oid_string);
715 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
717 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
718 * well-known #define to hook it in.
721 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
722 const char *mech_oid)
724 SMB_ASSERT(gensec_security != NULL);
726 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
727 if (!gensec_security->ops) {
728 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
729 return NT_STATUS_INVALID_PARAMETER;
731 return gensec_start_mech(gensec_security);
735 * Start a GENSEC sub-mechanism by a well know SASL name
739 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
740 const char *sasl_name)
742 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
743 if (!gensec_security->ops) {
744 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
745 return NT_STATUS_INVALID_PARAMETER;
747 return gensec_start_mech(gensec_security);
751 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
755 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
756 const char **sasl_names)
758 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
759 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
760 const struct gensec_security_ops **ops;
763 return NT_STATUS_NO_MEMORY;
765 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
767 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
768 str_list_join(mem_ctx,
770 talloc_free(mem_ctx);
771 return NT_STATUS_INVALID_PARAMETER;
773 for (i=0; ops[i]; i++) {
774 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
775 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
779 talloc_free(mem_ctx);
784 * Start a GENSEC sub-mechanism by an internal name
788 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
791 gensec_security->ops = gensec_security_by_name(gensec_security, name);
792 if (!gensec_security->ops) {
793 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
794 return NT_STATUS_INVALID_PARAMETER;
796 return gensec_start_mech(gensec_security);
800 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
804 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
806 gensec_security->credentials = talloc_reference(gensec_security, credentials);
807 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
808 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
813 register a GENSEC backend.
815 The 'name' can be later used by other backends to find the operations
816 structure for this backend.
818 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
820 if (gensec_security_by_name(NULL, ops->name) != NULL) {
821 /* its already registered! */
822 DEBUG(0,("GENSEC backend '%s' already registered\n",
824 return NT_STATUS_OBJECT_NAME_COLLISION;
827 generic_security_ops = talloc_realloc(talloc_autofree_context(),
828 generic_security_ops,
829 struct gensec_security_ops *,
830 gensec_num_backends+2);
831 if (!generic_security_ops) {
832 return NT_STATUS_NO_MEMORY;
835 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
836 gensec_num_backends++;
837 generic_security_ops[gensec_num_backends] = NULL;
839 DEBUG(3,("GENSEC backend '%s' registered\n",
846 return the GENSEC interface version, and the size of some critical types
847 This can be used by backends to either detect compilation errors, or provide
848 multiple implementations for different smbd compilation options in one module
850 const struct gensec_critical_sizes *gensec_interface_version(void)
852 static const struct gensec_critical_sizes critical_sizes = {
853 GENSEC_INTERFACE_VERSION,
854 sizeof(struct gensec_security_ops),
855 sizeof(struct gensec_security),
858 return &critical_sizes;
861 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
862 return (*gs2)->priority - (*gs1)->priority;
865 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
867 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
870 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
872 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
876 initialise the GENSEC subsystem
878 _PUBLIC_ NTSTATUS gensec_init(void)
880 static bool initialized = false;
881 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
882 #if _SAMBA_BUILD_ == 4
883 STATIC_gensec_MODULES_PROTO;
884 init_module_fn static_init[] = { STATIC_gensec_MODULES };
886 init_module_fn *static_init = NULL;
888 init_module_fn *shared_init;
890 if (initialized) return NT_STATUS_OK;
893 shared_init = load_samba_modules(NULL, "gensec");
895 run_init_functions(static_init);
896 run_init_functions(shared_init);
898 talloc_free(shared_init);
900 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);