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 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_reference it if convient */
41 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
43 return generic_security_ops;
46 bool gensec_security_ops_enabled(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_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
72 struct gensec_security_ops **old_gensec_list,
73 struct cli_credentials *creds)
75 struct gensec_security_ops **new_gensec_list;
76 int i, j, num_mechs_in;
77 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
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, struct gensec_security_ops *, num_mechs_in + 1);
88 if (!new_gensec_list) {
93 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
97 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
98 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
104 switch (use_kerberos) {
105 case CRED_AUTO_USE_KERBEROS:
109 case CRED_DONT_USE_KERBEROS:
110 if (old_gensec_list[i]->kerberos == false) {
116 case CRED_MUST_USE_KERBEROS:
117 if (old_gensec_list[i]->kerberos == true) {
123 /* Can't happen or invalid parameter */
131 new_gensec_list[j] = old_gensec_list[i];
134 new_gensec_list[j] = NULL;
136 return new_gensec_list;
139 _PUBLIC_ struct gensec_security_ops **gensec_security_mechs(
140 struct gensec_security *gensec_security,
143 struct cli_credentials *creds = NULL;
144 struct gensec_security_ops **backends = gensec_security_all();
146 if (gensec_security != NULL) {
147 creds = gensec_get_credentials(gensec_security);
149 if (gensec_security->settings->backends) {
150 backends = gensec_security->settings->backends;
154 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
158 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
162 struct gensec_security_ops **backends;
163 const struct gensec_security_ops *backend;
164 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
168 backends = gensec_security_mechs(gensec_security, mem_ctx);
169 for (i=0; backends && backends[i]; i++) {
170 if (!gensec_security_ops_enabled(backends[i], gensec_security))
172 if (backends[i]->auth_type == auth_type) {
173 backend = backends[i];
174 talloc_free(mem_ctx);
178 talloc_free(mem_ctx);
183 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
184 struct gensec_security *gensec_security,
185 const char *oid_string)
188 struct gensec_security_ops **backends;
189 const struct gensec_security_ops *backend;
190 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
194 backends = gensec_security_mechs(gensec_security, mem_ctx);
195 for (i=0; backends && backends[i]; i++) {
196 if (gensec_security != NULL &&
197 !gensec_security_ops_enabled(backends[i],
200 if (backends[i]->oid) {
201 for (j=0; backends[i]->oid[j]; j++) {
202 if (backends[i]->oid[j] &&
203 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
204 backend = backends[i];
205 talloc_free(mem_ctx);
211 talloc_free(mem_ctx);
216 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
217 struct gensec_security *gensec_security,
218 const char *sasl_name)
221 struct gensec_security_ops **backends;
222 const struct gensec_security_ops *backend;
223 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
227 backends = gensec_security_mechs(gensec_security, mem_ctx);
228 for (i=0; backends && backends[i]; i++) {
229 if (!gensec_security_ops_enabled(backends[i], gensec_security))
231 if (backends[i]->sasl_name
232 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
233 backend = backends[i];
234 talloc_free(mem_ctx);
238 talloc_free(mem_ctx);
243 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
244 struct gensec_security *gensec_security,
248 struct gensec_security_ops **backends;
249 const struct gensec_security_ops *backend;
250 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
254 backends = gensec_security_mechs(gensec_security, mem_ctx);
255 for (i=0; backends && backends[i]; i++) {
256 if (!gensec_security_ops_enabled(backends[i], gensec_security))
258 if (backends[i]->auth_type == auth_type) {
259 backend = backends[i];
260 talloc_free(mem_ctx);
264 talloc_free(mem_ctx);
269 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
273 struct gensec_security_ops **backends;
274 const struct gensec_security_ops *backend;
275 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
279 backends = gensec_security_mechs(gensec_security, mem_ctx);
280 for (i=0; backends && backends[i]; i++) {
281 if (gensec_security != NULL &&
282 !gensec_security_ops_enabled(backends[i], gensec_security))
284 if (backends[i]->name
285 && (strcmp(backends[i]->name, name) == 0)) {
286 backend = backends[i];
287 talloc_free(mem_ctx);
291 talloc_free(mem_ctx);
296 * Return a unique list of security subsystems from those specified in
297 * the list of SASL names.
299 * Use the list of enabled GENSEC mechanisms from the credentials
300 * attached to the gensec_security, and return in our preferred order.
303 static const struct gensec_security_ops **gensec_security_by_sasl_list(
304 struct gensec_security *gensec_security,
306 const char **sasl_names)
308 const struct gensec_security_ops **backends_out;
309 struct gensec_security_ops **backends;
311 int num_backends_out = 0;
317 backends = gensec_security_mechs(gensec_security, mem_ctx);
319 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
323 backends_out[0] = NULL;
325 /* Find backends in our preferred order, by walking our list,
326 * then looking in the supplied list */
327 for (i=0; backends && backends[i]; i++) {
328 if (gensec_security != NULL &&
329 !gensec_security_ops_enabled(backends[i], gensec_security))
331 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
332 if (!backends[i]->sasl_name ||
333 !(strcmp(backends[i]->sasl_name,
334 sasl_names[sasl_idx]) == 0)) {
338 for (k=0; backends_out[k]; k++) {
339 if (backends_out[k] == backends[i]) {
344 if (k < num_backends_out) {
345 /* already in there */
349 backends_out = talloc_realloc(mem_ctx, backends_out,
350 const struct gensec_security_ops *,
351 num_backends_out + 2);
356 backends_out[num_backends_out] = backends[i];
358 backends_out[num_backends_out] = NULL;
365 * Return a unique list of security subsystems from those specified in
366 * the OID list. That is, where two OIDs refer to the same module,
367 * return that module only once.
369 * Use the list of enabled GENSEC mechanisms from the credentials
370 * attached to the gensec_security, and return in our preferred order.
373 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
374 struct gensec_security *gensec_security,
376 const char **oid_strings,
379 struct gensec_security_ops_wrapper *backends_out;
380 struct gensec_security_ops **backends;
381 int i, j, k, oid_idx;
382 int num_backends_out = 0;
388 backends = gensec_security_mechs(gensec_security, gensec_security);
390 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
394 backends_out[0].op = NULL;
395 backends_out[0].oid = NULL;
397 /* Find backends in our preferred order, by walking our list,
398 * then looking in the supplied list */
399 for (i=0; backends && backends[i]; i++) {
400 if (gensec_security != NULL &&
401 !gensec_security_ops_enabled(backends[i], gensec_security))
403 if (!backends[i]->oid) {
406 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
407 if (strcmp(oid_strings[oid_idx], skip) == 0) {
411 for (j=0; backends[i]->oid[j]; j++) {
412 if (!backends[i]->oid[j] ||
413 !(strcmp(backends[i]->oid[j],
414 oid_strings[oid_idx]) == 0)) {
418 for (k=0; backends_out[k].op; k++) {
419 if (backends_out[k].op == backends[i]) {
424 if (k < num_backends_out) {
425 /* already in there */
429 backends_out = talloc_realloc(mem_ctx, backends_out,
430 struct gensec_security_ops_wrapper,
431 num_backends_out + 2);
436 backends_out[num_backends_out].op = backends[i];
437 backends_out[num_backends_out].oid = backends[i]->oid[j];
439 backends_out[num_backends_out].op = NULL;
440 backends_out[num_backends_out].oid = NULL;
448 * Return OIDS from the security subsystems listed
451 static const char **gensec_security_oids_from_ops(
452 struct gensec_security *gensec_security,
454 struct gensec_security_ops **ops,
460 const char **oid_list;
464 oid_list = talloc_array(mem_ctx, const char *, 1);
469 for (i=0; ops && ops[i]; i++) {
470 if (gensec_security != NULL &&
471 !gensec_security_ops_enabled(ops[i], gensec_security)) {
478 for (k = 0; ops[i]->oid[k]; k++) {
479 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
481 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
485 oid_list[j] = ops[i]->oid[k];
496 * Return OIDS from the security subsystems listed
499 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
500 const struct gensec_security_ops_wrapper *wops)
505 const char **oid_list;
509 oid_list = talloc_array(mem_ctx, const char *, 1);
514 for (i=0; wops[i].op; i++) {
515 if (!wops[i].op->oid) {
519 for (k = 0; wops[i].op->oid[k]; k++) {
520 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
524 oid_list[j] = wops[i].op->oid[k];
534 * Return all the security subsystems currently enabled on a GENSEC context.
536 * This is taken from a list attached to the cli_credentials, and
537 * skips the OID in 'skip'. (Typically the SPNEGO OID)
541 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
545 struct gensec_security_ops **ops
546 = gensec_security_mechs(gensec_security, mem_ctx);
547 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
551 Start the GENSEC system, returning a context pointer.
552 @param mem_ctx The parent TALLOC memory context.
553 @param gensec_security Returned GENSEC context pointer.
554 @note The mem_ctx is only a parent and may be NULL.
555 @note, the auth context is moved to be a referenced pointer of the
556 @ gensec_security return
558 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
559 struct gensec_settings *settings,
560 struct auth4_context *auth_context,
561 struct gensec_security **gensec_security)
563 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
564 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
566 (*gensec_security)->max_update_size = 0;
568 SMB_ASSERT(settings->lp_ctx != NULL);
569 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
571 /* We need to reference this, not steal, as the caller may be
572 * python, which won't like it if we steal it's object away
574 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
580 * Start a GENSEC subcontext, with a copy of the properties of the parent
581 * @param mem_ctx The parent TALLOC memory context.
582 * @param parent The parent GENSEC context
583 * @param gensec_security Returned GENSEC context pointer.
584 * @note Used by SPNEGO in particular, for the actual implementation mechanism
587 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
588 struct gensec_security *parent,
589 struct gensec_security **gensec_security)
591 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
592 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
594 (**gensec_security) = *parent;
595 (*gensec_security)->ops = NULL;
596 (*gensec_security)->private_data = NULL;
598 (*gensec_security)->subcontext = true;
599 (*gensec_security)->want_features = parent->want_features;
600 (*gensec_security)->max_update_size = parent->max_update_size;
601 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
602 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
603 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
604 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
610 Start the GENSEC system, in client mode, returning a context pointer.
611 @param mem_ctx The parent TALLOC memory context.
612 @param gensec_security Returned GENSEC context pointer.
613 @note The mem_ctx is only a parent and may be NULL.
615 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
616 struct gensec_security **gensec_security,
617 struct gensec_settings *settings)
621 if (settings == NULL) {
622 DEBUG(0,("gensec_client_start: no settings given!\n"));
623 return NT_STATUS_INTERNAL_ERROR;
626 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
627 if (!NT_STATUS_IS_OK(status)) {
630 (*gensec_security)->gensec_role = GENSEC_CLIENT;
638 Start the GENSEC system, in server mode, returning a context pointer.
639 @param mem_ctx The parent TALLOC memory context.
640 @param gensec_security Returned GENSEC context pointer.
641 @note The mem_ctx is only a parent and may be NULL.
643 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
644 struct gensec_settings *settings,
645 struct auth4_context *auth_context,
646 struct gensec_security **gensec_security)
651 DEBUG(0,("gensec_server_start: no settings given!\n"));
652 return NT_STATUS_INTERNAL_ERROR;
655 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
656 if (!NT_STATUS_IS_OK(status)) {
659 (*gensec_security)->gensec_role = GENSEC_SERVER;
664 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
667 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
668 gensec_security->subcontext ? "sub" : "",
669 gensec_security->ops->name));
670 switch (gensec_security->gensec_role) {
672 if (gensec_security->ops->client_start) {
673 status = gensec_security->ops->client_start(gensec_security);
674 if (!NT_STATUS_IS_OK(status)) {
675 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
676 gensec_security->ops->name, nt_errstr(status)));
682 if (gensec_security->ops->server_start) {
683 status = gensec_security->ops->server_start(gensec_security);
684 if (!NT_STATUS_IS_OK(status)) {
685 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
686 gensec_security->ops->name, nt_errstr(status)));
692 return NT_STATUS_INVALID_PARAMETER;
696 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
700 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
701 const struct gensec_security_ops *ops)
703 gensec_security->ops = ops;
704 return gensec_start_mech(gensec_security);
709 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
710 * @param gensec_security GENSEC context pointer.
711 * @param auth_type DCERPC auth type
712 * @param auth_level DCERPC auth level
715 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
716 uint8_t auth_type, uint8_t auth_level)
718 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
719 if (!gensec_security->ops) {
720 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
721 return NT_STATUS_INVALID_PARAMETER;
723 gensec_security->dcerpc_auth_level = auth_level;
724 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
725 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
726 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
727 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
728 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
729 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
730 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
731 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
732 /* Default features */
734 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
736 return NT_STATUS_INVALID_PARAMETER;
739 return gensec_start_mech(gensec_security);
742 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
744 const struct gensec_security_ops *ops;
745 ops = gensec_security_by_authtype(gensec_security, authtype);
753 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
754 const char *oid_string)
756 const struct gensec_security_ops *ops;
757 ops = gensec_security_by_oid(gensec_security, oid_string);
765 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
767 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
768 * well-known #define to hook it in.
771 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
772 const char *mech_oid)
774 SMB_ASSERT(gensec_security != NULL);
776 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
777 if (!gensec_security->ops) {
778 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
779 return NT_STATUS_INVALID_PARAMETER;
781 return gensec_start_mech(gensec_security);
785 * Start a GENSEC sub-mechanism by a well know SASL name
789 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
790 const char *sasl_name)
792 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
793 if (!gensec_security->ops) {
794 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
795 return NT_STATUS_INVALID_PARAMETER;
797 return gensec_start_mech(gensec_security);
801 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
805 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
806 const char **sasl_names)
808 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
809 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
810 const struct gensec_security_ops **ops;
813 return NT_STATUS_NO_MEMORY;
815 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
817 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
818 str_list_join(mem_ctx,
820 talloc_free(mem_ctx);
821 return NT_STATUS_INVALID_PARAMETER;
823 for (i=0; ops[i]; i++) {
824 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
825 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
829 talloc_free(mem_ctx);
834 * Start a GENSEC sub-mechanism by an internal name
838 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
841 gensec_security->ops = gensec_security_by_name(gensec_security, name);
842 if (!gensec_security->ops) {
843 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
844 return NT_STATUS_INVALID_PARAMETER;
846 return gensec_start_mech(gensec_security);
850 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
854 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
856 gensec_security->credentials = talloc_reference(gensec_security, credentials);
857 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
858 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
863 register a GENSEC backend.
865 The 'name' can be later used by other backends to find the operations
866 structure for this backend.
868 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
870 if (gensec_security_by_name(NULL, ops->name) != NULL) {
871 /* its already registered! */
872 DEBUG(0,("GENSEC backend '%s' already registered\n",
874 return NT_STATUS_OBJECT_NAME_COLLISION;
877 generic_security_ops = talloc_realloc(talloc_autofree_context(),
878 generic_security_ops,
879 struct gensec_security_ops *,
880 gensec_num_backends+2);
881 if (!generic_security_ops) {
882 return NT_STATUS_NO_MEMORY;
885 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
886 gensec_num_backends++;
887 generic_security_ops[gensec_num_backends] = NULL;
889 DEBUG(3,("GENSEC backend '%s' registered\n",
896 return the GENSEC interface version, and the size of some critical types
897 This can be used by backends to either detect compilation errors, or provide
898 multiple implementations for different smbd compilation options in one module
900 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
902 static const struct gensec_critical_sizes critical_sizes = {
903 GENSEC_INTERFACE_VERSION,
904 sizeof(struct gensec_security_ops),
905 sizeof(struct gensec_security),
908 return &critical_sizes;
911 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
912 return (*gs2)->priority - (*gs1)->priority;
915 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
917 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
920 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
922 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
926 initialise the GENSEC subsystem
928 _PUBLIC_ NTSTATUS gensec_init(void)
930 static bool initialized = false;
931 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
932 #ifdef STATIC_gensec_MODULES
933 STATIC_gensec_MODULES_PROTO;
934 init_module_fn static_init[] = { STATIC_gensec_MODULES };
936 init_module_fn *static_init = NULL;
938 init_module_fn *shared_init;
940 if (initialized) return NT_STATUS_OK;
943 shared_init = load_samba_modules(NULL, "gensec");
945 run_init_functions(static_init);
946 run_init_functions(shared_init);
948 talloc_free(shared_init);
950 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);