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 gensec_security_ops **backends;
144 if (!gensec_security) {
145 backends = gensec_security_all();
146 if (!talloc_reference(mem_ctx, backends)) {
151 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
152 if (gensec_security->settings->backends) {
153 backends = gensec_security->settings->backends;
155 backends = gensec_security_all();
158 if (!talloc_reference(mem_ctx, backends)) {
163 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
167 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
171 struct gensec_security_ops **backends;
172 const struct gensec_security_ops *backend;
173 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
177 backends = gensec_security_mechs(gensec_security, mem_ctx);
178 for (i=0; backends && backends[i]; i++) {
179 if (!gensec_security_ops_enabled(backends[i], gensec_security))
181 if (backends[i]->auth_type == auth_type) {
182 backend = backends[i];
183 talloc_free(mem_ctx);
187 talloc_free(mem_ctx);
192 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
193 struct gensec_security *gensec_security,
194 const char *oid_string)
197 struct gensec_security_ops **backends;
198 const struct gensec_security_ops *backend;
199 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
203 backends = gensec_security_mechs(gensec_security, mem_ctx);
204 for (i=0; backends && backends[i]; i++) {
205 if (gensec_security != NULL &&
206 !gensec_security_ops_enabled(backends[i],
209 if (backends[i]->oid) {
210 for (j=0; backends[i]->oid[j]; j++) {
211 if (backends[i]->oid[j] &&
212 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
213 backend = backends[i];
214 talloc_free(mem_ctx);
220 talloc_free(mem_ctx);
225 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
226 struct gensec_security *gensec_security,
227 const char *sasl_name)
230 struct gensec_security_ops **backends;
231 const struct gensec_security_ops *backend;
232 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
236 backends = gensec_security_mechs(gensec_security, mem_ctx);
237 for (i=0; backends && backends[i]; i++) {
238 if (!gensec_security_ops_enabled(backends[i], gensec_security))
240 if (backends[i]->sasl_name
241 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
242 backend = backends[i];
243 talloc_free(mem_ctx);
247 talloc_free(mem_ctx);
252 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
253 struct gensec_security *gensec_security,
257 struct gensec_security_ops **backends;
258 const struct gensec_security_ops *backend;
259 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
263 backends = gensec_security_mechs(gensec_security, mem_ctx);
264 for (i=0; backends && backends[i]; i++) {
265 if (!gensec_security_ops_enabled(backends[i], gensec_security))
267 if (backends[i]->auth_type == auth_type) {
268 backend = backends[i];
269 talloc_free(mem_ctx);
273 talloc_free(mem_ctx);
278 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
282 struct gensec_security_ops **backends;
283 const struct gensec_security_ops *backend;
284 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
288 backends = gensec_security_mechs(gensec_security, mem_ctx);
289 for (i=0; backends && backends[i]; i++) {
290 if (gensec_security != NULL &&
291 !gensec_security_ops_enabled(backends[i], gensec_security))
293 if (backends[i]->name
294 && (strcmp(backends[i]->name, name) == 0)) {
295 backend = backends[i];
296 talloc_free(mem_ctx);
300 talloc_free(mem_ctx);
305 * Return a unique list of security subsystems from those specified in
306 * the list of SASL names.
308 * Use the list of enabled GENSEC mechanisms from the credentials
309 * attached to the gensec_security, and return in our preferred order.
312 static const struct gensec_security_ops **gensec_security_by_sasl_list(
313 struct gensec_security *gensec_security,
315 const char **sasl_names)
317 const struct gensec_security_ops **backends_out;
318 struct gensec_security_ops **backends;
320 int num_backends_out = 0;
326 backends = gensec_security_mechs(gensec_security, mem_ctx);
328 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
332 backends_out[0] = NULL;
334 /* Find backends in our preferred order, by walking our list,
335 * then looking in the supplied list */
336 for (i=0; backends && backends[i]; i++) {
337 if (gensec_security != NULL &&
338 !gensec_security_ops_enabled(backends[i], gensec_security))
340 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
341 if (!backends[i]->sasl_name ||
342 !(strcmp(backends[i]->sasl_name,
343 sasl_names[sasl_idx]) == 0)) {
347 for (k=0; backends_out[k]; k++) {
348 if (backends_out[k] == backends[i]) {
353 if (k < num_backends_out) {
354 /* already in there */
358 backends_out = talloc_realloc(mem_ctx, backends_out,
359 const struct gensec_security_ops *,
360 num_backends_out + 2);
365 backends_out[num_backends_out] = backends[i];
367 backends_out[num_backends_out] = NULL;
374 * Return a unique list of security subsystems from those specified in
375 * the OID list. That is, where two OIDs refer to the same module,
376 * return that module only once.
378 * Use the list of enabled GENSEC mechanisms from the credentials
379 * attached to the gensec_security, and return in our preferred order.
382 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
383 struct gensec_security *gensec_security,
385 const char **oid_strings,
388 struct gensec_security_ops_wrapper *backends_out;
389 struct gensec_security_ops **backends;
390 int i, j, k, oid_idx;
391 int num_backends_out = 0;
397 backends = gensec_security_mechs(gensec_security, gensec_security);
399 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
403 backends_out[0].op = NULL;
404 backends_out[0].oid = NULL;
406 /* Find backends in our preferred order, by walking our list,
407 * then looking in the supplied list */
408 for (i=0; backends && backends[i]; i++) {
409 if (gensec_security != NULL &&
410 !gensec_security_ops_enabled(backends[i], gensec_security))
412 if (!backends[i]->oid) {
415 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
416 if (strcmp(oid_strings[oid_idx], skip) == 0) {
420 for (j=0; backends[i]->oid[j]; j++) {
421 if (!backends[i]->oid[j] ||
422 !(strcmp(backends[i]->oid[j],
423 oid_strings[oid_idx]) == 0)) {
427 for (k=0; backends_out[k].op; k++) {
428 if (backends_out[k].op == backends[i]) {
433 if (k < num_backends_out) {
434 /* already in there */
438 backends_out = talloc_realloc(mem_ctx, backends_out,
439 struct gensec_security_ops_wrapper,
440 num_backends_out + 2);
445 backends_out[num_backends_out].op = backends[i];
446 backends_out[num_backends_out].oid = backends[i]->oid[j];
448 backends_out[num_backends_out].op = NULL;
449 backends_out[num_backends_out].oid = NULL;
457 * Return OIDS from the security subsystems listed
460 static const char **gensec_security_oids_from_ops(
461 struct gensec_security *gensec_security,
463 struct gensec_security_ops **ops,
469 const char **oid_list;
473 oid_list = talloc_array(mem_ctx, const char *, 1);
478 for (i=0; ops && ops[i]; i++) {
479 if (gensec_security != NULL &&
480 !gensec_security_ops_enabled(ops[i], gensec_security)) {
487 for (k = 0; ops[i]->oid[k]; k++) {
488 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
490 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
494 oid_list[j] = ops[i]->oid[k];
505 * Return OIDS from the security subsystems listed
508 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
509 const struct gensec_security_ops_wrapper *wops)
514 const char **oid_list;
518 oid_list = talloc_array(mem_ctx, const char *, 1);
523 for (i=0; wops[i].op; i++) {
524 if (!wops[i].op->oid) {
528 for (k = 0; wops[i].op->oid[k]; k++) {
529 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
533 oid_list[j] = wops[i].op->oid[k];
543 * Return all the security subsystems currently enabled on a GENSEC context.
545 * This is taken from a list attached to the cli_credentials, and
546 * skips the OID in 'skip'. (Typically the SPNEGO OID)
550 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
554 struct gensec_security_ops **ops
555 = gensec_security_mechs(gensec_security, mem_ctx);
556 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
560 Start the GENSEC system, returning a context pointer.
561 @param mem_ctx The parent TALLOC memory context.
562 @param gensec_security Returned GENSEC context pointer.
563 @note The mem_ctx is only a parent and may be NULL.
564 @note, the auth context is moved to be a referenced pointer of the
565 @ gensec_security return
567 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
568 struct gensec_settings *settings,
569 struct auth4_context *auth_context,
570 struct gensec_security **gensec_security)
572 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
573 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
575 (*gensec_security)->max_update_size = 0;
577 SMB_ASSERT(settings->lp_ctx != NULL);
578 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
580 /* We need to reference this, not steal, as the caller may be
581 * python, which won't like it if we steal it's object away
583 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
589 * Start a GENSEC subcontext, with a copy of the properties of the parent
590 * @param mem_ctx The parent TALLOC memory context.
591 * @param parent The parent GENSEC context
592 * @param gensec_security Returned GENSEC context pointer.
593 * @note Used by SPNEGO in particular, for the actual implementation mechanism
596 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
597 struct gensec_security *parent,
598 struct gensec_security **gensec_security)
600 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
601 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
603 (**gensec_security) = *parent;
604 (*gensec_security)->ops = NULL;
605 (*gensec_security)->private_data = NULL;
607 (*gensec_security)->subcontext = true;
608 (*gensec_security)->want_features = parent->want_features;
609 (*gensec_security)->max_update_size = parent->max_update_size;
610 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
611 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
612 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
613 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
619 Start the GENSEC system, in client mode, returning a context pointer.
620 @param mem_ctx The parent TALLOC memory context.
621 @param gensec_security Returned GENSEC context pointer.
622 @note The mem_ctx is only a parent and may be NULL.
624 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
625 struct gensec_security **gensec_security,
626 struct gensec_settings *settings)
630 if (settings == NULL) {
631 DEBUG(0,("gensec_client_start: no settings given!\n"));
632 return NT_STATUS_INTERNAL_ERROR;
635 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
636 if (!NT_STATUS_IS_OK(status)) {
639 (*gensec_security)->gensec_role = GENSEC_CLIENT;
647 Start the GENSEC system, in server mode, returning a context pointer.
648 @param mem_ctx The parent TALLOC memory context.
649 @param gensec_security Returned GENSEC context pointer.
650 @note The mem_ctx is only a parent and may be NULL.
652 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
653 struct gensec_settings *settings,
654 struct auth4_context *auth_context,
655 struct gensec_security **gensec_security)
660 DEBUG(0,("gensec_server_start: no settings given!\n"));
661 return NT_STATUS_INTERNAL_ERROR;
664 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
665 if (!NT_STATUS_IS_OK(status)) {
668 (*gensec_security)->gensec_role = GENSEC_SERVER;
673 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
676 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
677 gensec_security->subcontext ? "sub" : "",
678 gensec_security->ops->name));
679 switch (gensec_security->gensec_role) {
681 if (gensec_security->ops->client_start) {
682 status = gensec_security->ops->client_start(gensec_security);
683 if (!NT_STATUS_IS_OK(status)) {
684 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
685 gensec_security->ops->name, nt_errstr(status)));
691 if (gensec_security->ops->server_start) {
692 status = gensec_security->ops->server_start(gensec_security);
693 if (!NT_STATUS_IS_OK(status)) {
694 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
695 gensec_security->ops->name, nt_errstr(status)));
701 return NT_STATUS_INVALID_PARAMETER;
705 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
709 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
710 const struct gensec_security_ops *ops)
712 gensec_security->ops = ops;
713 return gensec_start_mech(gensec_security);
718 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
719 * @param gensec_security GENSEC context pointer.
720 * @param auth_type DCERPC auth type
721 * @param auth_level DCERPC auth level
724 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
725 uint8_t auth_type, uint8_t auth_level)
727 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
728 if (!gensec_security->ops) {
729 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
730 return NT_STATUS_INVALID_PARAMETER;
732 gensec_security->dcerpc_auth_level = auth_level;
733 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
734 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
735 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
736 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
737 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
738 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
739 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
740 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
741 /* Default features */
743 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
745 return NT_STATUS_INVALID_PARAMETER;
748 return gensec_start_mech(gensec_security);
751 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
753 const struct gensec_security_ops *ops;
754 ops = gensec_security_by_authtype(gensec_security, authtype);
762 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
763 const char *oid_string)
765 const struct gensec_security_ops *ops;
766 ops = gensec_security_by_oid(gensec_security, oid_string);
774 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
776 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
777 * well-known #define to hook it in.
780 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
781 const char *mech_oid)
783 SMB_ASSERT(gensec_security != NULL);
785 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
786 if (!gensec_security->ops) {
787 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
788 return NT_STATUS_INVALID_PARAMETER;
790 return gensec_start_mech(gensec_security);
794 * Start a GENSEC sub-mechanism by a well know SASL name
798 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
799 const char *sasl_name)
801 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
802 if (!gensec_security->ops) {
803 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
804 return NT_STATUS_INVALID_PARAMETER;
806 return gensec_start_mech(gensec_security);
810 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
814 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
815 const char **sasl_names)
817 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
818 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
819 const struct gensec_security_ops **ops;
822 return NT_STATUS_NO_MEMORY;
824 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
826 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
827 str_list_join(mem_ctx,
829 talloc_free(mem_ctx);
830 return NT_STATUS_INVALID_PARAMETER;
832 for (i=0; ops[i]; i++) {
833 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
834 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
838 talloc_free(mem_ctx);
843 * Start a GENSEC sub-mechanism by an internal name
847 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
850 gensec_security->ops = gensec_security_by_name(gensec_security, name);
851 if (!gensec_security->ops) {
852 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
853 return NT_STATUS_INVALID_PARAMETER;
855 return gensec_start_mech(gensec_security);
859 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
863 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
865 gensec_security->credentials = talloc_reference(gensec_security, credentials);
866 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
867 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
872 register a GENSEC backend.
874 The 'name' can be later used by other backends to find the operations
875 structure for this backend.
877 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
879 if (gensec_security_by_name(NULL, ops->name) != NULL) {
880 /* its already registered! */
881 DEBUG(0,("GENSEC backend '%s' already registered\n",
883 return NT_STATUS_OBJECT_NAME_COLLISION;
886 generic_security_ops = talloc_realloc(talloc_autofree_context(),
887 generic_security_ops,
888 struct gensec_security_ops *,
889 gensec_num_backends+2);
890 if (!generic_security_ops) {
891 return NT_STATUS_NO_MEMORY;
894 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
895 gensec_num_backends++;
896 generic_security_ops[gensec_num_backends] = NULL;
898 DEBUG(3,("GENSEC backend '%s' registered\n",
905 return the GENSEC interface version, and the size of some critical types
906 This can be used by backends to either detect compilation errors, or provide
907 multiple implementations for different smbd compilation options in one module
909 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
911 static const struct gensec_critical_sizes critical_sizes = {
912 GENSEC_INTERFACE_VERSION,
913 sizeof(struct gensec_security_ops),
914 sizeof(struct gensec_security),
917 return &critical_sizes;
920 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
921 return (*gs2)->priority - (*gs1)->priority;
924 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
926 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
929 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
931 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
935 initialise the GENSEC subsystem
937 _PUBLIC_ NTSTATUS gensec_init(void)
939 static bool initialized = false;
940 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
941 #ifdef STATIC_gensec_MODULES
942 STATIC_gensec_MODULES_PROTO;
943 init_module_fn static_init[] = { STATIC_gensec_MODULES };
945 init_module_fn *static_init = NULL;
947 init_module_fn *shared_init;
949 if (initialized) return NT_STATUS_OK;
952 shared_init = load_samba_modules(NULL, "gensec");
954 run_init_functions(static_init);
955 run_init_functions(shared_init);
957 talloc_free(shared_init);
959 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);