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 * The intended logic is:
57 * if we are in the default AUTO have kerberos:
58 * - take a reference to the master list
60 * - always add spnego then:
61 * - if we 'MUST' have kerberos:
62 * only add kerberos mechs
63 * - if we 'DONT' want kerberos':
64 * only add non-kerberos mechs
66 * Once we get things like NegoEx or moonshot, this will of course get
70 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
71 struct gensec_security_ops **old_gensec_list,
72 struct cli_credentials *creds)
74 struct gensec_security_ops **new_gensec_list;
75 int i, j, num_mechs_in;
76 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
79 use_kerberos = cli_credentials_get_kerberos_state(creds);
82 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
83 if (!talloc_reference(mem_ctx, old_gensec_list)) {
86 return old_gensec_list;
89 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
93 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
94 if (!new_gensec_list) {
99 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
101 bool found_spnego = false;
102 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
103 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
104 new_gensec_list[j] = old_gensec_list[i];
113 switch (use_kerberos) {
114 case CRED_DONT_USE_KERBEROS:
115 if (old_gensec_list[i]->kerberos == false) {
116 new_gensec_list[j] = old_gensec_list[i];
120 case CRED_MUST_USE_KERBEROS:
121 if (old_gensec_list[i]->kerberos == true) {
122 new_gensec_list[j] = old_gensec_list[i];
127 /* Can't happen or invalid parameter */
131 new_gensec_list[j] = NULL;
133 return new_gensec_list;
136 _PUBLIC_ struct gensec_security_ops **gensec_security_mechs(
137 struct gensec_security *gensec_security,
140 struct gensec_security_ops **backends;
141 if (!gensec_security) {
142 backends = gensec_security_all();
143 if (!talloc_reference(mem_ctx, backends)) {
148 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
149 if (gensec_security->settings->backends) {
150 backends = gensec_security->settings->backends;
152 backends = gensec_security_all();
155 if (!talloc_reference(mem_ctx, backends)) {
160 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
164 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
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_ops_enabled(backends[i], gensec_security))
178 if (backends[i]->auth_type == auth_type) {
179 backend = backends[i];
180 talloc_free(mem_ctx);
184 talloc_free(mem_ctx);
189 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
190 struct gensec_security *gensec_security,
191 const char *oid_string)
194 struct gensec_security_ops **backends;
195 const struct gensec_security_ops *backend;
196 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
200 backends = gensec_security_mechs(gensec_security, mem_ctx);
201 for (i=0; backends && backends[i]; i++) {
202 if (gensec_security != NULL &&
203 !gensec_security_ops_enabled(backends[i],
206 if (backends[i]->oid) {
207 for (j=0; backends[i]->oid[j]; j++) {
208 if (backends[i]->oid[j] &&
209 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
210 backend = backends[i];
211 talloc_free(mem_ctx);
217 talloc_free(mem_ctx);
222 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
223 struct gensec_security *gensec_security,
224 const char *sasl_name)
227 struct gensec_security_ops **backends;
228 const struct gensec_security_ops *backend;
229 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
233 backends = gensec_security_mechs(gensec_security, mem_ctx);
234 for (i=0; backends && backends[i]; i++) {
235 if (!gensec_security_ops_enabled(backends[i], gensec_security))
237 if (backends[i]->sasl_name
238 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
239 backend = backends[i];
240 talloc_free(mem_ctx);
244 talloc_free(mem_ctx);
249 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
250 struct gensec_security *gensec_security,
254 struct gensec_security_ops **backends;
255 const struct gensec_security_ops *backend;
256 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
260 backends = gensec_security_mechs(gensec_security, mem_ctx);
261 for (i=0; backends && backends[i]; i++) {
262 if (!gensec_security_ops_enabled(backends[i], gensec_security))
264 if (backends[i]->auth_type == auth_type) {
265 backend = backends[i];
266 talloc_free(mem_ctx);
270 talloc_free(mem_ctx);
275 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
279 struct gensec_security_ops **backends;
280 const struct gensec_security_ops *backend;
281 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
285 backends = gensec_security_mechs(gensec_security, mem_ctx);
286 for (i=0; backends && backends[i]; i++) {
287 if (gensec_security != NULL &&
288 !gensec_security_ops_enabled(backends[i], gensec_security))
290 if (backends[i]->name
291 && (strcmp(backends[i]->name, name) == 0)) {
292 backend = backends[i];
293 talloc_free(mem_ctx);
297 talloc_free(mem_ctx);
302 * Return a unique list of security subsystems from those specified in
303 * the list of SASL names.
305 * Use the list of enabled GENSEC mechanisms from the credentials
306 * attached to the gensec_security, and return in our preferred order.
309 static const struct gensec_security_ops **gensec_security_by_sasl_list(
310 struct gensec_security *gensec_security,
312 const char **sasl_names)
314 const struct gensec_security_ops **backends_out;
315 struct gensec_security_ops **backends;
317 int num_backends_out = 0;
323 backends = gensec_security_mechs(gensec_security, mem_ctx);
325 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
329 backends_out[0] = NULL;
331 /* Find backends in our preferred order, by walking our list,
332 * then looking in the supplied list */
333 for (i=0; backends && backends[i]; i++) {
334 if (gensec_security != NULL &&
335 !gensec_security_ops_enabled(backends[i], gensec_security))
337 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
338 if (!backends[i]->sasl_name ||
339 !(strcmp(backends[i]->sasl_name,
340 sasl_names[sasl_idx]) == 0)) {
344 for (k=0; backends_out[k]; k++) {
345 if (backends_out[k] == backends[i]) {
350 if (k < num_backends_out) {
351 /* already in there */
355 backends_out = talloc_realloc(mem_ctx, backends_out,
356 const struct gensec_security_ops *,
357 num_backends_out + 2);
362 backends_out[num_backends_out] = backends[i];
364 backends_out[num_backends_out] = NULL;
371 * Return a unique list of security subsystems from those specified in
372 * the OID list. That is, where two OIDs refer to the same module,
373 * return that module only once.
375 * Use the list of enabled GENSEC mechanisms from the credentials
376 * attached to the gensec_security, and return in our preferred order.
379 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
380 struct gensec_security *gensec_security,
382 const char **oid_strings,
385 struct gensec_security_ops_wrapper *backends_out;
386 struct gensec_security_ops **backends;
387 int i, j, k, oid_idx;
388 int num_backends_out = 0;
394 backends = gensec_security_mechs(gensec_security, gensec_security);
396 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
400 backends_out[0].op = NULL;
401 backends_out[0].oid = NULL;
403 /* Find backends in our preferred order, by walking our list,
404 * then looking in the supplied list */
405 for (i=0; backends && backends[i]; i++) {
406 if (gensec_security != NULL &&
407 !gensec_security_ops_enabled(backends[i], gensec_security))
409 if (!backends[i]->oid) {
412 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
413 if (strcmp(oid_strings[oid_idx], skip) == 0) {
417 for (j=0; backends[i]->oid[j]; j++) {
418 if (!backends[i]->oid[j] ||
419 !(strcmp(backends[i]->oid[j],
420 oid_strings[oid_idx]) == 0)) {
424 for (k=0; backends_out[k].op; k++) {
425 if (backends_out[k].op == backends[i]) {
430 if (k < num_backends_out) {
431 /* already in there */
435 backends_out = talloc_realloc(mem_ctx, backends_out,
436 struct gensec_security_ops_wrapper,
437 num_backends_out + 2);
442 backends_out[num_backends_out].op = backends[i];
443 backends_out[num_backends_out].oid = backends[i]->oid[j];
445 backends_out[num_backends_out].op = NULL;
446 backends_out[num_backends_out].oid = NULL;
454 * Return OIDS from the security subsystems listed
457 static const char **gensec_security_oids_from_ops(
458 struct gensec_security *gensec_security,
460 struct gensec_security_ops **ops,
466 const char **oid_list;
470 oid_list = talloc_array(mem_ctx, const char *, 1);
475 for (i=0; ops && ops[i]; i++) {
476 if (gensec_security != NULL &&
477 !gensec_security_ops_enabled(ops[i], gensec_security)) {
484 for (k = 0; ops[i]->oid[k]; k++) {
485 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
487 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
491 oid_list[j] = ops[i]->oid[k];
502 * Return OIDS from the security subsystems listed
505 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
506 const struct gensec_security_ops_wrapper *wops)
511 const char **oid_list;
515 oid_list = talloc_array(mem_ctx, const char *, 1);
520 for (i=0; wops[i].op; i++) {
521 if (!wops[i].op->oid) {
525 for (k = 0; wops[i].op->oid[k]; k++) {
526 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
530 oid_list[j] = wops[i].op->oid[k];
540 * Return all the security subsystems currently enabled on a GENSEC context.
542 * This is taken from a list attached to the cli_credentials, and
543 * skips the OID in 'skip'. (Typically the SPNEGO OID)
547 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
551 struct gensec_security_ops **ops
552 = gensec_security_mechs(gensec_security, mem_ctx);
553 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
557 Start the GENSEC system, returning a context pointer.
558 @param mem_ctx The parent TALLOC memory context.
559 @param gensec_security Returned GENSEC context pointer.
560 @note The mem_ctx is only a parent and may be NULL.
561 @note, the auth context is moved to be a referenced pointer of the
562 @ gensec_security return
564 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
565 struct gensec_settings *settings,
566 struct auth4_context *auth_context,
567 struct gensec_security **gensec_security)
569 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
570 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
572 (*gensec_security)->max_update_size = 0;
574 SMB_ASSERT(settings->lp_ctx != NULL);
575 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
577 /* We need to reference this, not steal, as the caller may be
578 * python, which won't like it if we steal it's object away
580 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
586 * Start a GENSEC subcontext, with a copy of the properties of the parent
587 * @param mem_ctx The parent TALLOC memory context.
588 * @param parent The parent GENSEC context
589 * @param gensec_security Returned GENSEC context pointer.
590 * @note Used by SPNEGO in particular, for the actual implementation mechanism
593 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
594 struct gensec_security *parent,
595 struct gensec_security **gensec_security)
597 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
598 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
600 (**gensec_security) = *parent;
601 (*gensec_security)->ops = NULL;
602 (*gensec_security)->private_data = NULL;
604 (*gensec_security)->subcontext = true;
605 (*gensec_security)->want_features = parent->want_features;
606 (*gensec_security)->max_update_size = parent->max_update_size;
607 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
608 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
609 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
610 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
616 Start the GENSEC system, in client mode, returning a context pointer.
617 @param mem_ctx The parent TALLOC memory context.
618 @param gensec_security Returned GENSEC context pointer.
619 @note The mem_ctx is only a parent and may be NULL.
621 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
622 struct gensec_security **gensec_security,
623 struct gensec_settings *settings)
627 if (settings == NULL) {
628 DEBUG(0,("gensec_client_start: no settings given!\n"));
629 return NT_STATUS_INTERNAL_ERROR;
632 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
633 if (!NT_STATUS_IS_OK(status)) {
636 (*gensec_security)->gensec_role = GENSEC_CLIENT;
644 Start the GENSEC system, in server mode, returning a context pointer.
645 @param mem_ctx The parent TALLOC memory context.
646 @param gensec_security Returned GENSEC context pointer.
647 @note The mem_ctx is only a parent and may be NULL.
649 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
650 struct gensec_settings *settings,
651 struct auth4_context *auth_context,
652 struct gensec_security **gensec_security)
657 DEBUG(0,("gensec_server_start: no settings given!\n"));
658 return NT_STATUS_INTERNAL_ERROR;
661 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
662 if (!NT_STATUS_IS_OK(status)) {
665 (*gensec_security)->gensec_role = GENSEC_SERVER;
670 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
673 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
674 gensec_security->subcontext ? "sub" : "",
675 gensec_security->ops->name));
676 switch (gensec_security->gensec_role) {
678 if (gensec_security->ops->client_start) {
679 status = gensec_security->ops->client_start(gensec_security);
680 if (!NT_STATUS_IS_OK(status)) {
681 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
682 gensec_security->ops->name, nt_errstr(status)));
688 if (gensec_security->ops->server_start) {
689 status = gensec_security->ops->server_start(gensec_security);
690 if (!NT_STATUS_IS_OK(status)) {
691 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
692 gensec_security->ops->name, nt_errstr(status)));
698 return NT_STATUS_INVALID_PARAMETER;
702 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
706 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
707 const struct gensec_security_ops *ops)
709 gensec_security->ops = ops;
710 return gensec_start_mech(gensec_security);
715 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
716 * @param gensec_security GENSEC context pointer.
717 * @param auth_type DCERPC auth type
718 * @param auth_level DCERPC auth level
721 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
722 uint8_t auth_type, uint8_t auth_level)
724 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
725 if (!gensec_security->ops) {
726 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
727 return NT_STATUS_INVALID_PARAMETER;
729 gensec_security->dcerpc_auth_level = auth_level;
730 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
731 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
732 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
733 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
734 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
735 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
736 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
737 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
738 /* Default features */
740 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
742 return NT_STATUS_INVALID_PARAMETER;
745 return gensec_start_mech(gensec_security);
748 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
750 const struct gensec_security_ops *ops;
751 ops = gensec_security_by_authtype(gensec_security, authtype);
759 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
760 const char *oid_string)
762 const struct gensec_security_ops *ops;
763 ops = gensec_security_by_oid(gensec_security, oid_string);
771 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
773 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
774 * well-known #define to hook it in.
777 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
778 const char *mech_oid)
780 SMB_ASSERT(gensec_security != NULL);
782 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
783 if (!gensec_security->ops) {
784 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
785 return NT_STATUS_INVALID_PARAMETER;
787 return gensec_start_mech(gensec_security);
791 * Start a GENSEC sub-mechanism by a well know SASL name
795 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
796 const char *sasl_name)
798 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
799 if (!gensec_security->ops) {
800 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
801 return NT_STATUS_INVALID_PARAMETER;
803 return gensec_start_mech(gensec_security);
807 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
811 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
812 const char **sasl_names)
814 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
815 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
816 const struct gensec_security_ops **ops;
819 return NT_STATUS_NO_MEMORY;
821 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
823 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
824 str_list_join(mem_ctx,
826 talloc_free(mem_ctx);
827 return NT_STATUS_INVALID_PARAMETER;
829 for (i=0; ops[i]; i++) {
830 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
831 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
835 talloc_free(mem_ctx);
840 * Start a GENSEC sub-mechanism by an internal name
844 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
847 gensec_security->ops = gensec_security_by_name(gensec_security, name);
848 if (!gensec_security->ops) {
849 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
850 return NT_STATUS_INVALID_PARAMETER;
852 return gensec_start_mech(gensec_security);
856 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
860 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
862 gensec_security->credentials = talloc_reference(gensec_security, credentials);
863 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
864 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
869 register a GENSEC backend.
871 The 'name' can be later used by other backends to find the operations
872 structure for this backend.
874 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
876 if (gensec_security_by_name(NULL, ops->name) != NULL) {
877 /* its already registered! */
878 DEBUG(0,("GENSEC backend '%s' already registered\n",
880 return NT_STATUS_OBJECT_NAME_COLLISION;
883 generic_security_ops = talloc_realloc(talloc_autofree_context(),
884 generic_security_ops,
885 struct gensec_security_ops *,
886 gensec_num_backends+2);
887 if (!generic_security_ops) {
888 return NT_STATUS_NO_MEMORY;
891 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
892 gensec_num_backends++;
893 generic_security_ops[gensec_num_backends] = NULL;
895 DEBUG(3,("GENSEC backend '%s' registered\n",
902 return the GENSEC interface version, and the size of some critical types
903 This can be used by backends to either detect compilation errors, or provide
904 multiple implementations for different smbd compilation options in one module
906 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
908 static const struct gensec_critical_sizes critical_sizes = {
909 GENSEC_INTERFACE_VERSION,
910 sizeof(struct gensec_security_ops),
911 sizeof(struct gensec_security),
914 return &critical_sizes;
917 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
918 return (*gs2)->priority - (*gs1)->priority;
921 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
923 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
926 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
928 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
932 initialise the GENSEC subsystem
934 _PUBLIC_ NTSTATUS gensec_init(void)
936 static bool initialized = false;
937 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
938 #ifdef STATIC_gensec_MODULES
939 STATIC_gensec_MODULES_PROTO;
940 init_module_fn static_init[] = { STATIC_gensec_MODULES };
942 init_module_fn *static_init = NULL;
944 init_module_fn *shared_init;
946 if (initialized) return NT_STATUS_OK;
949 shared_init = load_samba_modules(NULL, "gensec");
951 run_init_functions(static_init);
952 run_init_functions(shared_init);
954 talloc_free(shared_init);
956 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);