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/gen_ndr/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 const 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_referen it if convient */
41 _PUBLIC_
const struct gensec_security_ops
* const *gensec_security_all(void)
43 return generic_security_ops
;
46 bool gensec_security_ops_enabled(const 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_
const struct gensec_security_ops
**gensec_use_kerberos_mechs(TALLOC_CTX
*mem_ctx
,
72 const struct gensec_security_ops
* const *old_gensec_list
,
73 struct cli_credentials
*creds
)
75 const 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
;
78 bool keep_schannel
= false;
81 use_kerberos
= cli_credentials_get_kerberos_state(creds
);
82 if (cli_credentials_get_netlogon_creds(creds
) != NULL
) {
87 for (num_mechs_in
=0; old_gensec_list
&& old_gensec_list
[num_mechs_in
]; num_mechs_in
++) {
91 new_gensec_list
= talloc_array(mem_ctx
,
92 const struct gensec_security_ops
*,
94 if (!new_gensec_list
) {
99 for (i
=0; old_gensec_list
&& old_gensec_list
[i
]; i
++) {
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) {
110 if (old_gensec_list
[i
]->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
111 keep
= keep_schannel
;
114 switch (use_kerberos
) {
115 case CRED_AUTO_USE_KERBEROS
:
119 case CRED_DONT_USE_KERBEROS
:
120 if (old_gensec_list
[i
]->kerberos
== false) {
126 case CRED_MUST_USE_KERBEROS
:
127 if (old_gensec_list
[i
]->kerberos
== true) {
133 /* Can't happen or invalid parameter */
141 new_gensec_list
[j
] = old_gensec_list
[i
];
144 new_gensec_list
[j
] = NULL
;
146 return new_gensec_list
;
149 _PUBLIC_
const struct gensec_security_ops
**gensec_security_mechs(
150 struct gensec_security
*gensec_security
,
153 struct cli_credentials
*creds
= NULL
;
154 const struct gensec_security_ops
* const *backends
= gensec_security_all();
156 if (gensec_security
!= NULL
) {
157 creds
= gensec_get_credentials(gensec_security
);
159 if (gensec_security
->settings
->backends
) {
160 backends
= gensec_security
->settings
->backends
;
164 return gensec_use_kerberos_mechs(mem_ctx
, backends
, creds
);
168 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_oid(
169 struct gensec_security
*gensec_security
,
170 const char *oid_string
)
173 const struct gensec_security_ops
**backends
;
174 const struct gensec_security_ops
*backend
;
175 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
179 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
180 for (i
=0; backends
&& backends
[i
]; i
++) {
181 if (gensec_security
!= NULL
&&
182 !gensec_security_ops_enabled(backends
[i
],
185 if (backends
[i
]->oid
) {
186 for (j
=0; backends
[i
]->oid
[j
]; j
++) {
187 if (backends
[i
]->oid
[j
] &&
188 (strcmp(backends
[i
]->oid
[j
], oid_string
) == 0)) {
189 backend
= backends
[i
];
190 talloc_free(mem_ctx
);
196 talloc_free(mem_ctx
);
201 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_sasl_name(
202 struct gensec_security
*gensec_security
,
203 const char *sasl_name
)
206 const 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 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_auth_type(
229 struct gensec_security
*gensec_security
,
233 const struct gensec_security_ops
**backends
;
234 const struct gensec_security_ops
*backend
;
235 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
239 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
240 for (i
=0; backends
&& backends
[i
]; i
++) {
241 if (gensec_security
!= NULL
&&
242 !gensec_security_ops_enabled(backends
[i
], gensec_security
)) {
245 if (backends
[i
]->auth_type
== auth_type
) {
246 backend
= backends
[i
];
247 talloc_free(mem_ctx
);
251 talloc_free(mem_ctx
);
256 static const struct gensec_security_ops
*gensec_security_by_name(struct gensec_security
*gensec_security
,
260 const struct gensec_security_ops
**backends
;
261 const struct gensec_security_ops
*backend
;
262 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
266 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
267 for (i
=0; backends
&& backends
[i
]; i
++) {
268 if (gensec_security
!= NULL
&&
269 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
271 if (backends
[i
]->name
272 && (strcmp(backends
[i
]->name
, name
) == 0)) {
273 backend
= backends
[i
];
274 talloc_free(mem_ctx
);
278 talloc_free(mem_ctx
);
283 * Return a unique list of security subsystems from those specified in
284 * the list of SASL names.
286 * Use the list of enabled GENSEC mechanisms from the credentials
287 * attached to the gensec_security, and return in our preferred order.
290 static const struct gensec_security_ops
**gensec_security_by_sasl_list(
291 struct gensec_security
*gensec_security
,
293 const char **sasl_names
)
295 const struct gensec_security_ops
**backends_out
;
296 const struct gensec_security_ops
**backends
;
298 int num_backends_out
= 0;
304 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
306 backends_out
= talloc_array(mem_ctx
, const struct gensec_security_ops
*, 1);
310 backends_out
[0] = NULL
;
312 /* Find backends in our preferred order, by walking our list,
313 * then looking in the supplied list */
314 for (i
=0; backends
&& backends
[i
]; i
++) {
315 if (gensec_security
!= NULL
&&
316 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
318 for (sasl_idx
= 0; sasl_names
[sasl_idx
]; sasl_idx
++) {
319 if (!backends
[i
]->sasl_name
||
320 !(strcmp(backends
[i
]->sasl_name
,
321 sasl_names
[sasl_idx
]) == 0)) {
325 for (k
=0; backends_out
[k
]; k
++) {
326 if (backends_out
[k
] == backends
[i
]) {
331 if (k
< num_backends_out
) {
332 /* already in there */
336 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
337 const struct gensec_security_ops
*,
338 num_backends_out
+ 2);
343 backends_out
[num_backends_out
] = backends
[i
];
345 backends_out
[num_backends_out
] = NULL
;
352 * Return a unique list of security subsystems from those specified in
353 * the OID list. That is, where two OIDs refer to the same module,
354 * return that module only once.
356 * Use the list of enabled GENSEC mechanisms from the credentials
357 * attached to the gensec_security, and return in our preferred order.
360 _PUBLIC_
const struct gensec_security_ops_wrapper
*gensec_security_by_oid_list(
361 struct gensec_security
*gensec_security
,
363 const char * const *oid_strings
,
366 struct gensec_security_ops_wrapper
*backends_out
;
367 const struct gensec_security_ops
**backends
;
368 int i
, j
, k
, oid_idx
;
369 int num_backends_out
= 0;
375 backends
= gensec_security_mechs(gensec_security
, gensec_security
);
377 backends_out
= talloc_array(mem_ctx
, struct gensec_security_ops_wrapper
, 1);
381 backends_out
[0].op
= NULL
;
382 backends_out
[0].oid
= NULL
;
384 /* Find backends in our preferred order, by walking our list,
385 * then looking in the supplied list */
386 for (i
=0; backends
&& backends
[i
]; i
++) {
387 if (gensec_security
!= NULL
&&
388 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
390 if (!backends
[i
]->oid
) {
393 for (oid_idx
= 0; oid_strings
[oid_idx
]; oid_idx
++) {
394 if (strcmp(oid_strings
[oid_idx
], skip
) == 0) {
398 for (j
=0; backends
[i
]->oid
[j
]; j
++) {
399 if (!backends
[i
]->oid
[j
] ||
400 !(strcmp(backends
[i
]->oid
[j
],
401 oid_strings
[oid_idx
]) == 0)) {
405 for (k
=0; backends_out
[k
].op
; k
++) {
406 if (backends_out
[k
].op
== backends
[i
]) {
411 if (k
< num_backends_out
) {
412 /* already in there */
416 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
417 struct gensec_security_ops_wrapper
,
418 num_backends_out
+ 2);
423 backends_out
[num_backends_out
].op
= backends
[i
];
424 backends_out
[num_backends_out
].oid
= backends
[i
]->oid
[j
];
426 backends_out
[num_backends_out
].op
= NULL
;
427 backends_out
[num_backends_out
].oid
= NULL
;
435 * Return OIDS from the security subsystems listed
438 static const char **gensec_security_oids_from_ops(
439 struct gensec_security
*gensec_security
,
441 const struct gensec_security_ops
* const *ops
,
447 const char **oid_list
;
451 oid_list
= talloc_array(mem_ctx
, const char *, 1);
456 for (i
=0; ops
&& ops
[i
]; i
++) {
457 if (gensec_security
!= NULL
&&
458 !gensec_security_ops_enabled(ops
[i
], gensec_security
)) {
465 for (k
= 0; ops
[i
]->oid
[k
]; k
++) {
466 if (skip
&& strcmp(skip
, ops
[i
]->oid
[k
])==0) {
468 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
472 oid_list
[j
] = ops
[i
]->oid
[k
];
483 * Return OIDS from the security subsystems listed
486 _PUBLIC_
const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX
*mem_ctx
,
487 const struct gensec_security_ops_wrapper
*wops
)
492 const char **oid_list
;
496 oid_list
= talloc_array(mem_ctx
, const char *, 1);
501 for (i
=0; wops
[i
].op
; i
++) {
502 if (!wops
[i
].op
->oid
) {
506 for (k
= 0; wops
[i
].op
->oid
[k
]; k
++) {
507 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
511 oid_list
[j
] = wops
[i
].op
->oid
[k
];
521 * Return all the security subsystems currently enabled on a GENSEC context.
523 * This is taken from a list attached to the cli_credentials, and
524 * skips the OID in 'skip'. (Typically the SPNEGO OID)
528 _PUBLIC_
const char **gensec_security_oids(struct gensec_security
*gensec_security
,
532 const struct gensec_security_ops
**ops
;
534 ops
= gensec_security_mechs(gensec_security
, mem_ctx
);
536 return gensec_security_oids_from_ops(gensec_security
, mem_ctx
, ops
, skip
);
540 Start the GENSEC system, returning a context pointer.
541 @param mem_ctx The parent TALLOC memory context.
542 @param gensec_security Returned GENSEC context pointer.
543 @note The mem_ctx is only a parent and may be NULL.
544 @note, the auth context is moved to be a referenced pointer of the
545 @ gensec_security return
547 static NTSTATUS
gensec_start(TALLOC_CTX
*mem_ctx
,
548 struct gensec_settings
*settings
,
549 struct auth4_context
*auth_context
,
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
)->max_update_size
= 0;
557 SMB_ASSERT(settings
->lp_ctx
!= NULL
);
558 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, settings
);
560 /* We need to reference this, not steal, as the caller may be
561 * python, which won't like it if we steal it's object away
563 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, auth_context
);
569 * Start a GENSEC subcontext, with a copy of the properties of the parent
570 * @param mem_ctx The parent TALLOC memory context.
571 * @param parent The parent GENSEC context
572 * @param gensec_security Returned GENSEC context pointer.
573 * @note Used by SPNEGO in particular, for the actual implementation mechanism
576 _PUBLIC_ NTSTATUS
gensec_subcontext_start(TALLOC_CTX
*mem_ctx
,
577 struct gensec_security
*parent
,
578 struct gensec_security
**gensec_security
)
580 (*gensec_security
) = talloc_zero(mem_ctx
, struct gensec_security
);
581 NT_STATUS_HAVE_NO_MEMORY(*gensec_security
);
583 (**gensec_security
) = *parent
;
584 (*gensec_security
)->ops
= NULL
;
585 (*gensec_security
)->private_data
= NULL
;
587 (*gensec_security
)->subcontext
= true;
588 (*gensec_security
)->want_features
= parent
->want_features
;
589 (*gensec_security
)->max_update_size
= parent
->max_update_size
;
590 (*gensec_security
)->dcerpc_auth_level
= parent
->dcerpc_auth_level
;
591 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
592 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, parent
->settings
);
593 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
599 Start the GENSEC system, in client 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_client_start(TALLOC_CTX
*mem_ctx
,
605 struct gensec_security
**gensec_security
,
606 struct gensec_settings
*settings
)
610 if (settings
== NULL
) {
611 DEBUG(0,("gensec_client_start: no settings given!\n"));
612 return NT_STATUS_INTERNAL_ERROR
;
615 status
= gensec_start(mem_ctx
, settings
, NULL
, gensec_security
);
616 if (!NT_STATUS_IS_OK(status
)) {
619 (*gensec_security
)->gensec_role
= GENSEC_CLIENT
;
627 Start the GENSEC system, in server mode, returning a context pointer.
628 @param mem_ctx The parent TALLOC memory context.
629 @param gensec_security Returned GENSEC context pointer.
630 @note The mem_ctx is only a parent and may be NULL.
632 _PUBLIC_ NTSTATUS
gensec_server_start(TALLOC_CTX
*mem_ctx
,
633 struct gensec_settings
*settings
,
634 struct auth4_context
*auth_context
,
635 struct gensec_security
**gensec_security
)
640 DEBUG(0,("gensec_server_start: no settings given!\n"));
641 return NT_STATUS_INTERNAL_ERROR
;
644 status
= gensec_start(mem_ctx
, settings
, auth_context
, gensec_security
);
645 if (!NT_STATUS_IS_OK(status
)) {
648 (*gensec_security
)->gensec_role
= GENSEC_SERVER
;
653 NTSTATUS
gensec_start_mech(struct gensec_security
*gensec_security
)
657 if (gensec_security
->credentials
) {
658 const char *forced_mech
= cli_credentials_get_forced_sasl_mech(gensec_security
->credentials
);
660 (gensec_security
->ops
->sasl_name
== NULL
||
661 strcasecmp(forced_mech
, gensec_security
->ops
->sasl_name
) != 0)) {
662 DEBUG(5, ("GENSEC mechanism %s (%s) skipped, as it "
663 "did not match forced mechanism %s\n",
664 gensec_security
->ops
->name
,
665 gensec_security
->ops
->sasl_name
,
667 return NT_STATUS_INVALID_PARAMETER
;
670 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
671 gensec_security
->subcontext
? "sub" : "",
672 gensec_security
->ops
->name
));
673 switch (gensec_security
->gensec_role
) {
675 if (gensec_security
->ops
->client_start
) {
676 status
= gensec_security
->ops
->client_start(gensec_security
);
677 if (!NT_STATUS_IS_OK(status
)) {
678 DEBUG(gensec_security
->subcontext
?4:2, ("Failed to start GENSEC client mech %s: %s\n",
679 gensec_security
->ops
->name
, nt_errstr(status
)));
685 if (gensec_security
->ops
->server_start
) {
686 status
= gensec_security
->ops
->server_start(gensec_security
);
687 if (!NT_STATUS_IS_OK(status
)) {
688 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
689 gensec_security
->ops
->name
, nt_errstr(status
)));
695 return NT_STATUS_INVALID_PARAMETER
;
699 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
703 NTSTATUS
gensec_start_mech_by_ops(struct gensec_security
*gensec_security
,
704 const struct gensec_security_ops
*ops
)
706 gensec_security
->ops
= ops
;
707 return gensec_start_mech(gensec_security
);
712 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
713 * @param gensec_security GENSEC context pointer.
714 * @param auth_type DCERPC auth type
715 * @param auth_level DCERPC auth level
718 _PUBLIC_ NTSTATUS
gensec_start_mech_by_authtype(struct gensec_security
*gensec_security
,
719 uint8_t auth_type
, uint8_t auth_level
)
721 gensec_security
->ops
= gensec_security_by_auth_type(gensec_security
, auth_type
);
722 if (!gensec_security
->ops
) {
723 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type
));
724 return NT_STATUS_INVALID_PARAMETER
;
726 gensec_security
->dcerpc_auth_level
= auth_level
;
727 gensec_want_feature(gensec_security
, GENSEC_FEATURE_DCE_STYLE
);
728 gensec_want_feature(gensec_security
, GENSEC_FEATURE_ASYNC_REPLIES
);
729 if (auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
730 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
731 } else if (auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
732 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
733 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SEAL
);
734 } else if (auth_level
== DCERPC_AUTH_LEVEL_CONNECT
) {
735 /* Default features */
737 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
739 return NT_STATUS_INVALID_PARAMETER
;
742 return gensec_start_mech(gensec_security
);
745 _PUBLIC_
const char *gensec_get_name_by_authtype(struct gensec_security
*gensec_security
, uint8_t authtype
)
747 const struct gensec_security_ops
*ops
;
748 ops
= gensec_security_by_auth_type(gensec_security
, authtype
);
756 _PUBLIC_
const char *gensec_get_name_by_oid(struct gensec_security
*gensec_security
,
757 const char *oid_string
)
759 const struct gensec_security_ops
*ops
;
760 ops
= gensec_security_by_oid(gensec_security
, oid_string
);
768 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
770 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
771 * well-known #define to hook it in.
774 _PUBLIC_ NTSTATUS
gensec_start_mech_by_oid(struct gensec_security
*gensec_security
,
775 const char *mech_oid
)
777 SMB_ASSERT(gensec_security
!= NULL
);
779 gensec_security
->ops
= gensec_security_by_oid(gensec_security
, mech_oid
);
780 if (!gensec_security
->ops
) {
781 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid
));
782 return NT_STATUS_INVALID_PARAMETER
;
784 return gensec_start_mech(gensec_security
);
788 * Start a GENSEC sub-mechanism by a well know SASL name
792 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_name(struct gensec_security
*gensec_security
,
793 const char *sasl_name
)
795 gensec_security
->ops
= gensec_security_by_sasl_name(gensec_security
, sasl_name
);
796 if (!gensec_security
->ops
) {
797 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name
));
798 return NT_STATUS_INVALID_PARAMETER
;
800 return gensec_start_mech(gensec_security
);
804 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
808 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_list(struct gensec_security
*gensec_security
,
809 const char **sasl_names
)
811 NTSTATUS nt_status
= NT_STATUS_INVALID_PARAMETER
;
812 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
813 const struct gensec_security_ops
**ops
;
816 return NT_STATUS_NO_MEMORY
;
818 ops
= gensec_security_by_sasl_list(gensec_security
, mem_ctx
, sasl_names
);
820 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
821 str_list_join(mem_ctx
,
823 talloc_free(mem_ctx
);
824 return NT_STATUS_INVALID_PARAMETER
;
826 for (i
=0; ops
[i
]; i
++) {
827 nt_status
= gensec_start_mech_by_ops(gensec_security
, ops
[i
]);
828 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_INVALID_PARAMETER
)) {
832 talloc_free(mem_ctx
);
837 * Start a GENSEC sub-mechanism by an internal name
841 _PUBLIC_ NTSTATUS
gensec_start_mech_by_name(struct gensec_security
*gensec_security
,
844 gensec_security
->ops
= gensec_security_by_name(gensec_security
, name
);
845 if (!gensec_security
->ops
) {
846 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name
));
847 return NT_STATUS_INVALID_PARAMETER
;
849 return gensec_start_mech(gensec_security
);
853 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
857 _PUBLIC_ NTSTATUS
gensec_set_credentials(struct gensec_security
*gensec_security
, struct cli_credentials
*credentials
)
859 gensec_security
->credentials
= talloc_reference(gensec_security
, credentials
);
860 NT_STATUS_HAVE_NO_MEMORY(gensec_security
->credentials
);
861 gensec_want_feature(gensec_security
, cli_credentials_get_gensec_features(gensec_security
->credentials
));
866 register a GENSEC backend.
868 The 'name' can be later used by other backends to find the operations
869 structure for this backend.
871 _PUBLIC_ NTSTATUS
gensec_register(const struct gensec_security_ops
*ops
)
873 if (gensec_security_by_name(NULL
, ops
->name
) != NULL
) {
874 /* its already registered! */
875 DEBUG(0,("GENSEC backend '%s' already registered\n",
877 return NT_STATUS_OBJECT_NAME_COLLISION
;
880 generic_security_ops
= talloc_realloc(talloc_autofree_context(),
881 generic_security_ops
,
882 const struct gensec_security_ops
*,
883 gensec_num_backends
+2);
884 if (!generic_security_ops
) {
885 return NT_STATUS_NO_MEMORY
;
888 generic_security_ops
[gensec_num_backends
] = ops
;
889 gensec_num_backends
++;
890 generic_security_ops
[gensec_num_backends
] = NULL
;
892 DEBUG(3,("GENSEC backend '%s' registered\n",
899 return the GENSEC interface version, and the size of some critical types
900 This can be used by backends to either detect compilation errors, or provide
901 multiple implementations for different smbd compilation options in one module
903 _PUBLIC_
const struct gensec_critical_sizes
*gensec_interface_version(void)
905 static const struct gensec_critical_sizes critical_sizes
= {
906 GENSEC_INTERFACE_VERSION
,
907 sizeof(struct gensec_security_ops
),
908 sizeof(struct gensec_security
),
911 return &critical_sizes
;
914 static int sort_gensec(const struct gensec_security_ops
**gs1
, const struct gensec_security_ops
**gs2
) {
915 return (*gs2
)->priority
- (*gs1
)->priority
;
918 int gensec_setting_int(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, int default_value
)
920 return lpcfg_parm_int(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
923 bool gensec_setting_bool(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, bool default_value
)
925 return lpcfg_parm_bool(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
929 initialise the GENSEC subsystem
931 _PUBLIC_ NTSTATUS
gensec_init(void)
933 static bool initialized
= false;
934 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
935 #ifdef STATIC_gensec_MODULES
936 STATIC_gensec_MODULES_PROTO
;
937 init_module_fn static_init
[] = { STATIC_gensec_MODULES
};
939 init_module_fn
*static_init
= NULL
;
941 init_module_fn
*shared_init
;
943 if (initialized
) return NT_STATUS_OK
;
946 shared_init
= load_samba_modules(NULL
, "gensec");
948 run_init_functions(static_init
);
949 run_init_functions(shared_init
);
951 talloc_free(shared_init
);
953 TYPESAFE_QSORT(generic_security_ops
, gensec_num_backends
, sort_gensec
);