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 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
84 if (!talloc_reference(mem_ctx, old_gensec_list)) {
87 return old_gensec_list;
90 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
94 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
95 if (!new_gensec_list) {
100 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
102 bool found_spnego = false;
103 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
104 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
105 new_gensec_list[j] = old_gensec_list[i];
114 switch (use_kerberos) {
115 case CRED_DONT_USE_KERBEROS:
116 if (old_gensec_list[i]->kerberos == false) {
117 new_gensec_list[j] = old_gensec_list[i];
121 case CRED_MUST_USE_KERBEROS:
122 if (old_gensec_list[i]->kerberos == true) {
123 new_gensec_list[j] = old_gensec_list[i];
128 /* Can't happen or invalid parameter */
132 new_gensec_list[j] = NULL;
134 return new_gensec_list;
137 _PUBLIC_ struct gensec_security_ops **gensec_security_mechs(
138 struct gensec_security *gensec_security,
141 struct gensec_security_ops **backends;
142 if (!gensec_security) {
143 backends = gensec_security_all();
144 if (!talloc_reference(mem_ctx, backends)) {
149 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
150 if (gensec_security->settings->backends) {
151 backends = gensec_security->settings->backends;
153 backends = gensec_security_all();
156 if (!talloc_reference(mem_ctx, backends)) {
161 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
165 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
169 struct gensec_security_ops **backends;
170 const struct gensec_security_ops *backend;
171 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
175 backends = gensec_security_mechs(gensec_security, mem_ctx);
176 for (i=0; backends && backends[i]; i++) {
177 if (!gensec_security_ops_enabled(backends[i], gensec_security))
179 if (backends[i]->auth_type == auth_type) {
180 backend = backends[i];
181 talloc_free(mem_ctx);
185 talloc_free(mem_ctx);
190 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
191 struct gensec_security *gensec_security,
192 const char *oid_string)
195 struct gensec_security_ops **backends;
196 const struct gensec_security_ops *backend;
197 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
201 backends = gensec_security_mechs(gensec_security, mem_ctx);
202 for (i=0; backends && backends[i]; i++) {
203 if (gensec_security != NULL &&
204 !gensec_security_ops_enabled(backends[i],
207 if (backends[i]->oid) {
208 for (j=0; backends[i]->oid[j]; j++) {
209 if (backends[i]->oid[j] &&
210 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
211 backend = backends[i];
212 talloc_free(mem_ctx);
218 talloc_free(mem_ctx);
223 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
224 struct gensec_security *gensec_security,
225 const char *sasl_name)
228 struct gensec_security_ops **backends;
229 const struct gensec_security_ops *backend;
230 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
234 backends = gensec_security_mechs(gensec_security, mem_ctx);
235 for (i=0; backends && backends[i]; i++) {
236 if (!gensec_security_ops_enabled(backends[i], gensec_security))
238 if (backends[i]->sasl_name
239 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
240 backend = backends[i];
241 talloc_free(mem_ctx);
245 talloc_free(mem_ctx);
250 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
251 struct gensec_security *gensec_security,
255 struct gensec_security_ops **backends;
256 const struct gensec_security_ops *backend;
257 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
261 backends = gensec_security_mechs(gensec_security, mem_ctx);
262 for (i=0; backends && backends[i]; i++) {
263 if (!gensec_security_ops_enabled(backends[i], gensec_security))
265 if (backends[i]->auth_type == auth_type) {
266 backend = backends[i];
267 talloc_free(mem_ctx);
271 talloc_free(mem_ctx);
276 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
280 struct gensec_security_ops **backends;
281 const struct gensec_security_ops *backend;
282 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
286 backends = gensec_security_mechs(gensec_security, mem_ctx);
287 for (i=0; backends && backends[i]; i++) {
288 if (gensec_security != NULL &&
289 !gensec_security_ops_enabled(backends[i], gensec_security))
291 if (backends[i]->name
292 && (strcmp(backends[i]->name, name) == 0)) {
293 backend = backends[i];
294 talloc_free(mem_ctx);
298 talloc_free(mem_ctx);
303 * Return a unique list of security subsystems from those specified in
304 * the list of SASL names.
306 * Use the list of enabled GENSEC mechanisms from the credentials
307 * attached to the gensec_security, and return in our preferred order.
310 static const struct gensec_security_ops **gensec_security_by_sasl_list(
311 struct gensec_security *gensec_security,
313 const char **sasl_names)
315 const struct gensec_security_ops **backends_out;
316 struct gensec_security_ops **backends;
318 int num_backends_out = 0;
324 backends = gensec_security_mechs(gensec_security, mem_ctx);
326 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
330 backends_out[0] = NULL;
332 /* Find backends in our preferred order, by walking our list,
333 * then looking in the supplied list */
334 for (i=0; backends && backends[i]; i++) {
335 if (gensec_security != NULL &&
336 !gensec_security_ops_enabled(backends[i], gensec_security))
338 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
339 if (!backends[i]->sasl_name ||
340 !(strcmp(backends[i]->sasl_name,
341 sasl_names[sasl_idx]) == 0)) {
345 for (k=0; backends_out[k]; k++) {
346 if (backends_out[k] == backends[i]) {
351 if (k < num_backends_out) {
352 /* already in there */
356 backends_out = talloc_realloc(mem_ctx, backends_out,
357 const struct gensec_security_ops *,
358 num_backends_out + 2);
363 backends_out[num_backends_out] = backends[i];
365 backends_out[num_backends_out] = NULL;
372 * Return a unique list of security subsystems from those specified in
373 * the OID list. That is, where two OIDs refer to the same module,
374 * return that module only once.
376 * Use the list of enabled GENSEC mechanisms from the credentials
377 * attached to the gensec_security, and return in our preferred order.
380 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
381 struct gensec_security *gensec_security,
383 const char **oid_strings,
386 struct gensec_security_ops_wrapper *backends_out;
387 struct gensec_security_ops **backends;
388 int i, j, k, oid_idx;
389 int num_backends_out = 0;
395 backends = gensec_security_mechs(gensec_security, gensec_security);
397 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
401 backends_out[0].op = NULL;
402 backends_out[0].oid = NULL;
404 /* Find backends in our preferred order, by walking our list,
405 * then looking in the supplied list */
406 for (i=0; backends && backends[i]; i++) {
407 if (gensec_security != NULL &&
408 !gensec_security_ops_enabled(backends[i], gensec_security))
410 if (!backends[i]->oid) {
413 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
414 if (strcmp(oid_strings[oid_idx], skip) == 0) {
418 for (j=0; backends[i]->oid[j]; j++) {
419 if (!backends[i]->oid[j] ||
420 !(strcmp(backends[i]->oid[j],
421 oid_strings[oid_idx]) == 0)) {
425 for (k=0; backends_out[k].op; k++) {
426 if (backends_out[k].op == backends[i]) {
431 if (k < num_backends_out) {
432 /* already in there */
436 backends_out = talloc_realloc(mem_ctx, backends_out,
437 struct gensec_security_ops_wrapper,
438 num_backends_out + 2);
443 backends_out[num_backends_out].op = backends[i];
444 backends_out[num_backends_out].oid = backends[i]->oid[j];
446 backends_out[num_backends_out].op = NULL;
447 backends_out[num_backends_out].oid = NULL;
455 * Return OIDS from the security subsystems listed
458 static const char **gensec_security_oids_from_ops(
459 struct gensec_security *gensec_security,
461 struct gensec_security_ops **ops,
467 const char **oid_list;
471 oid_list = talloc_array(mem_ctx, const char *, 1);
476 for (i=0; ops && ops[i]; i++) {
477 if (gensec_security != NULL &&
478 !gensec_security_ops_enabled(ops[i], gensec_security)) {
485 for (k = 0; ops[i]->oid[k]; k++) {
486 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
488 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
492 oid_list[j] = ops[i]->oid[k];
503 * Return OIDS from the security subsystems listed
506 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
507 const struct gensec_security_ops_wrapper *wops)
512 const char **oid_list;
516 oid_list = talloc_array(mem_ctx, const char *, 1);
521 for (i=0; wops[i].op; i++) {
522 if (!wops[i].op->oid) {
526 for (k = 0; wops[i].op->oid[k]; k++) {
527 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
531 oid_list[j] = wops[i].op->oid[k];
541 * Return all the security subsystems currently enabled on a GENSEC context.
543 * This is taken from a list attached to the cli_credentials, and
544 * skips the OID in 'skip'. (Typically the SPNEGO OID)
548 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
552 struct gensec_security_ops **ops
553 = gensec_security_mechs(gensec_security, mem_ctx);
554 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
558 Start the GENSEC system, returning a context pointer.
559 @param mem_ctx The parent TALLOC memory context.
560 @param gensec_security Returned GENSEC context pointer.
561 @note The mem_ctx is only a parent and may be NULL.
562 @note, the auth context is moved to be a referenced pointer of the
563 @ gensec_security return
565 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
566 struct gensec_settings *settings,
567 struct auth4_context *auth_context,
568 struct gensec_security **gensec_security)
570 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
571 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
573 (*gensec_security)->max_update_size = 0;
575 SMB_ASSERT(settings->lp_ctx != NULL);
576 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
578 /* We need to reference this, not steal, as the caller may be
579 * python, which won't like it if we steal it's object away
581 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
587 * Start a GENSEC subcontext, with a copy of the properties of the parent
588 * @param mem_ctx The parent TALLOC memory context.
589 * @param parent The parent GENSEC context
590 * @param gensec_security Returned GENSEC context pointer.
591 * @note Used by SPNEGO in particular, for the actual implementation mechanism
594 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
595 struct gensec_security *parent,
596 struct gensec_security **gensec_security)
598 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
599 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
601 (**gensec_security) = *parent;
602 (*gensec_security)->ops = NULL;
603 (*gensec_security)->private_data = NULL;
605 (*gensec_security)->subcontext = true;
606 (*gensec_security)->want_features = parent->want_features;
607 (*gensec_security)->max_update_size = parent->max_update_size;
608 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
609 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
610 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
611 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
617 Start the GENSEC system, in client mode, returning a context pointer.
618 @param mem_ctx The parent TALLOC memory context.
619 @param gensec_security Returned GENSEC context pointer.
620 @note The mem_ctx is only a parent and may be NULL.
622 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
623 struct gensec_security **gensec_security,
624 struct gensec_settings *settings)
628 if (settings == NULL) {
629 DEBUG(0,("gensec_client_start: no settings given!\n"));
630 return NT_STATUS_INTERNAL_ERROR;
633 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
634 if (!NT_STATUS_IS_OK(status)) {
637 (*gensec_security)->gensec_role = GENSEC_CLIENT;
645 Start the GENSEC system, in server mode, returning a context pointer.
646 @param mem_ctx The parent TALLOC memory context.
647 @param gensec_security Returned GENSEC context pointer.
648 @note The mem_ctx is only a parent and may be NULL.
650 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
651 struct gensec_settings *settings,
652 struct auth4_context *auth_context,
653 struct gensec_security **gensec_security)
658 DEBUG(0,("gensec_server_start: no settings given!\n"));
659 return NT_STATUS_INTERNAL_ERROR;
662 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
663 if (!NT_STATUS_IS_OK(status)) {
666 (*gensec_security)->gensec_role = GENSEC_SERVER;
671 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
674 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
675 gensec_security->subcontext ? "sub" : "",
676 gensec_security->ops->name));
677 switch (gensec_security->gensec_role) {
679 if (gensec_security->ops->client_start) {
680 status = gensec_security->ops->client_start(gensec_security);
681 if (!NT_STATUS_IS_OK(status)) {
682 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
683 gensec_security->ops->name, nt_errstr(status)));
689 if (gensec_security->ops->server_start) {
690 status = gensec_security->ops->server_start(gensec_security);
691 if (!NT_STATUS_IS_OK(status)) {
692 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
693 gensec_security->ops->name, nt_errstr(status)));
699 return NT_STATUS_INVALID_PARAMETER;
703 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
707 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
708 const struct gensec_security_ops *ops)
710 gensec_security->ops = ops;
711 return gensec_start_mech(gensec_security);
716 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
717 * @param gensec_security GENSEC context pointer.
718 * @param auth_type DCERPC auth type
719 * @param auth_level DCERPC auth level
722 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
723 uint8_t auth_type, uint8_t auth_level)
725 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
726 if (!gensec_security->ops) {
727 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
728 return NT_STATUS_INVALID_PARAMETER;
730 gensec_security->dcerpc_auth_level = auth_level;
731 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
732 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
733 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
734 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
735 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
736 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
737 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
738 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
739 /* Default features */
741 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
743 return NT_STATUS_INVALID_PARAMETER;
746 return gensec_start_mech(gensec_security);
749 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
751 const struct gensec_security_ops *ops;
752 ops = gensec_security_by_authtype(gensec_security, authtype);
760 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
761 const char *oid_string)
763 const struct gensec_security_ops *ops;
764 ops = gensec_security_by_oid(gensec_security, oid_string);
772 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
774 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
775 * well-known #define to hook it in.
778 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
779 const char *mech_oid)
781 SMB_ASSERT(gensec_security != NULL);
783 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
784 if (!gensec_security->ops) {
785 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
786 return NT_STATUS_INVALID_PARAMETER;
788 return gensec_start_mech(gensec_security);
792 * Start a GENSEC sub-mechanism by a well know SASL name
796 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
797 const char *sasl_name)
799 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
800 if (!gensec_security->ops) {
801 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
802 return NT_STATUS_INVALID_PARAMETER;
804 return gensec_start_mech(gensec_security);
808 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
812 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
813 const char **sasl_names)
815 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
816 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
817 const struct gensec_security_ops **ops;
820 return NT_STATUS_NO_MEMORY;
822 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
824 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
825 str_list_join(mem_ctx,
827 talloc_free(mem_ctx);
828 return NT_STATUS_INVALID_PARAMETER;
830 for (i=0; ops[i]; i++) {
831 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
832 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
836 talloc_free(mem_ctx);
841 * Start a GENSEC sub-mechanism by an internal name
845 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
848 gensec_security->ops = gensec_security_by_name(gensec_security, name);
849 if (!gensec_security->ops) {
850 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
851 return NT_STATUS_INVALID_PARAMETER;
853 return gensec_start_mech(gensec_security);
857 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
861 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
863 gensec_security->credentials = talloc_reference(gensec_security, credentials);
864 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
865 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
870 register a GENSEC backend.
872 The 'name' can be later used by other backends to find the operations
873 structure for this backend.
875 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
877 if (gensec_security_by_name(NULL, ops->name) != NULL) {
878 /* its already registered! */
879 DEBUG(0,("GENSEC backend '%s' already registered\n",
881 return NT_STATUS_OBJECT_NAME_COLLISION;
884 generic_security_ops = talloc_realloc(talloc_autofree_context(),
885 generic_security_ops,
886 struct gensec_security_ops *,
887 gensec_num_backends+2);
888 if (!generic_security_ops) {
889 return NT_STATUS_NO_MEMORY;
892 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
893 gensec_num_backends++;
894 generic_security_ops[gensec_num_backends] = NULL;
896 DEBUG(3,("GENSEC backend '%s' registered\n",
903 return the GENSEC interface version, and the size of some critical types
904 This can be used by backends to either detect compilation errors, or provide
905 multiple implementations for different smbd compilation options in one module
907 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
909 static const struct gensec_critical_sizes critical_sizes = {
910 GENSEC_INTERFACE_VERSION,
911 sizeof(struct gensec_security_ops),
912 sizeof(struct gensec_security),
915 return &critical_sizes;
918 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
919 return (*gs2)->priority - (*gs1)->priority;
922 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
924 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
927 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
929 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
933 initialise the GENSEC subsystem
935 _PUBLIC_ NTSTATUS gensec_init(void)
937 static bool initialized = false;
938 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
939 #ifdef STATIC_gensec_MODULES
940 STATIC_gensec_MODULES_PROTO;
941 init_module_fn static_init[] = { STATIC_gensec_MODULES };
943 init_module_fn *static_init = NULL;
945 init_module_fn *shared_init;
947 if (initialized) return NT_STATUS_OK;
950 shared_init = load_samba_modules(NULL, "gensec");
952 run_init_functions(static_init);
953 run_init_functions(shared_init);
955 talloc_free(shared_init);
957 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);