2 Unix SMB/CIFS implementation.
4 Generic Authentication Interface
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/network.h"
26 #include "../lib/util/tevent_ntstatus.h"
27 #include "librpc/rpc/dcerpc.h"
28 #include "auth/credentials/credentials.h"
29 #include "auth/gensec/gensec.h"
30 #include "lib/param/param.h"
31 #include "lib/util/tsort.h"
32 #include "lib/util/samba_modules.h"
34 /* the list of currently registered GENSEC backends */
35 static struct gensec_security_ops
**generic_security_ops
;
36 static int gensec_num_backends
;
38 /* Return all the registered mechs. Don't modify the return pointer,
39 * but you may talloc_reference it if convient */
40 _PUBLIC_
struct gensec_security_ops
**gensec_security_all(void)
42 return generic_security_ops
;
45 bool gensec_security_ops_enabled(struct gensec_security_ops
*ops
, struct gensec_security
*security
)
47 return lpcfg_parm_bool(security
->settings
->lp_ctx
, NULL
, "gensec", ops
->name
, ops
->enabled
);
50 /* Sometimes we want to force only kerberos, sometimes we want to
51 * force it's avoidance. The old list could be either
52 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
53 * an existing list we have trimmed down)
55 * The intended logic is:
57 * if we are in the default AUTO have kerberos:
58 * - take a reference to the master list
60 * - always add spnego then:
61 * - if we 'MUST' have kerberos:
62 * only add kerberos mechs
63 * - if we 'DONT' want kerberos':
64 * only add non-kerberos mechs
66 * Once we get things like NegoEx or moonshot, this will of course get
70 _PUBLIC_
struct gensec_security_ops
**gensec_use_kerberos_mechs(TALLOC_CTX
*mem_ctx
,
71 struct gensec_security_ops
**old_gensec_list
,
72 struct cli_credentials
*creds
)
74 struct gensec_security_ops
**new_gensec_list
;
75 int i
, j
, num_mechs_in
;
76 enum credentials_use_kerberos use_kerberos
= CRED_AUTO_USE_KERBEROS
;
79 use_kerberos
= cli_credentials_get_kerberos_state(creds
);
82 if (use_kerberos
== CRED_AUTO_USE_KERBEROS
) {
83 if (!talloc_reference(mem_ctx
, old_gensec_list
)) {
86 return old_gensec_list
;
89 for (num_mechs_in
=0; old_gensec_list
&& old_gensec_list
[num_mechs_in
]; num_mechs_in
++) {
93 new_gensec_list
= talloc_array(mem_ctx
, struct gensec_security_ops
*, num_mechs_in
+ 1);
94 if (!new_gensec_list
) {
99 for (i
=0; old_gensec_list
&& old_gensec_list
[i
]; i
++) {
101 bool found_spnego
= false;
102 for (oid_idx
= 0; old_gensec_list
[i
]->oid
&& old_gensec_list
[i
]->oid
[oid_idx
]; oid_idx
++) {
103 if (strcmp(old_gensec_list
[i
]->oid
[oid_idx
], GENSEC_OID_SPNEGO
) == 0) {
104 new_gensec_list
[j
] = old_gensec_list
[i
];
113 switch (use_kerberos
) {
114 case CRED_DONT_USE_KERBEROS
:
115 if (old_gensec_list
[i
]->kerberos
== false) {
116 new_gensec_list
[j
] = old_gensec_list
[i
];
120 case CRED_MUST_USE_KERBEROS
:
121 if (old_gensec_list
[i
]->kerberos
== true) {
122 new_gensec_list
[j
] = old_gensec_list
[i
];
127 /* Can't happen or invalid parameter */
131 new_gensec_list
[j
] = NULL
;
133 return new_gensec_list
;
136 _PUBLIC_
struct gensec_security_ops
**gensec_security_mechs(
137 struct gensec_security
*gensec_security
,
140 struct gensec_security_ops
**backends
;
141 if (!gensec_security
) {
142 backends
= gensec_security_all();
143 if (!talloc_reference(mem_ctx
, backends
)) {
148 struct cli_credentials
*creds
= gensec_get_credentials(gensec_security
);
149 if (gensec_security
->settings
->backends
) {
150 backends
= gensec_security
->settings
->backends
;
152 backends
= gensec_security_all();
155 if (!talloc_reference(mem_ctx
, backends
)) {
160 return gensec_use_kerberos_mechs(mem_ctx
, backends
, creds
);
164 static const struct gensec_security_ops
*gensec_security_by_authtype(struct gensec_security
*gensec_security
,
168 struct gensec_security_ops
**backends
;
169 const struct gensec_security_ops
*backend
;
170 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
174 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
175 for (i
=0; backends
&& backends
[i
]; i
++) {
176 if (!gensec_security_ops_enabled(backends
[i
], gensec_security
))
178 if (backends
[i
]->auth_type
== auth_type
) {
179 backend
= backends
[i
];
180 talloc_free(mem_ctx
);
184 talloc_free(mem_ctx
);
189 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_oid(
190 struct gensec_security
*gensec_security
,
191 const char *oid_string
)
194 struct gensec_security_ops
**backends
;
195 const struct gensec_security_ops
*backend
;
196 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
200 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
201 for (i
=0; backends
&& backends
[i
]; i
++) {
202 if (gensec_security
!= NULL
&&
203 !gensec_security_ops_enabled(backends
[i
],
206 if (backends
[i
]->oid
) {
207 for (j
=0; backends
[i
]->oid
[j
]; j
++) {
208 if (backends
[i
]->oid
[j
] &&
209 (strcmp(backends
[i
]->oid
[j
], oid_string
) == 0)) {
210 backend
= backends
[i
];
211 talloc_free(mem_ctx
);
217 talloc_free(mem_ctx
);
222 _PUBLIC_
const struct gensec_security_ops
*gensec_security_by_sasl_name(
223 struct gensec_security
*gensec_security
,
224 const char *sasl_name
)
227 struct gensec_security_ops
**backends
;
228 const struct gensec_security_ops
*backend
;
229 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
233 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
234 for (i
=0; backends
&& backends
[i
]; i
++) {
235 if (!gensec_security_ops_enabled(backends
[i
], gensec_security
))
237 if (backends
[i
]->sasl_name
238 && (strcmp(backends
[i
]->sasl_name
, sasl_name
) == 0)) {
239 backend
= backends
[i
];
240 talloc_free(mem_ctx
);
244 talloc_free(mem_ctx
);
249 static const struct gensec_security_ops
*gensec_security_by_name(struct gensec_security
*gensec_security
,
253 struct gensec_security_ops
**backends
;
254 const struct gensec_security_ops
*backend
;
255 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
259 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
260 for (i
=0; backends
&& backends
[i
]; i
++) {
261 if (gensec_security
!= NULL
&&
262 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
264 if (backends
[i
]->name
265 && (strcmp(backends
[i
]->name
, name
) == 0)) {
266 backend
= backends
[i
];
267 talloc_free(mem_ctx
);
271 talloc_free(mem_ctx
);
276 * Return a unique list of security subsystems from those specified in
277 * the list of SASL names.
279 * Use the list of enabled GENSEC mechanisms from the credentials
280 * attached to the gensec_security, and return in our preferred order.
283 static const struct gensec_security_ops
**gensec_security_by_sasl_list(
284 struct gensec_security
*gensec_security
,
286 const char **sasl_names
)
288 const struct gensec_security_ops
**backends_out
;
289 struct gensec_security_ops
**backends
;
291 int num_backends_out
= 0;
297 backends
= gensec_security_mechs(gensec_security
, mem_ctx
);
299 backends_out
= talloc_array(mem_ctx
, const struct gensec_security_ops
*, 1);
303 backends_out
[0] = NULL
;
305 /* Find backends in our preferred order, by walking our list,
306 * then looking in the supplied list */
307 for (i
=0; backends
&& backends
[i
]; i
++) {
308 if (gensec_security
!= NULL
&&
309 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
311 for (sasl_idx
= 0; sasl_names
[sasl_idx
]; sasl_idx
++) {
312 if (!backends
[i
]->sasl_name
||
313 !(strcmp(backends
[i
]->sasl_name
,
314 sasl_names
[sasl_idx
]) == 0)) {
318 for (k
=0; backends_out
[k
]; k
++) {
319 if (backends_out
[k
] == backends
[i
]) {
324 if (k
< num_backends_out
) {
325 /* already in there */
329 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
330 const struct gensec_security_ops
*,
331 num_backends_out
+ 2);
336 backends_out
[num_backends_out
] = backends
[i
];
338 backends_out
[num_backends_out
] = NULL
;
345 * Return a unique list of security subsystems from those specified in
346 * the OID list. That is, where two OIDs refer to the same module,
347 * return that module only once.
349 * Use the list of enabled GENSEC mechanisms from the credentials
350 * attached to the gensec_security, and return in our preferred order.
353 _PUBLIC_
const struct gensec_security_ops_wrapper
*gensec_security_by_oid_list(
354 struct gensec_security
*gensec_security
,
356 const char **oid_strings
,
359 struct gensec_security_ops_wrapper
*backends_out
;
360 struct gensec_security_ops
**backends
;
361 int i
, j
, k
, oid_idx
;
362 int num_backends_out
= 0;
368 backends
= gensec_security_mechs(gensec_security
, gensec_security
);
370 backends_out
= talloc_array(mem_ctx
, struct gensec_security_ops_wrapper
, 1);
374 backends_out
[0].op
= NULL
;
375 backends_out
[0].oid
= NULL
;
377 /* Find backends in our preferred order, by walking our list,
378 * then looking in the supplied list */
379 for (i
=0; backends
&& backends
[i
]; i
++) {
380 if (gensec_security
!= NULL
&&
381 !gensec_security_ops_enabled(backends
[i
], gensec_security
))
383 if (!backends
[i
]->oid
) {
386 for (oid_idx
= 0; oid_strings
[oid_idx
]; oid_idx
++) {
387 if (strcmp(oid_strings
[oid_idx
], skip
) == 0) {
391 for (j
=0; backends
[i
]->oid
[j
]; j
++) {
392 if (!backends
[i
]->oid
[j
] ||
393 !(strcmp(backends
[i
]->oid
[j
],
394 oid_strings
[oid_idx
]) == 0)) {
398 for (k
=0; backends_out
[k
].op
; k
++) {
399 if (backends_out
[k
].op
== backends
[i
]) {
404 if (k
< num_backends_out
) {
405 /* already in there */
409 backends_out
= talloc_realloc(mem_ctx
, backends_out
,
410 struct gensec_security_ops_wrapper
,
411 num_backends_out
+ 2);
416 backends_out
[num_backends_out
].op
= backends
[i
];
417 backends_out
[num_backends_out
].oid
= backends
[i
]->oid
[j
];
419 backends_out
[num_backends_out
].op
= NULL
;
420 backends_out
[num_backends_out
].oid
= NULL
;
428 * Return OIDS from the security subsystems listed
431 const char **gensec_security_oids_from_ops(struct gensec_security
*gensec_security
,
433 struct gensec_security_ops
**ops
,
439 const char **oid_list
;
443 oid_list
= talloc_array(mem_ctx
, const char *, 1);
448 for (i
=0; ops
&& ops
[i
]; i
++) {
449 if (gensec_security
!= NULL
&&
450 !gensec_security_ops_enabled(ops
[i
], gensec_security
)) {
457 for (k
= 0; ops
[i
]->oid
[k
]; k
++) {
458 if (skip
&& strcmp(skip
, ops
[i
]->oid
[k
])==0) {
460 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
464 oid_list
[j
] = ops
[i
]->oid
[k
];
475 * Return OIDS from the security subsystems listed
478 _PUBLIC_
const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX
*mem_ctx
,
479 const struct gensec_security_ops_wrapper
*wops
)
484 const char **oid_list
;
488 oid_list
= talloc_array(mem_ctx
, const char *, 1);
493 for (i
=0; wops
[i
].op
; i
++) {
494 if (!wops
[i
].op
->oid
) {
498 for (k
= 0; wops
[i
].op
->oid
[k
]; k
++) {
499 oid_list
= talloc_realloc(mem_ctx
, oid_list
, const char *, j
+ 2);
503 oid_list
[j
] = wops
[i
].op
->oid
[k
];
513 * Return all the security subsystems currently enabled on a GENSEC context.
515 * This is taken from a list attached to the cli_credentials, and
516 * skips the OID in 'skip'. (Typically the SPNEGO OID)
520 _PUBLIC_
const char **gensec_security_oids(struct gensec_security
*gensec_security
,
524 struct gensec_security_ops
**ops
525 = gensec_security_mechs(gensec_security
, mem_ctx
);
526 return gensec_security_oids_from_ops(gensec_security
, mem_ctx
, ops
, skip
);
530 Start the GENSEC system, returning a context pointer.
531 @param mem_ctx The parent TALLOC memory context.
532 @param gensec_security Returned GENSEC context pointer.
533 @note The mem_ctx is only a parent and may be NULL.
534 @note, the auth context is moved to be a referenced pointer of the
535 @ gensec_security return
537 static NTSTATUS
gensec_start(TALLOC_CTX
*mem_ctx
,
538 struct gensec_settings
*settings
,
539 struct auth4_context
*auth_context
,
540 struct gensec_security
**gensec_security
)
542 (*gensec_security
) = talloc_zero(mem_ctx
, struct gensec_security
);
543 NT_STATUS_HAVE_NO_MEMORY(*gensec_security
);
545 (*gensec_security
)->max_update_size
= 0;
547 SMB_ASSERT(settings
->lp_ctx
!= NULL
);
548 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, settings
);
550 /* We need to reference this, not steal, as the caller may be
551 * python, which won't like it if we steal it's object away
553 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, auth_context
);
559 * Start a GENSEC subcontext, with a copy of the properties of the parent
560 * @param mem_ctx The parent TALLOC memory context.
561 * @param parent The parent GENSEC context
562 * @param gensec_security Returned GENSEC context pointer.
563 * @note Used by SPNEGO in particular, for the actual implementation mechanism
566 _PUBLIC_ NTSTATUS
gensec_subcontext_start(TALLOC_CTX
*mem_ctx
,
567 struct gensec_security
*parent
,
568 struct gensec_security
**gensec_security
)
570 (*gensec_security
) = talloc_zero(mem_ctx
, struct gensec_security
);
571 NT_STATUS_HAVE_NO_MEMORY(*gensec_security
);
573 (**gensec_security
) = *parent
;
574 (*gensec_security
)->ops
= NULL
;
575 (*gensec_security
)->private_data
= NULL
;
577 (*gensec_security
)->subcontext
= true;
578 (*gensec_security
)->want_features
= parent
->want_features
;
579 (*gensec_security
)->max_update_size
= parent
->max_update_size
;
580 (*gensec_security
)->dcerpc_auth_level
= parent
->dcerpc_auth_level
;
581 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
582 (*gensec_security
)->settings
= talloc_reference(*gensec_security
, parent
->settings
);
583 (*gensec_security
)->auth_context
= talloc_reference(*gensec_security
, parent
->auth_context
);
589 Start the GENSEC system, in client mode, returning a context pointer.
590 @param mem_ctx The parent TALLOC memory context.
591 @param gensec_security Returned GENSEC context pointer.
592 @note The mem_ctx is only a parent and may be NULL.
594 _PUBLIC_ NTSTATUS
gensec_client_start(TALLOC_CTX
*mem_ctx
,
595 struct gensec_security
**gensec_security
,
596 struct gensec_settings
*settings
)
600 if (settings
== NULL
) {
601 DEBUG(0,("gensec_client_start: no settings given!\n"));
602 return NT_STATUS_INTERNAL_ERROR
;
605 status
= gensec_start(mem_ctx
, settings
, NULL
, gensec_security
);
606 if (!NT_STATUS_IS_OK(status
)) {
609 (*gensec_security
)->gensec_role
= GENSEC_CLIENT
;
617 Start the GENSEC system, in server mode, returning a context pointer.
618 @param mem_ctx The parent TALLOC memory context.
619 @param gensec_security Returned GENSEC context pointer.
620 @note The mem_ctx is only a parent and may be NULL.
622 _PUBLIC_ NTSTATUS
gensec_server_start(TALLOC_CTX
*mem_ctx
,
623 struct gensec_settings
*settings
,
624 struct auth4_context
*auth_context
,
625 struct gensec_security
**gensec_security
)
630 DEBUG(0,("gensec_server_start: no settings given!\n"));
631 return NT_STATUS_INTERNAL_ERROR
;
634 status
= gensec_start(mem_ctx
, settings
, auth_context
, gensec_security
);
635 if (!NT_STATUS_IS_OK(status
)) {
638 (*gensec_security
)->gensec_role
= GENSEC_SERVER
;
643 NTSTATUS
gensec_start_mech(struct gensec_security
*gensec_security
)
646 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
647 gensec_security
->subcontext
? "sub" : "",
648 gensec_security
->ops
->name
));
649 switch (gensec_security
->gensec_role
) {
651 if (gensec_security
->ops
->client_start
) {
652 status
= gensec_security
->ops
->client_start(gensec_security
);
653 if (!NT_STATUS_IS_OK(status
)) {
654 DEBUG(gensec_security
->subcontext
?4:2, ("Failed to start GENSEC client mech %s: %s\n",
655 gensec_security
->ops
->name
, nt_errstr(status
)));
661 if (gensec_security
->ops
->server_start
) {
662 status
= gensec_security
->ops
->server_start(gensec_security
);
663 if (!NT_STATUS_IS_OK(status
)) {
664 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
665 gensec_security
->ops
->name
, nt_errstr(status
)));
671 return NT_STATUS_INVALID_PARAMETER
;
675 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
679 NTSTATUS
gensec_start_mech_by_ops(struct gensec_security
*gensec_security
,
680 const struct gensec_security_ops
*ops
)
682 gensec_security
->ops
= ops
;
683 return gensec_start_mech(gensec_security
);
688 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
689 * @param gensec_security GENSEC context pointer.
690 * @param auth_type DCERPC auth type
691 * @param auth_level DCERPC auth level
694 _PUBLIC_ NTSTATUS
gensec_start_mech_by_authtype(struct gensec_security
*gensec_security
,
695 uint8_t auth_type
, uint8_t auth_level
)
697 gensec_security
->ops
= gensec_security_by_authtype(gensec_security
, auth_type
);
698 if (!gensec_security
->ops
) {
699 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type
));
700 return NT_STATUS_INVALID_PARAMETER
;
702 gensec_security
->dcerpc_auth_level
= auth_level
;
703 gensec_want_feature(gensec_security
, GENSEC_FEATURE_DCE_STYLE
);
704 gensec_want_feature(gensec_security
, GENSEC_FEATURE_ASYNC_REPLIES
);
705 if (auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
706 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
707 } else if (auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
708 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SIGN
);
709 gensec_want_feature(gensec_security
, GENSEC_FEATURE_SEAL
);
710 } else if (auth_level
== DCERPC_AUTH_LEVEL_CONNECT
) {
711 /* Default features */
713 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
715 return NT_STATUS_INVALID_PARAMETER
;
718 return gensec_start_mech(gensec_security
);
721 _PUBLIC_
const char *gensec_get_name_by_authtype(struct gensec_security
*gensec_security
, uint8_t authtype
)
723 const struct gensec_security_ops
*ops
;
724 ops
= gensec_security_by_authtype(gensec_security
, authtype
);
732 _PUBLIC_
const char *gensec_get_name_by_oid(struct gensec_security
*gensec_security
,
733 const char *oid_string
)
735 const struct gensec_security_ops
*ops
;
736 ops
= gensec_security_by_oid(gensec_security
, oid_string
);
744 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
746 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
747 * well-known #define to hook it in.
750 _PUBLIC_ NTSTATUS
gensec_start_mech_by_oid(struct gensec_security
*gensec_security
,
751 const char *mech_oid
)
753 SMB_ASSERT(gensec_security
!= NULL
);
755 gensec_security
->ops
= gensec_security_by_oid(gensec_security
, mech_oid
);
756 if (!gensec_security
->ops
) {
757 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid
));
758 return NT_STATUS_INVALID_PARAMETER
;
760 return gensec_start_mech(gensec_security
);
764 * Start a GENSEC sub-mechanism by a well know SASL name
768 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_name(struct gensec_security
*gensec_security
,
769 const char *sasl_name
)
771 gensec_security
->ops
= gensec_security_by_sasl_name(gensec_security
, sasl_name
);
772 if (!gensec_security
->ops
) {
773 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name
));
774 return NT_STATUS_INVALID_PARAMETER
;
776 return gensec_start_mech(gensec_security
);
780 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
784 _PUBLIC_ NTSTATUS
gensec_start_mech_by_sasl_list(struct gensec_security
*gensec_security
,
785 const char **sasl_names
)
787 NTSTATUS nt_status
= NT_STATUS_INVALID_PARAMETER
;
788 TALLOC_CTX
*mem_ctx
= talloc_new(gensec_security
);
789 const struct gensec_security_ops
**ops
;
792 return NT_STATUS_NO_MEMORY
;
794 ops
= gensec_security_by_sasl_list(gensec_security
, mem_ctx
, sasl_names
);
796 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
797 str_list_join(mem_ctx
,
799 talloc_free(mem_ctx
);
800 return NT_STATUS_INVALID_PARAMETER
;
802 for (i
=0; ops
[i
]; i
++) {
803 nt_status
= gensec_start_mech_by_ops(gensec_security
, ops
[i
]);
804 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_INVALID_PARAMETER
)) {
808 talloc_free(mem_ctx
);
813 * Start a GENSEC sub-mechanism by an internal name
817 _PUBLIC_ NTSTATUS
gensec_start_mech_by_name(struct gensec_security
*gensec_security
,
820 gensec_security
->ops
= gensec_security_by_name(gensec_security
, name
);
821 if (!gensec_security
->ops
) {
822 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name
));
823 return NT_STATUS_INVALID_PARAMETER
;
825 return gensec_start_mech(gensec_security
);
829 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
833 _PUBLIC_ NTSTATUS
gensec_set_credentials(struct gensec_security
*gensec_security
, struct cli_credentials
*credentials
)
835 gensec_security
->credentials
= talloc_reference(gensec_security
, credentials
);
836 NT_STATUS_HAVE_NO_MEMORY(gensec_security
->credentials
);
837 gensec_want_feature(gensec_security
, cli_credentials_get_gensec_features(gensec_security
->credentials
));
842 register a GENSEC backend.
844 The 'name' can be later used by other backends to find the operations
845 structure for this backend.
847 _PUBLIC_ NTSTATUS
gensec_register(const struct gensec_security_ops
*ops
)
849 if (gensec_security_by_name(NULL
, ops
->name
) != NULL
) {
850 /* its already registered! */
851 DEBUG(0,("GENSEC backend '%s' already registered\n",
853 return NT_STATUS_OBJECT_NAME_COLLISION
;
856 generic_security_ops
= talloc_realloc(talloc_autofree_context(),
857 generic_security_ops
,
858 struct gensec_security_ops
*,
859 gensec_num_backends
+2);
860 if (!generic_security_ops
) {
861 return NT_STATUS_NO_MEMORY
;
864 generic_security_ops
[gensec_num_backends
] = discard_const_p(struct gensec_security_ops
, ops
);
865 gensec_num_backends
++;
866 generic_security_ops
[gensec_num_backends
] = NULL
;
868 DEBUG(3,("GENSEC backend '%s' registered\n",
875 return the GENSEC interface version, and the size of some critical types
876 This can be used by backends to either detect compilation errors, or provide
877 multiple implementations for different smbd compilation options in one module
879 _PUBLIC_
const struct gensec_critical_sizes
*gensec_interface_version(void)
881 static const struct gensec_critical_sizes critical_sizes
= {
882 GENSEC_INTERFACE_VERSION
,
883 sizeof(struct gensec_security_ops
),
884 sizeof(struct gensec_security
),
887 return &critical_sizes
;
890 static int sort_gensec(struct gensec_security_ops
**gs1
, struct gensec_security_ops
**gs2
) {
891 return (*gs2
)->priority
- (*gs1
)->priority
;
894 int gensec_setting_int(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, int default_value
)
896 return lpcfg_parm_int(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
899 bool gensec_setting_bool(struct gensec_settings
*settings
, const char *mechanism
, const char *name
, bool default_value
)
901 return lpcfg_parm_bool(settings
->lp_ctx
, NULL
, mechanism
, name
, default_value
);
905 initialise the GENSEC subsystem
907 _PUBLIC_ NTSTATUS
gensec_init(void)
909 static bool initialized
= false;
910 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
911 #ifdef STATIC_gensec_MODULES
912 STATIC_gensec_MODULES_PROTO
;
913 init_module_fn static_init
[] = { STATIC_gensec_MODULES
};
915 init_module_fn
*static_init
= NULL
;
917 init_module_fn
*shared_init
;
919 if (initialized
) return NT_STATUS_OK
;
922 shared_init
= load_samba_modules(NULL
, "gensec");
924 run_init_functions(static_init
);
925 run_init_functions(shared_init
);
927 talloc_free(shared_init
);
929 TYPESAFE_QSORT(generic_security_ops
, gensec_num_backends
, sort_gensec
);