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"
34 #include "lib/util/base64.h"
36 /* the list of currently registered GENSEC backends */
37 static const struct gensec_security_ops
**generic_security_ops
;
38 static int gensec_num_backends
;
40 /* Return all the registered mechs. Don't modify the return pointer,
41 * but you may talloc_referen it if convient */
42 _PUBLIC_
const struct gensec_security_ops
* const *gensec_security_all(void)
44 return generic_security_ops
;
47 bool gensec_security_ops_enabled(const struct gensec_security_ops
*ops
, struct gensec_security
*security
)
49 return lpcfg_parm_bool(security
->settings
->lp_ctx
, NULL
, "gensec", ops
->name
, ops
->enabled
);
52 /* Sometimes we want to force only kerberos, sometimes we want to
53 * force it's avoidance. The old list could be either
54 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
55 * an existing list we have trimmed down)
57 * The intended logic is:
59 * if we are in the default AUTO have kerberos:
60 * - take a reference to the master list
62 * - always add spnego then:
63 * - if we 'MUST' have kerberos:
64 * only add kerberos mechs
65 * - if we 'DONT' want kerberos':
66 * only add non-kerberos mechs
68 * Once we get things like NegoEx or moonshot, this will of course get
72 _PUBLIC_
const struct gensec_security_ops
**gensec_use_kerberos_mechs(TALLOC_CTX
*mem_ctx
,
73 const struct gensec_security_ops
* const *old_gensec_list
,
74 struct cli_credentials
*creds
)
76 const struct gensec_security_ops
**new_gensec_list
;
77 int i
, j
, num_mechs_in
;
78 enum credentials_use_kerberos use_kerberos
= CRED_AUTO_USE_KERBEROS
;
79 bool keep_schannel
= false;
82 use_kerberos
= cli_credentials_get_kerberos_state(creds
);
83 if (cli_credentials_get_netlogon_creds(creds
) != NULL
) {
88 for (num_mechs_in
=0; old_gensec_list
&& old_gensec_list
[num_mechs_in
]; num_mechs_in
++) {
92 new_gensec_list
= talloc_array(mem_ctx
,
93 const struct gensec_security_ops
*,
95 if (!new_gensec_list
) {
100 for (i
=0; old_gensec_list
&& old_gensec_list
[i
]; i
++) {
104 for (oid_idx
= 0; old_gensec_list
[i
]->oid
&& old_gensec_list
[i
]->oid
[oid_idx
]; oid_idx
++) {
105 if (strcmp(old_gensec_list
[i
]->oid
[oid_idx
], GENSEC_OID_SPNEGO
) == 0) {
111 if (old_gensec_list
[i
]->auth_type
== DCERPC_AUTH_TYPE_SCHANNEL
) {
112 keep
= keep_schannel
;
115 switch (use_kerberos
) {
116 case CRED_AUTO_USE_KERBEROS
:
120 case CRED_DONT_USE_KERBEROS
:
121 if (old_gensec_list
[i
]->kerberos
== false) {
127 case CRED_MUST_USE_KERBEROS
:
128 if (old_gensec_list
[i
]->kerberos
== true) {
134 /* Can't happen or invalid parameter */
142 new_gensec_list
[j
] = old_gensec_list
[i
];
145 new_gensec_list
[j
] = NULL
;
147 return new_gensec_list
;
150 _PUBLIC_
const struct gensec_security_ops
**gensec_security_mechs(
151 struct gensec_security
*gensec_security
,
154 struct cli_credentials
*creds
= NULL
;
155 const struct gensec_security_ops
* const *backends
= gensec_security_all();
157 if (gensec_security
!= NULL
) {
158 creds
= gensec_get_credentials(gensec_security
);
160 if (gensec_security
->settings
->backends
) {
161 backends
= gensec_security
->settings
->backends
;
165 return gensec_use_kerberos_mechs(mem_ctx
, backends
, creds
);
169 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_oid(
170 struct gensec_security
*gensec_security
,
171 const char *oid_string
)
174 const 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 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_sasl_name(
203 struct gensec_security
*gensec_security
,
204 const char *sasl_name
)
207 const struct gensec_security_ops
**backends
;
208 const struct gensec_security_ops
*backend
;
209 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
213 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
214 for (i
=0; backends
&& backends
[i
]; i
++) {
215 if (gensec_security
!= NULL
&&
216 !gensec_security_ops_enabled(backends
[i
], gensec_security
)) {
219 if (backends
[i
]->sasl_name
220 && (strcmp(backends
[i
]->sasl_name
, sasl_name
) == 0)) {
221 backend
= backends
[i
];
222 talloc_free(mem_ctx
);
226 talloc_free(mem_ctx
);
231 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_auth_type(
232 struct gensec_security
*gensec_security
,
236 const struct gensec_security_ops
**backends
;
237 const struct gensec_security_ops
*backend
;
240 if (auth_type
== DCERPC_AUTH_TYPE_NONE
) {
244 mem_ctx
= talloc_new(gensec_security
);
248 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
249 for (i
=0; backends
&& backends
[i
]; i
++) {
250 if (gensec_security
!= NULL
&&
251 !gensec_security_ops_enabled(backends
[i
], gensec_security
)) {
254 if (backends
[i
]->auth_type
== auth_type
) {
255 backend
= backends
[i
];
256 talloc_free(mem_ctx
);
260 talloc_free(mem_ctx
);
265 const struct gensec_security_ops
*gensec_security_by_name(struct gensec_security
*gensec_security
,
269 const struct gensec_security_ops
**backends
;
270 const struct gensec_security_ops
*backend
;
271 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
275 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
276 for (i
=0; backends
&& backends
[i
]; i
++) {
277 if (gensec_security
!= NULL
&&
278 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
280 if (backends
[i
]->name
281 && (strcmp(backends
[i
]->name
, name
) == 0)) {
282 backend
= backends
[i
];
283 talloc_free(mem_ctx
);
287 talloc_free(mem_ctx
);
292 * Return a unique list of security subsystems from those specified in
293 * the list of SASL names.
295 * Use the list of enabled GENSEC mechanisms from the credentials
296 * attached to the gensec_security, and return in our preferred order.
299 static const struct gensec_security_ops
**gensec_security_by_sasl_list(
300 struct gensec_security
*gensec_security
,
302 const char **sasl_names
)
304 const struct gensec_security_ops
**backends_out
;
305 const struct gensec_security_ops
**backends
;
307 int num_backends_out
= 0;
313 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
315 backends_out
= talloc_array(mem_ctx
, const struct gensec_security_ops
*, 1);
319 backends_out
[0] = NULL
;
321 /* Find backends in our preferred order, by walking our list,
322 * then looking in the supplied list */
323 for (i
=0; backends
&& backends
[i
]; i
++) {
324 if (gensec_security
!= NULL
&&
325 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
327 for (sasl_idx
= 0; sasl_names
[sasl_idx
]; sasl_idx
++) {
328 if (!backends
[i
]->sasl_name
||
329 !(strcmp(backends
[i
]->sasl_name
,
330 sasl_names
[sasl_idx
]) == 0)) {
334 for (k
=0; backends_out
[k
]; k
++) {
335 if (backends_out
[k
] == backends
[i
]) {
340 if (k
< num_backends_out
) {
341 /* already in there */
345 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
346 const struct gensec_security_ops
*,
347 num_backends_out
+ 2);
352 backends_out
[num_backends_out
] = backends
[i
];
354 backends_out
[num_backends_out
] = NULL
;
361 * Return a unique list of security subsystems from those specified in
362 * the OID list. That is, where two OIDs refer to the same module,
363 * return that module only once.
365 * Use the list of enabled GENSEC mechanisms from the credentials
366 * attached to the gensec_security, and return in our preferred order.
369 _PUBLIC_
const struct gensec_security_ops_wrapper
*gensec_security_by_oid_list(
370 struct gensec_security
*gensec_security
,
372 const char * const *oid_strings
,
375 struct gensec_security_ops_wrapper
*backends_out
;
376 const struct gensec_security_ops
**backends
;
377 int i
, j
, k
, oid_idx
;
378 int num_backends_out
= 0;
384 backends
= gensec_security_mechs(gensec_security
, gensec_security
);
386 backends_out
= talloc_array(mem_ctx
, struct gensec_security_ops_wrapper
, 1);
390 backends_out
[0].op
= NULL
;
391 backends_out
[0].oid
= NULL
;
393 /* Find backends in our preferred order, by walking our list,
394 * then looking in the supplied list */
395 for (i
=0; backends
&& backends
[i
]; i
++) {
396 if (gensec_security
!= NULL
&&
397 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
399 if (!backends
[i
]->oid
) {
402 for (oid_idx
= 0; oid_strings
[oid_idx
]; oid_idx
++) {
403 if (strcmp(oid_strings
[oid_idx
], skip
) == 0) {
407 for (j
=0; backends
[i
]->oid
[j
]; j
++) {
408 if (!backends
[i
]->oid
[j
] ||
409 !(strcmp(backends
[i
]->oid
[j
],
410 oid_strings
[oid_idx
]) == 0)) {
414 for (k
=0; backends_out
[k
].op
; k
++) {
415 if (backends_out
[k
].op
== backends
[i
]) {
420 if (k
< num_backends_out
) {
421 /* already in there */
425 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
426 struct gensec_security_ops_wrapper
,
427 num_backends_out
+ 2);
432 backends_out
[num_backends_out
].op
= backends
[i
];
433 backends_out
[num_backends_out
].oid
= backends
[i
]->oid
[j
];
435 backends_out
[num_backends_out
].op
= NULL
;
436 backends_out
[num_backends_out
].oid
= NULL
;
444 * Return OIDS from the security subsystems listed
447 static const char **gensec_security_oids_from_ops(
448 struct gensec_security
*gensec_security
,
450 const struct gensec_security_ops
* const *ops
,
456 const char **oid_list
;
460 oid_list
= talloc_array(mem_ctx
, const char *, 1);
465 for (i
=0; ops
&& ops
[i
]; i
++) {
466 if (gensec_security
!= NULL
&&
467 !gensec_security_ops_enabled(ops
[i
], gensec_security
)) {
474 for (k
= 0; ops
[i
]->oid
[k
]; k
++) {
475 if (skip
&& strcmp(skip
, ops
[i
]->oid
[k
])==0) {
477 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
481 oid_list
[j
] = ops
[i
]->oid
[k
];
492 * Return OIDS from the security subsystems listed
495 _PUBLIC_
const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX
*mem_ctx
,
496 const struct gensec_security_ops_wrapper
*wops
)
501 const char **oid_list
;
505 oid_list
= talloc_array(mem_ctx
, const char *, 1);
510 for (i
=0; wops
[i
].op
; i
++) {
511 if (!wops
[i
].op
->oid
) {
515 for (k
= 0; wops
[i
].op
->oid
[k
]; k
++) {
516 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
520 oid_list
[j
] = wops
[i
].op
->oid
[k
];
530 * Return all the security subsystems currently enabled on a GENSEC context.
532 * This is taken from a list attached to the cli_credentials, and
533 * skips the OID in 'skip'. (Typically the SPNEGO OID)
537 _PUBLIC_
const char **gensec_security_oids(struct gensec_security
*gensec_security
,
541 const struct gensec_security_ops
**ops
;
543 ops
= gensec_security_mechs(gensec_security
, mem_ctx
);
545 return gensec_security_oids_from_ops(gensec_security
, mem_ctx
, ops
, skip
);
549 Start the GENSEC system, returning a context pointer.
550 @param mem_ctx The parent TALLOC memory context.
551 @param gensec_security Returned GENSEC context pointer.
552 @note The mem_ctx is only a parent and may be NULL.
553 @note, the auth context is moved to be a referenced pointer of the
554 @ gensec_security return
556 static NTSTATUS
gensec_start(TALLOC_CTX
*mem_ctx
,
557 struct gensec_settings
*settings
,
558 struct auth4_context
*auth_context
,
559 struct gensec_security
**gensec_security
)
561 (*gensec_security
) = talloc_zero(mem_ctx
, struct gensec_security
);
562 NT_STATUS_HAVE_NO_MEMORY(*gensec_security
);
564 (*gensec_security
)->max_update_size
= 0;
566 SMB_ASSERT(settings
->lp_ctx
!= NULL
);
567 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, settings
);
569 /* We need to reference this, not steal, as the caller may be
570 * python, which won't like it if we steal it's object away
572 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, auth_context
);
578 * Start a GENSEC subcontext, with a copy of the properties of the parent
579 * @param mem_ctx The parent TALLOC memory context.
580 * @param parent The parent GENSEC context
581 * @param gensec_security Returned GENSEC context pointer.
582 * @note Used by SPNEGO in particular, for the actual implementation mechanism
585 _PUBLIC_ NTSTATUS
gensec_subcontext_start(TALLOC_CTX
*mem_ctx
,
586 struct gensec_security
*parent
,
587 struct gensec_security
**gensec_security
)
589 (*gensec_security
) = talloc_zero(mem_ctx
, struct gensec_security
);
590 NT_STATUS_HAVE_NO_MEMORY(*gensec_security
);
592 (**gensec_security
) = *parent
;
593 (*gensec_security
)->ops
= NULL
;
594 (*gensec_security
)->private_data
= NULL
;
596 (*gensec_security
)->subcontext
= true;
597 (*gensec_security
)->want_features
= parent
->want_features
;
598 (*gensec_security
)->max_update_size
= parent
->max_update_size
;
599 (*gensec_security
)->dcerpc_auth_level
= parent
->dcerpc_auth_level
;
600 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
601 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, parent
->settings
);
602 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
608 Start the GENSEC system, in client mode, returning a context pointer.
609 @param mem_ctx The parent TALLOC memory context.
610 @param gensec_security Returned GENSEC context pointer.
611 @note The mem_ctx is only a parent and may be NULL.
613 _PUBLIC_ NTSTATUS
gensec_client_start(TALLOC_CTX
*mem_ctx
,
614 struct gensec_security
**gensec_security
,
615 struct gensec_settings
*settings
)
619 if (settings
== NULL
) {
620 DEBUG(0,("gensec_client_start: no settings given!\n"));
621 return NT_STATUS_INTERNAL_ERROR
;
624 status
= gensec_start(mem_ctx
, settings
, NULL
, gensec_security
);
625 if (!NT_STATUS_IS_OK(status
)) {
628 (*gensec_security
)->gensec_role
= GENSEC_CLIENT
;
636 Start the GENSEC system, in server mode, returning a context pointer.
637 @param mem_ctx The parent TALLOC memory context.
638 @param gensec_security Returned GENSEC context pointer.
639 @note The mem_ctx is only a parent and may be NULL.
641 _PUBLIC_ NTSTATUS
gensec_server_start(TALLOC_CTX
*mem_ctx
,
642 struct gensec_settings
*settings
,
643 struct auth4_context
*auth_context
,
644 struct gensec_security
**gensec_security
)
649 DEBUG(0,("gensec_server_start: no settings given!\n"));
650 return NT_STATUS_INTERNAL_ERROR
;
653 status
= gensec_start(mem_ctx
, settings
, auth_context
, gensec_security
);
654 if (!NT_STATUS_IS_OK(status
)) {
657 (*gensec_security
)->gensec_role
= GENSEC_SERVER
;
662 NTSTATUS
gensec_start_mech(struct gensec_security
*gensec_security
)
666 if (gensec_security
->credentials
) {
667 const char *forced_mech
= cli_credentials_get_forced_sasl_mech(gensec_security
->credentials
);
669 (gensec_security
->ops
->sasl_name
== NULL
||
670 strcasecmp(forced_mech
, gensec_security
->ops
->sasl_name
) != 0)) {
671 DEBUG(5, ("GENSEC mechanism %s (%s) skipped, as it "
672 "did not match forced mechanism %s\n",
673 gensec_security
->ops
->name
,
674 gensec_security
->ops
->sasl_name
,
676 return NT_STATUS_INVALID_PARAMETER
;
679 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
680 gensec_security
->subcontext
? "sub" : "",
681 gensec_security
->ops
->name
));
682 switch (gensec_security
->gensec_role
) {
684 if (gensec_security
->ops
->client_start
) {
685 status
= gensec_security
->ops
->client_start(gensec_security
);
686 if (!NT_STATUS_IS_OK(status
)) {
687 DEBUG(gensec_security
->subcontext
?4:2, ("Failed to start GENSEC client mech %s: %s\n",
688 gensec_security
->ops
->name
, nt_errstr(status
)));
694 if (gensec_security
->ops
->server_start
) {
695 status
= gensec_security
->ops
->server_start(gensec_security
);
696 if (!NT_STATUS_IS_OK(status
)) {
697 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
698 gensec_security
->ops
->name
, nt_errstr(status
)));
704 return NT_STATUS_INVALID_PARAMETER
;
708 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
712 NTSTATUS
gensec_start_mech_by_ops(struct gensec_security
*gensec_security
,
713 const struct gensec_security_ops
*ops
)
715 gensec_security
->ops
= ops
;
716 return gensec_start_mech(gensec_security
);
721 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
722 * @param gensec_security GENSEC context pointer.
723 * @param auth_type DCERPC auth type
724 * @param auth_level DCERPC auth level
727 _PUBLIC_ NTSTATUS
gensec_start_mech_by_authtype(struct gensec_security
*gensec_security
,
728 uint8_t auth_type
, uint8_t auth_level
)
730 gensec_security
->ops
= gensec_security_by_auth_type(gensec_security
, auth_type
);
731 if (!gensec_security
->ops
) {
732 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type
));
733 return NT_STATUS_INVALID_PARAMETER
;
735 gensec_security
->dcerpc_auth_level
= auth_level
;
737 * We need to reset sign/seal in order to reset it.
738 * We may got some default features inherited by the credentials
740 gensec_security
->want_features
&= ~GENSEC_FEATURE_SIGN
;
741 gensec_security
->want_features
&= ~GENSEC_FEATURE_SEAL
;
742 gensec_want_feature(gensec_security
, GENSEC_FEATURE_DCE_STYLE
);
743 gensec_want_feature(gensec_security
, GENSEC_FEATURE_ASYNC_REPLIES
);
744 if (auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
745 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
746 } else if (auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
747 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
748 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SEAL
);
749 } else if (auth_level
== DCERPC_AUTH_LEVEL_CONNECT
) {
750 /* Default features */
752 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
754 return NT_STATUS_INVALID_PARAMETER
;
757 return gensec_start_mech(gensec_security
);
760 _PUBLIC_
const char *gensec_get_name_by_authtype(struct gensec_security
*gensec_security
, uint8_t authtype
)
762 const struct gensec_security_ops
*ops
;
763 ops
= gensec_security_by_auth_type(gensec_security
, authtype
);
771 _PUBLIC_
const char *gensec_get_name_by_oid(struct gensec_security
*gensec_security
,
772 const char *oid_string
)
774 const struct gensec_security_ops
*ops
;
775 ops
= gensec_security_by_oid(gensec_security
, oid_string
);
783 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
785 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
786 * well-known #define to hook it in.
789 _PUBLIC_ NTSTATUS
gensec_start_mech_by_oid(struct gensec_security
*gensec_security
,
790 const char *mech_oid
)
792 SMB_ASSERT(gensec_security
!= NULL
);
794 gensec_security
->ops
= gensec_security_by_oid(gensec_security
, mech_oid
);
795 if (!gensec_security
->ops
) {
796 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid
));
797 return NT_STATUS_INVALID_PARAMETER
;
799 return gensec_start_mech(gensec_security
);
803 * Start a GENSEC sub-mechanism by a well know SASL name
807 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_name(struct gensec_security
*gensec_security
,
808 const char *sasl_name
)
810 gensec_security
->ops
= gensec_security_by_sasl_name(gensec_security
, sasl_name
);
811 if (!gensec_security
->ops
) {
812 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name
));
813 return NT_STATUS_INVALID_PARAMETER
;
815 return gensec_start_mech(gensec_security
);
819 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
823 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_list(struct gensec_security
*gensec_security
,
824 const char **sasl_names
)
826 NTSTATUS nt_status
= NT_STATUS_INVALID_PARAMETER
;
827 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
828 const struct gensec_security_ops
**ops
;
831 return NT_STATUS_NO_MEMORY
;
833 ops
= gensec_security_by_sasl_list(gensec_security
, mem_ctx
, sasl_names
);
835 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
836 str_list_join(mem_ctx
,
838 talloc_free(mem_ctx
);
839 return NT_STATUS_INVALID_PARAMETER
;
841 for (i
=0; ops
[i
]; i
++) {
842 nt_status
= gensec_start_mech_by_ops(gensec_security
, ops
[i
]);
843 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_INVALID_PARAMETER
)) {
847 talloc_free(mem_ctx
);
852 * Start a GENSEC sub-mechanism by an internal name
856 _PUBLIC_ NTSTATUS
gensec_start_mech_by_name(struct gensec_security
*gensec_security
,
859 gensec_security
->ops
= gensec_security_by_name(gensec_security
, name
);
860 if (!gensec_security
->ops
) {
861 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name
));
862 return NT_STATUS_INVALID_PARAMETER
;
864 return gensec_start_mech(gensec_security
);
868 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
872 _PUBLIC_ NTSTATUS
gensec_set_credentials(struct gensec_security
*gensec_security
, struct cli_credentials
*credentials
)
874 gensec_security
->credentials
= talloc_reference(gensec_security
, credentials
);
875 NT_STATUS_HAVE_NO_MEMORY(gensec_security
->credentials
);
876 gensec_want_feature(gensec_security
, cli_credentials_get_gensec_features(gensec_security
->credentials
));
881 register a GENSEC backend.
883 The 'name' can be later used by other backends to find the operations
884 structure for this backend.
886 _PUBLIC_ NTSTATUS
gensec_register(const struct gensec_security_ops
*ops
)
888 if (gensec_security_by_name(NULL
, ops
->name
) != NULL
) {
889 /* its already registered! */
890 DEBUG(0,("GENSEC backend '%s' already registered\n",
892 return NT_STATUS_OBJECT_NAME_COLLISION
;
895 generic_security_ops
= talloc_realloc(talloc_autofree_context(),
896 generic_security_ops
,
897 const struct gensec_security_ops
*,
898 gensec_num_backends
+2);
899 if (!generic_security_ops
) {
900 return NT_STATUS_NO_MEMORY
;
903 generic_security_ops
[gensec_num_backends
] = ops
;
904 gensec_num_backends
++;
905 generic_security_ops
[gensec_num_backends
] = NULL
;
907 DEBUG(3,("GENSEC backend '%s' registered\n",
914 return the GENSEC interface version, and the size of some critical types
915 This can be used by backends to either detect compilation errors, or provide
916 multiple implementations for different smbd compilation options in one module
918 _PUBLIC_
const struct gensec_critical_sizes
*gensec_interface_version(void)
920 static const struct gensec_critical_sizes critical_sizes
= {
921 GENSEC_INTERFACE_VERSION
,
922 sizeof(struct gensec_security_ops
),
923 sizeof(struct gensec_security
),
926 return &critical_sizes
;
929 static int sort_gensec(const struct gensec_security_ops
**gs1
, const struct gensec_security_ops
**gs2
) {
930 return (*gs2
)->priority
- (*gs1
)->priority
;
933 int gensec_setting_int(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, int default_value
)
935 return lpcfg_parm_int(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
938 bool gensec_setting_bool(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, bool default_value
)
940 return lpcfg_parm_bool(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
944 initialise the GENSEC subsystem
946 _PUBLIC_ NTSTATUS
gensec_init(void)
948 static bool initialized
= false;
949 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
950 #ifdef STATIC_gensec_MODULES
951 STATIC_gensec_MODULES_PROTO
;
952 init_module_fn static_init
[] = { STATIC_gensec_MODULES
};
954 init_module_fn
*static_init
= NULL
;
956 init_module_fn
*shared_init
;
958 if (initialized
) return NT_STATUS_OK
;
961 shared_init
= load_samba_modules(NULL
, "gensec");
963 run_init_functions(static_init
);
964 run_init_functions(shared_init
);
966 talloc_free(shared_init
);
968 TYPESAFE_QSORT(generic_security_ops
, gensec_num_backends
, sort_gensec
);