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"
25 #include "lib/events/events.h"
26 #include "lib/socket/socket.h"
27 #include "lib/tsocket/tsocket.h"
28 #include "../lib/util/tevent_ntstatus.h"
29 #include "librpc/rpc/dcerpc.h"
30 #include "auth/credentials/credentials.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/gensec/gensec_proto.h"
33 #include "auth/auth.h"
34 #include "auth/system_session_proto.h"
35 #include "param/param.h"
36 #include "lib/util/tsort.h"
37 #include "auth/gensec/gensec_toplevel_proto.h"
38 #include "lib/util/samba_modules.h"
40 /* the list of currently registered GENSEC backends */
41 static struct gensec_security_ops **generic_security_ops;
42 static int gensec_num_backends;
44 /* Return all the registered mechs. Don't modify the return pointer,
45 * but you may talloc_reference it if convient */
46 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
48 return generic_security_ops;
51 bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security)
53 return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled);
56 /* Sometimes we want to force only kerberos, sometimes we want to
57 * force it's avoidance. The old list could be either
58 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
59 * an existing list we have trimmed down) */
61 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
62 struct gensec_security_ops **old_gensec_list,
63 struct cli_credentials *creds)
65 struct gensec_security_ops **new_gensec_list;
66 int i, j, num_mechs_in;
67 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
70 use_kerberos = cli_credentials_get_kerberos_state(creds);
73 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
74 if (!talloc_reference(mem_ctx, old_gensec_list)) {
77 return old_gensec_list;
80 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
84 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
85 if (!new_gensec_list) {
90 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
93 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
94 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
95 new_gensec_list[j] = old_gensec_list[i];
100 switch (use_kerberos) {
101 case CRED_DONT_USE_KERBEROS:
102 if (old_gensec_list[i]->kerberos == false) {
103 new_gensec_list[j] = old_gensec_list[i];
107 case CRED_MUST_USE_KERBEROS:
108 if (old_gensec_list[i]->kerberos == true) {
109 new_gensec_list[j] = old_gensec_list[i];
114 /* Can't happen or invalid parameter */
118 new_gensec_list[j] = NULL;
120 return new_gensec_list;
123 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
126 struct gensec_security_ops **backends;
127 backends = gensec_security_all();
128 if (!gensec_security) {
129 if (!talloc_reference(mem_ctx, backends)) {
134 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
136 if (!talloc_reference(mem_ctx, backends)) {
141 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
145 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
149 struct gensec_security_ops **backends;
150 const struct gensec_security_ops *backend;
151 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
155 backends = gensec_security_mechs(gensec_security, mem_ctx);
156 for (i=0; backends && backends[i]; i++) {
157 if (!gensec_security_ops_enabled(backends[i], gensec_security))
159 if (backends[i]->auth_type == auth_type) {
160 backend = backends[i];
161 talloc_free(mem_ctx);
165 talloc_free(mem_ctx);
170 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
171 const char *oid_string)
174 struct gensec_security_ops **backends;
175 const struct gensec_security_ops *backend;
176 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
180 backends = gensec_security_mechs(gensec_security, mem_ctx);
181 for (i=0; backends && backends[i]; i++) {
182 if (gensec_security != NULL &&
183 !gensec_security_ops_enabled(backends[i],
186 if (backends[i]->oid) {
187 for (j=0; backends[i]->oid[j]; j++) {
188 if (backends[i]->oid[j] &&
189 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
190 backend = backends[i];
191 talloc_free(mem_ctx);
197 talloc_free(mem_ctx);
202 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
203 const char *sasl_name)
206 struct gensec_security_ops **backends;
207 const struct gensec_security_ops *backend;
208 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
212 backends = gensec_security_mechs(gensec_security, mem_ctx);
213 for (i=0; backends && backends[i]; i++) {
214 if (!gensec_security_ops_enabled(backends[i], gensec_security))
216 if (backends[i]->sasl_name
217 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
218 backend = backends[i];
219 talloc_free(mem_ctx);
223 talloc_free(mem_ctx);
228 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
232 struct gensec_security_ops **backends;
233 const struct gensec_security_ops *backend;
234 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
238 backends = gensec_security_mechs(gensec_security, mem_ctx);
239 for (i=0; backends && backends[i]; i++) {
240 if (gensec_security != NULL &&
241 !gensec_security_ops_enabled(backends[i], gensec_security))
243 if (backends[i]->name
244 && (strcmp(backends[i]->name, name) == 0)) {
245 backend = backends[i];
246 talloc_free(mem_ctx);
250 talloc_free(mem_ctx);
255 * Return a unique list of security subsystems from those specified in
256 * the list of SASL names.
258 * Use the list of enabled GENSEC mechanisms from the credentials
259 * attached to the gensec_security, and return in our preferred order.
262 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
264 const char **sasl_names)
266 const struct gensec_security_ops **backends_out;
267 struct gensec_security_ops **backends;
269 int num_backends_out = 0;
275 backends = gensec_security_mechs(gensec_security, mem_ctx);
277 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
281 backends_out[0] = NULL;
283 /* Find backends in our preferred order, by walking our list,
284 * then looking in the supplied list */
285 for (i=0; backends && backends[i]; i++) {
286 if (gensec_security != NULL &&
287 !gensec_security_ops_enabled(backends[i], gensec_security))
289 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
290 if (!backends[i]->sasl_name ||
291 !(strcmp(backends[i]->sasl_name,
292 sasl_names[sasl_idx]) == 0)) {
296 for (k=0; backends_out[k]; k++) {
297 if (backends_out[k] == backends[i]) {
302 if (k < num_backends_out) {
303 /* already in there */
307 backends_out = talloc_realloc(mem_ctx, backends_out,
308 const struct gensec_security_ops *,
309 num_backends_out + 2);
314 backends_out[num_backends_out] = backends[i];
316 backends_out[num_backends_out] = NULL;
323 * Return a unique list of security subsystems from those specified in
324 * the OID list. That is, where two OIDs refer to the same module,
325 * return that module only once.
327 * Use the list of enabled GENSEC mechanisms from the credentials
328 * attached to the gensec_security, and return in our preferred order.
331 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
333 const char **oid_strings,
336 struct gensec_security_ops_wrapper *backends_out;
337 struct gensec_security_ops **backends;
338 int i, j, k, oid_idx;
339 int num_backends_out = 0;
345 backends = gensec_security_mechs(gensec_security, gensec_security);
347 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
351 backends_out[0].op = NULL;
352 backends_out[0].oid = NULL;
354 /* Find backends in our preferred order, by walking our list,
355 * then looking in the supplied list */
356 for (i=0; backends && backends[i]; i++) {
357 if (gensec_security != NULL &&
358 !gensec_security_ops_enabled(backends[i], gensec_security))
360 if (!backends[i]->oid) {
363 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
364 if (strcmp(oid_strings[oid_idx], skip) == 0) {
368 for (j=0; backends[i]->oid[j]; j++) {
369 if (!backends[i]->oid[j] ||
370 !(strcmp(backends[i]->oid[j],
371 oid_strings[oid_idx]) == 0)) {
375 for (k=0; backends_out[k].op; k++) {
376 if (backends_out[k].op == backends[i]) {
381 if (k < num_backends_out) {
382 /* already in there */
386 backends_out = talloc_realloc(mem_ctx, backends_out,
387 struct gensec_security_ops_wrapper,
388 num_backends_out + 2);
393 backends_out[num_backends_out].op = backends[i];
394 backends_out[num_backends_out].oid = backends[i]->oid[j];
396 backends_out[num_backends_out].op = NULL;
397 backends_out[num_backends_out].oid = NULL;
405 * Return OIDS from the security subsystems listed
408 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
410 struct gensec_security_ops **ops,
416 const char **oid_list;
420 oid_list = talloc_array(mem_ctx, const char *, 1);
425 for (i=0; ops && ops[i]; i++) {
426 if (gensec_security != NULL &&
427 !gensec_security_ops_enabled(ops[i], gensec_security)) {
434 for (k = 0; ops[i]->oid[k]; k++) {
435 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
437 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
441 oid_list[j] = ops[i]->oid[k];
452 * Return OIDS from the security subsystems listed
455 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
456 const struct gensec_security_ops_wrapper *wops)
461 const char **oid_list;
465 oid_list = talloc_array(mem_ctx, const char *, 1);
470 for (i=0; wops[i].op; i++) {
471 if (!wops[i].op->oid) {
475 for (k = 0; wops[i].op->oid[k]; k++) {
476 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
480 oid_list[j] = wops[i].op->oid[k];
490 * Return all the security subsystems currently enabled on a GENSEC context.
492 * This is taken from a list attached to the cli_credentials, and
493 * skips the OID in 'skip'. (Typically the SPNEGO OID)
497 const char **gensec_security_oids(struct gensec_security *gensec_security,
501 struct gensec_security_ops **ops
502 = gensec_security_mechs(gensec_security, mem_ctx);
503 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
507 Start the GENSEC system, returning a context pointer.
508 @param mem_ctx The parent TALLOC memory context.
509 @param gensec_security Returned GENSEC context pointer.
510 @note The mem_ctx is only a parent and may be NULL.
511 @note, the auth context is moved to be a referenced pointer of the
512 @ gensec_security return
514 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
515 struct tevent_context *ev,
516 struct gensec_settings *settings,
517 struct auth4_context *auth_context,
518 struct gensec_security **gensec_security)
521 DEBUG(0, ("No event context available!\n"));
522 return NT_STATUS_INTERNAL_ERROR;
525 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
526 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
528 (*gensec_security)->event_ctx = ev;
529 SMB_ASSERT(settings->lp_ctx != NULL);
530 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
532 /* We need to reference this, not steal, as the caller may be
533 * python, which won't like it if we steal it's object away
535 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
541 * Start a GENSEC subcontext, with a copy of the properties of the parent
542 * @param mem_ctx The parent TALLOC memory context.
543 * @param parent The parent GENSEC context
544 * @param gensec_security Returned GENSEC context pointer.
545 * @note Used by SPNEGO in particular, for the actual implementation mechanism
548 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
549 struct gensec_security *parent,
550 struct gensec_security **gensec_security)
552 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
553 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
555 (**gensec_security) = *parent;
556 (*gensec_security)->ops = NULL;
557 (*gensec_security)->private_data = NULL;
559 (*gensec_security)->subcontext = true;
560 (*gensec_security)->want_features = parent->want_features;
561 (*gensec_security)->event_ctx = parent->event_ctx;
562 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
563 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
564 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
570 Start the GENSEC system, in client mode, returning a context pointer.
571 @param mem_ctx The parent TALLOC memory context.
572 @param gensec_security Returned GENSEC context pointer.
573 @note The mem_ctx is only a parent and may be NULL.
575 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
576 struct gensec_security **gensec_security,
577 struct tevent_context *ev,
578 struct gensec_settings *settings)
582 if (settings == NULL) {
583 DEBUG(0,("gensec_client_start: no settings given!\n"));
584 return NT_STATUS_INTERNAL_ERROR;
587 status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
588 if (!NT_STATUS_IS_OK(status)) {
591 (*gensec_security)->gensec_role = GENSEC_CLIENT;
599 Start the GENSEC system, in server mode, returning a context pointer.
600 @param mem_ctx The parent TALLOC memory context.
601 @param gensec_security Returned GENSEC context pointer.
602 @note The mem_ctx is only a parent and may be NULL.
604 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
605 struct tevent_context *ev,
606 struct gensec_settings *settings,
607 struct auth4_context *auth_context,
608 struct gensec_security **gensec_security)
613 DEBUG(0,("gensec_server_start: no event context given!\n"));
614 return NT_STATUS_INTERNAL_ERROR;
618 DEBUG(0,("gensec_server_start: no settings given!\n"));
619 return NT_STATUS_INTERNAL_ERROR;
622 status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
623 if (!NT_STATUS_IS_OK(status)) {
626 (*gensec_security)->gensec_role = GENSEC_SERVER;
631 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
634 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
635 gensec_security->subcontext ? "sub" : "",
636 gensec_security->ops->name));
637 switch (gensec_security->gensec_role) {
639 if (gensec_security->ops->client_start) {
640 status = gensec_security->ops->client_start(gensec_security);
641 if (!NT_STATUS_IS_OK(status)) {
642 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
643 gensec_security->ops->name, nt_errstr(status)));
649 if (gensec_security->ops->server_start) {
650 status = gensec_security->ops->server_start(gensec_security);
651 if (!NT_STATUS_IS_OK(status)) {
652 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
653 gensec_security->ops->name, nt_errstr(status)));
659 return NT_STATUS_INVALID_PARAMETER;
663 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
667 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
668 const struct gensec_security_ops *ops)
670 gensec_security->ops = ops;
671 return gensec_start_mech(gensec_security);
676 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
677 * @param gensec_security GENSEC context pointer.
678 * @param auth_type DCERPC auth type
679 * @param auth_level DCERPC auth level
682 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
683 uint8_t auth_type, uint8_t auth_level)
685 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
686 if (!gensec_security->ops) {
687 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
688 return NT_STATUS_INVALID_PARAMETER;
690 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
691 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
692 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
693 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
694 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
695 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
696 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
697 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
698 /* Default features */
700 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
702 return NT_STATUS_INVALID_PARAMETER;
705 return gensec_start_mech(gensec_security);
708 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
710 const struct gensec_security_ops *ops;
711 ops = gensec_security_by_authtype(gensec_security, authtype);
719 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
720 const char *oid_string)
722 const struct gensec_security_ops *ops;
723 ops = gensec_security_by_oid(gensec_security, oid_string);
731 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
733 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
734 * well-known #define to hook it in.
737 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
738 const char *mech_oid)
740 SMB_ASSERT(gensec_security != NULL);
742 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
743 if (!gensec_security->ops) {
744 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
745 return NT_STATUS_INVALID_PARAMETER;
747 return gensec_start_mech(gensec_security);
751 * Start a GENSEC sub-mechanism by a well know SASL name
755 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
756 const char *sasl_name)
758 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
759 if (!gensec_security->ops) {
760 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
761 return NT_STATUS_INVALID_PARAMETER;
763 return gensec_start_mech(gensec_security);
767 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
771 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
772 const char **sasl_names)
774 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
775 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
776 const struct gensec_security_ops **ops;
779 return NT_STATUS_NO_MEMORY;
781 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
783 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
784 str_list_join(mem_ctx,
786 talloc_free(mem_ctx);
787 return NT_STATUS_INVALID_PARAMETER;
789 for (i=0; ops[i]; i++) {
790 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
791 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
795 talloc_free(mem_ctx);
800 * Start a GENSEC sub-mechanism by an internal name
804 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
807 gensec_security->ops = gensec_security_by_name(gensec_security, name);
808 if (!gensec_security->ops) {
809 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
810 return NT_STATUS_INVALID_PARAMETER;
812 return gensec_start_mech(gensec_security);
816 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
820 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
822 gensec_security->credentials = talloc_reference(gensec_security, credentials);
823 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
824 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
828 NTSTATUS gensec_generate_session_info(TALLOC_CTX *mem_ctx,
829 struct gensec_security *gensec_security,
830 struct auth_user_info_dc *user_info_dc,
831 struct auth_session_info **session_info)
834 uint32_t session_info_flags = 0;
836 if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
837 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
840 session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
841 if (user_info_dc->info->authenticated) {
842 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
845 if (gensec_security->auth_context) {
846 nt_status = gensec_security->auth_context->generate_session_info(mem_ctx, gensec_security->auth_context,
851 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
852 nt_status = auth_generate_session_info(mem_ctx,
855 user_info_dc, session_info_flags,
862 register a GENSEC backend.
864 The 'name' can be later used by other backends to find the operations
865 structure for this backend.
867 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
869 if (gensec_security_by_name(NULL, ops->name) != NULL) {
870 /* its already registered! */
871 DEBUG(0,("GENSEC backend '%s' already registered\n",
873 return NT_STATUS_OBJECT_NAME_COLLISION;
876 generic_security_ops = talloc_realloc(talloc_autofree_context(),
877 generic_security_ops,
878 struct gensec_security_ops *,
879 gensec_num_backends+2);
880 if (!generic_security_ops) {
881 return NT_STATUS_NO_MEMORY;
884 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
885 gensec_num_backends++;
886 generic_security_ops[gensec_num_backends] = NULL;
888 DEBUG(3,("GENSEC backend '%s' registered\n",
895 return the GENSEC interface version, and the size of some critical types
896 This can be used by backends to either detect compilation errors, or provide
897 multiple implementations for different smbd compilation options in one module
899 const struct gensec_critical_sizes *gensec_interface_version(void)
901 static const struct gensec_critical_sizes critical_sizes = {
902 GENSEC_INTERFACE_VERSION,
903 sizeof(struct gensec_security_ops),
904 sizeof(struct gensec_security),
907 return &critical_sizes;
910 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
911 return (*gs2)->priority - (*gs1)->priority;
914 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
916 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
919 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
921 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
925 initialise the GENSEC subsystem
927 _PUBLIC_ NTSTATUS gensec_init(void)
929 static bool initialized = false;
930 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
931 STATIC_gensec_MODULES_PROTO;
932 init_module_fn static_init[] = { STATIC_gensec_MODULES };
933 init_module_fn *shared_init;
935 if (initialized) return NT_STATUS_OK;
938 shared_init = load_samba_modules(NULL, "gensec");
940 run_init_functions(static_init);
941 run_init_functions(shared_init);
943 talloc_free(shared_init);
945 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);