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
!= NULL
&&
215 !gensec_security_ops_enabled(backends
[i
], gensec_security
)) {
218 if (backends
[i
]->sasl_name
219 && (strcmp(backends
[i
]->sasl_name
, sasl_name
) == 0)) {
220 backend
= backends
[i
];
221 talloc_free(mem_ctx
);
225 talloc_free(mem_ctx
);
230 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_auth_type(
231 struct gensec_security
*gensec_security
,
235 const struct gensec_security_ops
**backends
;
236 const struct gensec_security_ops
*backend
;
239 if (auth_type
== DCERPC_AUTH_TYPE_NONE
) {
243 mem_ctx
= talloc_new(gensec_security
);
247 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
248 for (i
=0; backends
&& backends
[i
]; i
++) {
249 if (gensec_security
!= NULL
&&
250 !gensec_security_ops_enabled(backends
[i
], gensec_security
)) {
253 if (backends
[i
]->auth_type
== auth_type
) {
254 backend
= backends
[i
];
255 talloc_free(mem_ctx
);
259 talloc_free(mem_ctx
);
264 const struct gensec_security_ops
*gensec_security_by_name(struct gensec_security
*gensec_security
,
268 const struct gensec_security_ops
**backends
;
269 const struct gensec_security_ops
*backend
;
270 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
274 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
275 for (i
=0; backends
&& backends
[i
]; i
++) {
276 if (gensec_security
!= NULL
&&
277 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
279 if (backends
[i
]->name
280 && (strcmp(backends
[i
]->name
, name
) == 0)) {
281 backend
= backends
[i
];
282 talloc_free(mem_ctx
);
286 talloc_free(mem_ctx
);
291 * Return a unique list of security subsystems from those specified in
292 * the list of SASL names.
294 * Use the list of enabled GENSEC mechanisms from the credentials
295 * attached to the gensec_security, and return in our preferred order.
298 static const struct gensec_security_ops
**gensec_security_by_sasl_list(
299 struct gensec_security
*gensec_security
,
301 const char **sasl_names
)
303 const struct gensec_security_ops
**backends_out
;
304 const struct gensec_security_ops
**backends
;
306 int num_backends_out
= 0;
312 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
314 backends_out
= talloc_array(mem_ctx
, const struct gensec_security_ops
*, 1);
318 backends_out
[0] = NULL
;
320 /* Find backends in our preferred order, by walking our list,
321 * then looking in the supplied list */
322 for (i
=0; backends
&& backends
[i
]; i
++) {
323 if (gensec_security
!= NULL
&&
324 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
326 for (sasl_idx
= 0; sasl_names
[sasl_idx
]; sasl_idx
++) {
327 if (!backends
[i
]->sasl_name
||
328 !(strcmp(backends
[i
]->sasl_name
,
329 sasl_names
[sasl_idx
]) == 0)) {
333 for (k
=0; backends_out
[k
]; k
++) {
334 if (backends_out
[k
] == backends
[i
]) {
339 if (k
< num_backends_out
) {
340 /* already in there */
344 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
345 const struct gensec_security_ops
*,
346 num_backends_out
+ 2);
351 backends_out
[num_backends_out
] = backends
[i
];
353 backends_out
[num_backends_out
] = NULL
;
360 * Return a unique list of security subsystems from those specified in
361 * the OID list. That is, where two OIDs refer to the same module,
362 * return that module only once.
364 * Use the list of enabled GENSEC mechanisms from the credentials
365 * attached to the gensec_security, and return in our preferred order.
368 _PUBLIC_
const struct gensec_security_ops_wrapper
*gensec_security_by_oid_list(
369 struct gensec_security
*gensec_security
,
371 const char * const *oid_strings
,
374 struct gensec_security_ops_wrapper
*backends_out
;
375 const struct gensec_security_ops
**backends
;
376 int i
, j
, k
, oid_idx
;
377 int num_backends_out
= 0;
383 backends
= gensec_security_mechs(gensec_security
, gensec_security
);
385 backends_out
= talloc_array(mem_ctx
, struct gensec_security_ops_wrapper
, 1);
389 backends_out
[0].op
= NULL
;
390 backends_out
[0].oid
= NULL
;
392 /* Find backends in our preferred order, by walking our list,
393 * then looking in the supplied list */
394 for (i
=0; backends
&& backends
[i
]; i
++) {
395 if (gensec_security
!= NULL
&&
396 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
398 if (!backends
[i
]->oid
) {
401 for (oid_idx
= 0; oid_strings
[oid_idx
]; oid_idx
++) {
402 if (strcmp(oid_strings
[oid_idx
], skip
) == 0) {
406 for (j
=0; backends
[i
]->oid
[j
]; j
++) {
407 if (!backends
[i
]->oid
[j
] ||
408 !(strcmp(backends
[i
]->oid
[j
],
409 oid_strings
[oid_idx
]) == 0)) {
413 for (k
=0; backends_out
[k
].op
; k
++) {
414 if (backends_out
[k
].op
== backends
[i
]) {
419 if (k
< num_backends_out
) {
420 /* already in there */
424 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
425 struct gensec_security_ops_wrapper
,
426 num_backends_out
+ 2);
431 backends_out
[num_backends_out
].op
= backends
[i
];
432 backends_out
[num_backends_out
].oid
= backends
[i
]->oid
[j
];
434 backends_out
[num_backends_out
].op
= NULL
;
435 backends_out
[num_backends_out
].oid
= NULL
;
443 * Return OIDS from the security subsystems listed
446 static const char **gensec_security_oids_from_ops(
447 struct gensec_security
*gensec_security
,
449 const struct gensec_security_ops
* const *ops
,
455 const char **oid_list
;
459 oid_list
= talloc_array(mem_ctx
, const char *, 1);
464 for (i
=0; ops
&& ops
[i
]; i
++) {
465 if (gensec_security
!= NULL
&&
466 !gensec_security_ops_enabled(ops
[i
], gensec_security
)) {
473 for (k
= 0; ops
[i
]->oid
[k
]; k
++) {
474 if (skip
&& strcmp(skip
, ops
[i
]->oid
[k
])==0) {
476 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
480 oid_list
[j
] = ops
[i
]->oid
[k
];
491 * Return OIDS from the security subsystems listed
494 _PUBLIC_
const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX
*mem_ctx
,
495 const struct gensec_security_ops_wrapper
*wops
)
500 const char **oid_list
;
504 oid_list
= talloc_array(mem_ctx
, const char *, 1);
509 for (i
=0; wops
[i
].op
; i
++) {
510 if (!wops
[i
].op
->oid
) {
514 for (k
= 0; wops
[i
].op
->oid
[k
]; k
++) {
515 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
519 oid_list
[j
] = wops
[i
].op
->oid
[k
];
529 * Return all the security subsystems currently enabled on a GENSEC context.
531 * This is taken from a list attached to the cli_credentials, and
532 * skips the OID in 'skip'. (Typically the SPNEGO OID)
536 _PUBLIC_
const char **gensec_security_oids(struct gensec_security
*gensec_security
,
540 const struct gensec_security_ops
**ops
;
542 ops
= gensec_security_mechs(gensec_security
, mem_ctx
);
544 return gensec_security_oids_from_ops(gensec_security
, mem_ctx
, ops
, skip
);
548 Start the GENSEC system, returning a context pointer.
549 @param mem_ctx The parent TALLOC memory context.
550 @param gensec_security Returned GENSEC context pointer.
551 @note The mem_ctx is only a parent and may be NULL.
552 @note, the auth context is moved to be a referenced pointer of the
553 @ gensec_security return
555 static NTSTATUS
gensec_start(TALLOC_CTX
*mem_ctx
,
556 struct gensec_settings
*settings
,
557 struct auth4_context
*auth_context
,
558 struct gensec_security
**gensec_security
)
560 (*gensec_security
) = talloc_zero(mem_ctx
, struct gensec_security
);
561 NT_STATUS_HAVE_NO_MEMORY(*gensec_security
);
563 (*gensec_security
)->max_update_size
= 0;
565 SMB_ASSERT(settings
->lp_ctx
!= NULL
);
566 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, settings
);
568 /* We need to reference this, not steal, as the caller may be
569 * python, which won't like it if we steal it's object away
571 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, auth_context
);
577 * Start a GENSEC subcontext, with a copy of the properties of the parent
578 * @param mem_ctx The parent TALLOC memory context.
579 * @param parent The parent GENSEC context
580 * @param gensec_security Returned GENSEC context pointer.
581 * @note Used by SPNEGO in particular, for the actual implementation mechanism
584 _PUBLIC_ NTSTATUS
gensec_subcontext_start(TALLOC_CTX
*mem_ctx
,
585 struct gensec_security
*parent
,
586 struct gensec_security
**gensec_security
)
588 (*gensec_security
) = talloc_zero(mem_ctx
, struct gensec_security
);
589 NT_STATUS_HAVE_NO_MEMORY(*gensec_security
);
591 (**gensec_security
) = *parent
;
592 (*gensec_security
)->ops
= NULL
;
593 (*gensec_security
)->private_data
= NULL
;
595 (*gensec_security
)->subcontext
= true;
596 (*gensec_security
)->want_features
= parent
->want_features
;
597 (*gensec_security
)->max_update_size
= parent
->max_update_size
;
598 (*gensec_security
)->dcerpc_auth_level
= parent
->dcerpc_auth_level
;
599 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
600 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, parent
->settings
);
601 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
607 Start the GENSEC system, in client mode, returning a context pointer.
608 @param mem_ctx The parent TALLOC memory context.
609 @param gensec_security Returned GENSEC context pointer.
610 @note The mem_ctx is only a parent and may be NULL.
612 _PUBLIC_ NTSTATUS
gensec_client_start(TALLOC_CTX
*mem_ctx
,
613 struct gensec_security
**gensec_security
,
614 struct gensec_settings
*settings
)
618 if (settings
== NULL
) {
619 DEBUG(0,("gensec_client_start: no settings given!\n"));
620 return NT_STATUS_INTERNAL_ERROR
;
623 status
= gensec_start(mem_ctx
, settings
, NULL
, gensec_security
);
624 if (!NT_STATUS_IS_OK(status
)) {
627 (*gensec_security
)->gensec_role
= GENSEC_CLIENT
;
635 Start the GENSEC system, in server mode, returning a context pointer.
636 @param mem_ctx The parent TALLOC memory context.
637 @param gensec_security Returned GENSEC context pointer.
638 @note The mem_ctx is only a parent and may be NULL.
640 _PUBLIC_ NTSTATUS
gensec_server_start(TALLOC_CTX
*mem_ctx
,
641 struct gensec_settings
*settings
,
642 struct auth4_context
*auth_context
,
643 struct gensec_security
**gensec_security
)
648 DEBUG(0,("gensec_server_start: no settings given!\n"));
649 return NT_STATUS_INTERNAL_ERROR
;
652 status
= gensec_start(mem_ctx
, settings
, auth_context
, gensec_security
);
653 if (!NT_STATUS_IS_OK(status
)) {
656 (*gensec_security
)->gensec_role
= GENSEC_SERVER
;
661 NTSTATUS
gensec_start_mech(struct gensec_security
*gensec_security
)
665 if (gensec_security
->credentials
) {
666 const char *forced_mech
= cli_credentials_get_forced_sasl_mech(gensec_security
->credentials
);
668 (gensec_security
->ops
->sasl_name
== NULL
||
669 strcasecmp(forced_mech
, gensec_security
->ops
->sasl_name
) != 0)) {
670 DEBUG(5, ("GENSEC mechanism %s (%s) skipped, as it "
671 "did not match forced mechanism %s\n",
672 gensec_security
->ops
->name
,
673 gensec_security
->ops
->sasl_name
,
675 return NT_STATUS_INVALID_PARAMETER
;
678 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
679 gensec_security
->subcontext
? "sub" : "",
680 gensec_security
->ops
->name
));
681 switch (gensec_security
->gensec_role
) {
683 if (gensec_security
->ops
->client_start
) {
684 status
= gensec_security
->ops
->client_start(gensec_security
);
685 if (!NT_STATUS_IS_OK(status
)) {
686 DEBUG(gensec_security
->subcontext
?4:2, ("Failed to start GENSEC client mech %s: %s\n",
687 gensec_security
->ops
->name
, nt_errstr(status
)));
693 if (gensec_security
->ops
->server_start
) {
694 status
= gensec_security
->ops
->server_start(gensec_security
);
695 if (!NT_STATUS_IS_OK(status
)) {
696 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
697 gensec_security
->ops
->name
, nt_errstr(status
)));
703 return NT_STATUS_INVALID_PARAMETER
;
707 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
711 NTSTATUS
gensec_start_mech_by_ops(struct gensec_security
*gensec_security
,
712 const struct gensec_security_ops
*ops
)
714 gensec_security
->ops
= ops
;
715 return gensec_start_mech(gensec_security
);
720 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
721 * @param gensec_security GENSEC context pointer.
722 * @param auth_type DCERPC auth type
723 * @param auth_level DCERPC auth level
726 _PUBLIC_ NTSTATUS
gensec_start_mech_by_authtype(struct gensec_security
*gensec_security
,
727 uint8_t auth_type
, uint8_t auth_level
)
729 gensec_security
->ops
= gensec_security_by_auth_type(gensec_security
, auth_type
);
730 if (!gensec_security
->ops
) {
731 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type
));
732 return NT_STATUS_INVALID_PARAMETER
;
734 gensec_security
->dcerpc_auth_level
= auth_level
;
736 * We need to reset sign/seal in order to reset it.
737 * We may got some default features inherited by the credentials
739 gensec_security
->want_features
&= ~GENSEC_FEATURE_SIGN
;
740 gensec_security
->want_features
&= ~GENSEC_FEATURE_SEAL
;
741 gensec_want_feature(gensec_security
, GENSEC_FEATURE_DCE_STYLE
);
742 gensec_want_feature(gensec_security
, GENSEC_FEATURE_ASYNC_REPLIES
);
743 if (auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
744 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
745 } else if (auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
746 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
747 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SEAL
);
748 } else if (auth_level
== DCERPC_AUTH_LEVEL_CONNECT
) {
749 /* Default features */
751 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
753 return NT_STATUS_INVALID_PARAMETER
;
756 return gensec_start_mech(gensec_security
);
759 _PUBLIC_
const char *gensec_get_name_by_authtype(struct gensec_security
*gensec_security
, uint8_t authtype
)
761 const struct gensec_security_ops
*ops
;
762 ops
= gensec_security_by_auth_type(gensec_security
, authtype
);
770 _PUBLIC_
const char *gensec_get_name_by_oid(struct gensec_security
*gensec_security
,
771 const char *oid_string
)
773 const struct gensec_security_ops
*ops
;
774 ops
= gensec_security_by_oid(gensec_security
, oid_string
);
782 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
784 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
785 * well-known #define to hook it in.
788 _PUBLIC_ NTSTATUS
gensec_start_mech_by_oid(struct gensec_security
*gensec_security
,
789 const char *mech_oid
)
791 SMB_ASSERT(gensec_security
!= NULL
);
793 gensec_security
->ops
= gensec_security_by_oid(gensec_security
, mech_oid
);
794 if (!gensec_security
->ops
) {
795 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid
));
796 return NT_STATUS_INVALID_PARAMETER
;
798 return gensec_start_mech(gensec_security
);
802 * Start a GENSEC sub-mechanism by a well know SASL name
806 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_name(struct gensec_security
*gensec_security
,
807 const char *sasl_name
)
809 gensec_security
->ops
= gensec_security_by_sasl_name(gensec_security
, sasl_name
);
810 if (!gensec_security
->ops
) {
811 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name
));
812 return NT_STATUS_INVALID_PARAMETER
;
814 return gensec_start_mech(gensec_security
);
818 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
822 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_list(struct gensec_security
*gensec_security
,
823 const char **sasl_names
)
825 NTSTATUS nt_status
= NT_STATUS_INVALID_PARAMETER
;
826 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
827 const struct gensec_security_ops
**ops
;
830 return NT_STATUS_NO_MEMORY
;
832 ops
= gensec_security_by_sasl_list(gensec_security
, mem_ctx
, sasl_names
);
834 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
835 str_list_join(mem_ctx
,
837 talloc_free(mem_ctx
);
838 return NT_STATUS_INVALID_PARAMETER
;
840 for (i
=0; ops
[i
]; i
++) {
841 nt_status
= gensec_start_mech_by_ops(gensec_security
, ops
[i
]);
842 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_INVALID_PARAMETER
)) {
846 talloc_free(mem_ctx
);
851 * Start a GENSEC sub-mechanism by an internal name
855 _PUBLIC_ NTSTATUS
gensec_start_mech_by_name(struct gensec_security
*gensec_security
,
858 gensec_security
->ops
= gensec_security_by_name(gensec_security
, name
);
859 if (!gensec_security
->ops
) {
860 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name
));
861 return NT_STATUS_INVALID_PARAMETER
;
863 return gensec_start_mech(gensec_security
);
867 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
871 _PUBLIC_ NTSTATUS
gensec_set_credentials(struct gensec_security
*gensec_security
, struct cli_credentials
*credentials
)
873 gensec_security
->credentials
= talloc_reference(gensec_security
, credentials
);
874 NT_STATUS_HAVE_NO_MEMORY(gensec_security
->credentials
);
875 gensec_want_feature(gensec_security
, cli_credentials_get_gensec_features(gensec_security
->credentials
));
880 register a GENSEC backend.
882 The 'name' can be later used by other backends to find the operations
883 structure for this backend.
885 _PUBLIC_ NTSTATUS
gensec_register(const struct gensec_security_ops
*ops
)
887 if (gensec_security_by_name(NULL
, ops
->name
) != NULL
) {
888 /* its already registered! */
889 DEBUG(0,("GENSEC backend '%s' already registered\n",
891 return NT_STATUS_OBJECT_NAME_COLLISION
;
894 generic_security_ops
= talloc_realloc(talloc_autofree_context(),
895 generic_security_ops
,
896 const struct gensec_security_ops
*,
897 gensec_num_backends
+2);
898 if (!generic_security_ops
) {
899 return NT_STATUS_NO_MEMORY
;
902 generic_security_ops
[gensec_num_backends
] = ops
;
903 gensec_num_backends
++;
904 generic_security_ops
[gensec_num_backends
] = NULL
;
906 DEBUG(3,("GENSEC backend '%s' registered\n",
913 return the GENSEC interface version, and the size of some critical types
914 This can be used by backends to either detect compilation errors, or provide
915 multiple implementations for different smbd compilation options in one module
917 _PUBLIC_
const struct gensec_critical_sizes
*gensec_interface_version(void)
919 static const struct gensec_critical_sizes critical_sizes
= {
920 GENSEC_INTERFACE_VERSION
,
921 sizeof(struct gensec_security_ops
),
922 sizeof(struct gensec_security
),
925 return &critical_sizes
;
928 static int sort_gensec(const struct gensec_security_ops
**gs1
, const struct gensec_security_ops
**gs2
) {
929 return (*gs2
)->priority
- (*gs1
)->priority
;
932 int gensec_setting_int(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, int default_value
)
934 return lpcfg_parm_int(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
937 bool gensec_setting_bool(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, bool default_value
)
939 return lpcfg_parm_bool(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
943 initialise the GENSEC subsystem
945 _PUBLIC_ NTSTATUS
gensec_init(void)
947 static bool initialized
= false;
948 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
949 #ifdef STATIC_gensec_MODULES
950 STATIC_gensec_MODULES_PROTO
;
951 init_module_fn static_init
[] = { STATIC_gensec_MODULES
};
953 init_module_fn
*static_init
= NULL
;
955 init_module_fn
*shared_init
;
957 if (initialized
) return NT_STATUS_OK
;
960 shared_init
= load_samba_modules(NULL
, "gensec");
962 run_init_functions(static_init
);
963 run_init_functions(shared_init
);
965 talloc_free(shared_init
);
967 TYPESAFE_QSORT(generic_security_ops
, gensec_num_backends
, sort_gensec
);