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++) {
86 bool found_spnego = false;
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];
98 switch (use_kerberos) {
99 case CRED_DONT_USE_KERBEROS:
100 if (old_gensec_list[i]->kerberos == false) {
101 new_gensec_list[j] = old_gensec_list[i];
105 case CRED_MUST_USE_KERBEROS:
106 if (old_gensec_list[i]->kerberos == true) {
107 new_gensec_list[j] = old_gensec_list[i];
112 /* Can't happen or invalid parameter */
116 new_gensec_list[j] = NULL;
118 return new_gensec_list;
121 _PUBLIC_ struct gensec_security_ops **gensec_security_mechs(
122 struct gensec_security *gensec_security,
125 struct gensec_security_ops **backends;
126 if (!gensec_security) {
127 backends = gensec_security_all();
128 if (!talloc_reference(mem_ctx, backends)) {
133 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
134 if (gensec_security->settings->backends) {
135 backends = gensec_security->settings->backends;
137 backends = gensec_security_all();
140 if (!talloc_reference(mem_ctx, backends)) {
145 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
149 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
153 struct gensec_security_ops **backends;
154 const struct gensec_security_ops *backend;
155 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
159 backends = gensec_security_mechs(gensec_security, mem_ctx);
160 for (i=0; backends && backends[i]; i++) {
161 if (!gensec_security_ops_enabled(backends[i], gensec_security))
163 if (backends[i]->auth_type == auth_type) {
164 backend = backends[i];
165 talloc_free(mem_ctx);
169 talloc_free(mem_ctx);
174 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
175 struct gensec_security *gensec_security,
176 const char *oid_string)
179 struct gensec_security_ops **backends;
180 const struct gensec_security_ops *backend;
181 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
185 backends = gensec_security_mechs(gensec_security, mem_ctx);
186 for (i=0; backends && backends[i]; i++) {
187 if (gensec_security != NULL &&
188 !gensec_security_ops_enabled(backends[i],
191 if (backends[i]->oid) {
192 for (j=0; backends[i]->oid[j]; j++) {
193 if (backends[i]->oid[j] &&
194 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
195 backend = backends[i];
196 talloc_free(mem_ctx);
202 talloc_free(mem_ctx);
207 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
208 struct gensec_security *gensec_security,
209 const char *sasl_name)
212 struct gensec_security_ops **backends;
213 const struct gensec_security_ops *backend;
214 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
218 backends = gensec_security_mechs(gensec_security, mem_ctx);
219 for (i=0; backends && backends[i]; i++) {
220 if (!gensec_security_ops_enabled(backends[i], gensec_security))
222 if (backends[i]->sasl_name
223 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
224 backend = backends[i];
225 talloc_free(mem_ctx);
229 talloc_free(mem_ctx);
234 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
238 struct gensec_security_ops **backends;
239 const struct gensec_security_ops *backend;
240 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
244 backends = gensec_security_mechs(gensec_security, mem_ctx);
245 for (i=0; backends && backends[i]; i++) {
246 if (gensec_security != NULL &&
247 !gensec_security_ops_enabled(backends[i], gensec_security))
249 if (backends[i]->name
250 && (strcmp(backends[i]->name, name) == 0)) {
251 backend = backends[i];
252 talloc_free(mem_ctx);
256 talloc_free(mem_ctx);
261 * Return a unique list of security subsystems from those specified in
262 * the list of SASL names.
264 * Use the list of enabled GENSEC mechanisms from the credentials
265 * attached to the gensec_security, and return in our preferred order.
268 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
270 const char **sasl_names)
272 const struct gensec_security_ops **backends_out;
273 struct gensec_security_ops **backends;
275 int num_backends_out = 0;
281 backends = gensec_security_mechs(gensec_security, mem_ctx);
283 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
287 backends_out[0] = NULL;
289 /* Find backends in our preferred order, by walking our list,
290 * then looking in the supplied list */
291 for (i=0; backends && backends[i]; i++) {
292 if (gensec_security != NULL &&
293 !gensec_security_ops_enabled(backends[i], gensec_security))
295 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
296 if (!backends[i]->sasl_name ||
297 !(strcmp(backends[i]->sasl_name,
298 sasl_names[sasl_idx]) == 0)) {
302 for (k=0; backends_out[k]; k++) {
303 if (backends_out[k] == backends[i]) {
308 if (k < num_backends_out) {
309 /* already in there */
313 backends_out = talloc_realloc(mem_ctx, backends_out,
314 const struct gensec_security_ops *,
315 num_backends_out + 2);
320 backends_out[num_backends_out] = backends[i];
322 backends_out[num_backends_out] = NULL;
329 * Return a unique list of security subsystems from those specified in
330 * the OID list. That is, where two OIDs refer to the same module,
331 * return that module only once.
333 * Use the list of enabled GENSEC mechanisms from the credentials
334 * attached to the gensec_security, and return in our preferred order.
337 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
338 struct gensec_security *gensec_security,
340 const char **oid_strings,
343 struct gensec_security_ops_wrapper *backends_out;
344 struct gensec_security_ops **backends;
345 int i, j, k, oid_idx;
346 int num_backends_out = 0;
352 backends = gensec_security_mechs(gensec_security, gensec_security);
354 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
358 backends_out[0].op = NULL;
359 backends_out[0].oid = NULL;
361 /* Find backends in our preferred order, by walking our list,
362 * then looking in the supplied list */
363 for (i=0; backends && backends[i]; i++) {
364 if (gensec_security != NULL &&
365 !gensec_security_ops_enabled(backends[i], gensec_security))
367 if (!backends[i]->oid) {
370 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
371 if (strcmp(oid_strings[oid_idx], skip) == 0) {
375 for (j=0; backends[i]->oid[j]; j++) {
376 if (!backends[i]->oid[j] ||
377 !(strcmp(backends[i]->oid[j],
378 oid_strings[oid_idx]) == 0)) {
382 for (k=0; backends_out[k].op; k++) {
383 if (backends_out[k].op == backends[i]) {
388 if (k < num_backends_out) {
389 /* already in there */
393 backends_out = talloc_realloc(mem_ctx, backends_out,
394 struct gensec_security_ops_wrapper,
395 num_backends_out + 2);
400 backends_out[num_backends_out].op = backends[i];
401 backends_out[num_backends_out].oid = backends[i]->oid[j];
403 backends_out[num_backends_out].op = NULL;
404 backends_out[num_backends_out].oid = NULL;
412 * Return OIDS from the security subsystems listed
415 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
417 struct gensec_security_ops **ops,
423 const char **oid_list;
427 oid_list = talloc_array(mem_ctx, const char *, 1);
432 for (i=0; ops && ops[i]; i++) {
433 if (gensec_security != NULL &&
434 !gensec_security_ops_enabled(ops[i], gensec_security)) {
441 for (k = 0; ops[i]->oid[k]; k++) {
442 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
444 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
448 oid_list[j] = ops[i]->oid[k];
459 * Return OIDS from the security subsystems listed
462 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
463 const struct gensec_security_ops_wrapper *wops)
468 const char **oid_list;
472 oid_list = talloc_array(mem_ctx, const char *, 1);
477 for (i=0; wops[i].op; i++) {
478 if (!wops[i].op->oid) {
482 for (k = 0; wops[i].op->oid[k]; k++) {
483 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
487 oid_list[j] = wops[i].op->oid[k];
497 * Return all the security subsystems currently enabled on a GENSEC context.
499 * This is taken from a list attached to the cli_credentials, and
500 * skips the OID in 'skip'. (Typically the SPNEGO OID)
504 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
508 struct gensec_security_ops **ops
509 = gensec_security_mechs(gensec_security, mem_ctx);
510 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
514 Start the GENSEC system, returning a context pointer.
515 @param mem_ctx The parent TALLOC memory context.
516 @param gensec_security Returned GENSEC context pointer.
517 @note The mem_ctx is only a parent and may be NULL.
518 @note, the auth context is moved to be a referenced pointer of the
519 @ gensec_security return
521 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
522 struct gensec_settings *settings,
523 struct auth4_context *auth_context,
524 struct gensec_security **gensec_security)
526 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
527 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
529 (*gensec_security)->max_update_size = 0;
531 SMB_ASSERT(settings->lp_ctx != NULL);
532 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
534 /* We need to reference this, not steal, as the caller may be
535 * python, which won't like it if we steal it's object away
537 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
543 * Start a GENSEC subcontext, with a copy of the properties of the parent
544 * @param mem_ctx The parent TALLOC memory context.
545 * @param parent The parent GENSEC context
546 * @param gensec_security Returned GENSEC context pointer.
547 * @note Used by SPNEGO in particular, for the actual implementation mechanism
550 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
551 struct gensec_security *parent,
552 struct gensec_security **gensec_security)
554 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
555 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
557 (**gensec_security) = *parent;
558 (*gensec_security)->ops = NULL;
559 (*gensec_security)->private_data = NULL;
561 (*gensec_security)->subcontext = true;
562 (*gensec_security)->want_features = parent->want_features;
563 (*gensec_security)->max_update_size = parent->max_update_size;
564 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
565 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
566 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
567 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
573 Start the GENSEC system, in client mode, returning a context pointer.
574 @param mem_ctx The parent TALLOC memory context.
575 @param gensec_security Returned GENSEC context pointer.
576 @note The mem_ctx is only a parent and may be NULL.
578 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
579 struct gensec_security **gensec_security,
580 struct gensec_settings *settings)
584 if (settings == NULL) {
585 DEBUG(0,("gensec_client_start: no settings given!\n"));
586 return NT_STATUS_INTERNAL_ERROR;
589 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
590 if (!NT_STATUS_IS_OK(status)) {
593 (*gensec_security)->gensec_role = GENSEC_CLIENT;
601 Start the GENSEC system, in server mode, returning a context pointer.
602 @param mem_ctx The parent TALLOC memory context.
603 @param gensec_security Returned GENSEC context pointer.
604 @note The mem_ctx is only a parent and may be NULL.
606 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
607 struct gensec_settings *settings,
608 struct auth4_context *auth_context,
609 struct gensec_security **gensec_security)
614 DEBUG(0,("gensec_server_start: no settings given!\n"));
615 return NT_STATUS_INTERNAL_ERROR;
618 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
619 if (!NT_STATUS_IS_OK(status)) {
622 (*gensec_security)->gensec_role = GENSEC_SERVER;
627 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
630 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
631 gensec_security->subcontext ? "sub" : "",
632 gensec_security->ops->name));
633 switch (gensec_security->gensec_role) {
635 if (gensec_security->ops->client_start) {
636 status = gensec_security->ops->client_start(gensec_security);
637 if (!NT_STATUS_IS_OK(status)) {
638 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
639 gensec_security->ops->name, nt_errstr(status)));
645 if (gensec_security->ops->server_start) {
646 status = gensec_security->ops->server_start(gensec_security);
647 if (!NT_STATUS_IS_OK(status)) {
648 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
649 gensec_security->ops->name, nt_errstr(status)));
655 return NT_STATUS_INVALID_PARAMETER;
659 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
663 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
664 const struct gensec_security_ops *ops)
666 gensec_security->ops = ops;
667 return gensec_start_mech(gensec_security);
672 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
673 * @param gensec_security GENSEC context pointer.
674 * @param auth_type DCERPC auth type
675 * @param auth_level DCERPC auth level
678 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
679 uint8_t auth_type, uint8_t auth_level)
681 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
682 if (!gensec_security->ops) {
683 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
684 return NT_STATUS_INVALID_PARAMETER;
686 gensec_security->dcerpc_auth_level = auth_level;
687 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
688 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
689 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
690 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
691 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
692 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
693 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
694 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
695 /* Default features */
697 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
699 return NT_STATUS_INVALID_PARAMETER;
702 return gensec_start_mech(gensec_security);
705 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
707 const struct gensec_security_ops *ops;
708 ops = gensec_security_by_authtype(gensec_security, authtype);
716 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
717 const char *oid_string)
719 const struct gensec_security_ops *ops;
720 ops = gensec_security_by_oid(gensec_security, oid_string);
728 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
730 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
731 * well-known #define to hook it in.
734 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
735 const char *mech_oid)
737 SMB_ASSERT(gensec_security != NULL);
739 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
740 if (!gensec_security->ops) {
741 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
742 return NT_STATUS_INVALID_PARAMETER;
744 return gensec_start_mech(gensec_security);
748 * Start a GENSEC sub-mechanism by a well know SASL name
752 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
753 const char *sasl_name)
755 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
756 if (!gensec_security->ops) {
757 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
758 return NT_STATUS_INVALID_PARAMETER;
760 return gensec_start_mech(gensec_security);
764 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
768 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
769 const char **sasl_names)
771 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
772 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
773 const struct gensec_security_ops **ops;
776 return NT_STATUS_NO_MEMORY;
778 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
780 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
781 str_list_join(mem_ctx,
783 talloc_free(mem_ctx);
784 return NT_STATUS_INVALID_PARAMETER;
786 for (i=0; ops[i]; i++) {
787 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
788 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
792 talloc_free(mem_ctx);
797 * Start a GENSEC sub-mechanism by an internal name
801 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
804 gensec_security->ops = gensec_security_by_name(gensec_security, name);
805 if (!gensec_security->ops) {
806 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
807 return NT_STATUS_INVALID_PARAMETER;
809 return gensec_start_mech(gensec_security);
813 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
817 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
819 gensec_security->credentials = talloc_reference(gensec_security, credentials);
820 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
821 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
826 register a GENSEC backend.
828 The 'name' can be later used by other backends to find the operations
829 structure for this backend.
831 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
833 if (gensec_security_by_name(NULL, ops->name) != NULL) {
834 /* its already registered! */
835 DEBUG(0,("GENSEC backend '%s' already registered\n",
837 return NT_STATUS_OBJECT_NAME_COLLISION;
840 generic_security_ops = talloc_realloc(talloc_autofree_context(),
841 generic_security_ops,
842 struct gensec_security_ops *,
843 gensec_num_backends+2);
844 if (!generic_security_ops) {
845 return NT_STATUS_NO_MEMORY;
848 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
849 gensec_num_backends++;
850 generic_security_ops[gensec_num_backends] = NULL;
852 DEBUG(3,("GENSEC backend '%s' registered\n",
859 return the GENSEC interface version, and the size of some critical types
860 This can be used by backends to either detect compilation errors, or provide
861 multiple implementations for different smbd compilation options in one module
863 const struct gensec_critical_sizes *gensec_interface_version(void)
865 static const struct gensec_critical_sizes critical_sizes = {
866 GENSEC_INTERFACE_VERSION,
867 sizeof(struct gensec_security_ops),
868 sizeof(struct gensec_security),
871 return &critical_sizes;
874 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
875 return (*gs2)->priority - (*gs1)->priority;
878 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
880 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
883 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
885 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
889 initialise the GENSEC subsystem
891 _PUBLIC_ NTSTATUS gensec_init(void)
893 static bool initialized = false;
894 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
895 #ifdef STATIC_gensec_MODULES
896 STATIC_gensec_MODULES_PROTO;
897 init_module_fn static_init[] = { STATIC_gensec_MODULES };
899 init_module_fn *static_init = NULL;
901 init_module_fn *shared_init;
903 if (initialized) return NT_STATUS_OK;
906 shared_init = load_samba_modules(NULL, "gensec");
908 run_init_functions(static_init);
909 run_init_functions(shared_init);
911 talloc_free(shared_init);
913 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);