s3:dbwrap: add function dbwrap_wipe()
[Samba/gebeck_regimport.git] / auth / gensec / gensec_start.c
blobea54352918b3e5586292f48452a596b74f9a5849
1 /*
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/>.
23 #include "includes.h"
24 #include "system/network.h"
25 #include "tevent.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 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
56 struct gensec_security_ops **old_gensec_list,
57 struct cli_credentials *creds)
59 struct gensec_security_ops **new_gensec_list;
60 int i, j, num_mechs_in;
61 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
63 if (creds) {
64 use_kerberos = cli_credentials_get_kerberos_state(creds);
67 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
68 if (!talloc_reference(mem_ctx, old_gensec_list)) {
69 return NULL;
71 return old_gensec_list;
74 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
75 /* noop */
78 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
79 if (!new_gensec_list) {
80 return NULL;
83 j = 0;
84 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
85 int oid_idx;
87 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
88 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
89 new_gensec_list[j] = old_gensec_list[i];
90 j++;
91 break;
94 switch (use_kerberos) {
95 case CRED_DONT_USE_KERBEROS:
96 if (old_gensec_list[i]->kerberos == false) {
97 new_gensec_list[j] = old_gensec_list[i];
98 j++;
100 break;
101 case CRED_MUST_USE_KERBEROS:
102 if (old_gensec_list[i]->kerberos == true) {
103 new_gensec_list[j] = old_gensec_list[i];
104 j++;
106 break;
107 default:
108 /* Can't happen or invalid parameter */
109 return NULL;
112 new_gensec_list[j] = NULL;
114 return new_gensec_list;
117 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
118 TALLOC_CTX *mem_ctx)
120 struct gensec_security_ops **backends;
121 backends = gensec_security_all();
122 if (!gensec_security) {
123 if (!talloc_reference(mem_ctx, backends)) {
124 return NULL;
126 return backends;
127 } else {
128 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
129 if (!creds) {
130 if (!talloc_reference(mem_ctx, backends)) {
131 return NULL;
133 return backends;
135 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
139 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
140 uint8_t auth_type)
142 int i;
143 struct gensec_security_ops **backends;
144 const struct gensec_security_ops *backend;
145 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
146 if (!mem_ctx) {
147 return NULL;
149 backends = gensec_security_mechs(gensec_security, mem_ctx);
150 for (i=0; backends && backends[i]; i++) {
151 if (!gensec_security_ops_enabled(backends[i], gensec_security))
152 continue;
153 if (backends[i]->auth_type == auth_type) {
154 backend = backends[i];
155 talloc_free(mem_ctx);
156 return backend;
159 talloc_free(mem_ctx);
161 return NULL;
164 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
165 const char *oid_string)
167 int i, j;
168 struct gensec_security_ops **backends;
169 const struct gensec_security_ops *backend;
170 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
171 if (!mem_ctx) {
172 return NULL;
174 backends = gensec_security_mechs(gensec_security, mem_ctx);
175 for (i=0; backends && backends[i]; i++) {
176 if (gensec_security != NULL &&
177 !gensec_security_ops_enabled(backends[i],
178 gensec_security))
179 continue;
180 if (backends[i]->oid) {
181 for (j=0; backends[i]->oid[j]; j++) {
182 if (backends[i]->oid[j] &&
183 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
184 backend = backends[i];
185 talloc_free(mem_ctx);
186 return backend;
191 talloc_free(mem_ctx);
193 return NULL;
196 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
197 const char *sasl_name)
199 int i;
200 struct gensec_security_ops **backends;
201 const struct gensec_security_ops *backend;
202 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
203 if (!mem_ctx) {
204 return NULL;
206 backends = gensec_security_mechs(gensec_security, mem_ctx);
207 for (i=0; backends && backends[i]; i++) {
208 if (!gensec_security_ops_enabled(backends[i], gensec_security))
209 continue;
210 if (backends[i]->sasl_name
211 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
212 backend = backends[i];
213 talloc_free(mem_ctx);
214 return backend;
217 talloc_free(mem_ctx);
219 return NULL;
222 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
223 const char *name)
225 int i;
226 struct gensec_security_ops **backends;
227 const struct gensec_security_ops *backend;
228 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
229 if (!mem_ctx) {
230 return NULL;
232 backends = gensec_security_mechs(gensec_security, mem_ctx);
233 for (i=0; backends && backends[i]; i++) {
234 if (gensec_security != NULL &&
235 !gensec_security_ops_enabled(backends[i], gensec_security))
236 continue;
237 if (backends[i]->name
238 && (strcmp(backends[i]->name, name) == 0)) {
239 backend = backends[i];
240 talloc_free(mem_ctx);
241 return backend;
244 talloc_free(mem_ctx);
245 return NULL;
249 * Return a unique list of security subsystems from those specified in
250 * the list of SASL names.
252 * Use the list of enabled GENSEC mechanisms from the credentials
253 * attached to the gensec_security, and return in our preferred order.
256 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
257 TALLOC_CTX *mem_ctx,
258 const char **sasl_names)
260 const struct gensec_security_ops **backends_out;
261 struct gensec_security_ops **backends;
262 int i, k, sasl_idx;
263 int num_backends_out = 0;
265 if (!sasl_names) {
266 return NULL;
269 backends = gensec_security_mechs(gensec_security, mem_ctx);
271 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
272 if (!backends_out) {
273 return NULL;
275 backends_out[0] = NULL;
277 /* Find backends in our preferred order, by walking our list,
278 * then looking in the supplied list */
279 for (i=0; backends && backends[i]; i++) {
280 if (gensec_security != NULL &&
281 !gensec_security_ops_enabled(backends[i], gensec_security))
282 continue;
283 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
284 if (!backends[i]->sasl_name ||
285 !(strcmp(backends[i]->sasl_name,
286 sasl_names[sasl_idx]) == 0)) {
287 continue;
290 for (k=0; backends_out[k]; k++) {
291 if (backends_out[k] == backends[i]) {
292 break;
296 if (k < num_backends_out) {
297 /* already in there */
298 continue;
301 backends_out = talloc_realloc(mem_ctx, backends_out,
302 const struct gensec_security_ops *,
303 num_backends_out + 2);
304 if (!backends_out) {
305 return NULL;
308 backends_out[num_backends_out] = backends[i];
309 num_backends_out++;
310 backends_out[num_backends_out] = NULL;
313 return backends_out;
317 * Return a unique list of security subsystems from those specified in
318 * the OID list. That is, where two OIDs refer to the same module,
319 * return that module only once.
321 * Use the list of enabled GENSEC mechanisms from the credentials
322 * attached to the gensec_security, and return in our preferred order.
325 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
326 TALLOC_CTX *mem_ctx,
327 const char **oid_strings,
328 const char *skip)
330 struct gensec_security_ops_wrapper *backends_out;
331 struct gensec_security_ops **backends;
332 int i, j, k, oid_idx;
333 int num_backends_out = 0;
335 if (!oid_strings) {
336 return NULL;
339 backends = gensec_security_mechs(gensec_security, gensec_security);
341 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
342 if (!backends_out) {
343 return NULL;
345 backends_out[0].op = NULL;
346 backends_out[0].oid = NULL;
348 /* Find backends in our preferred order, by walking our list,
349 * then looking in the supplied list */
350 for (i=0; backends && backends[i]; i++) {
351 if (gensec_security != NULL &&
352 !gensec_security_ops_enabled(backends[i], gensec_security))
353 continue;
354 if (!backends[i]->oid) {
355 continue;
357 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
358 if (strcmp(oid_strings[oid_idx], skip) == 0) {
359 continue;
362 for (j=0; backends[i]->oid[j]; j++) {
363 if (!backends[i]->oid[j] ||
364 !(strcmp(backends[i]->oid[j],
365 oid_strings[oid_idx]) == 0)) {
366 continue;
369 for (k=0; backends_out[k].op; k++) {
370 if (backends_out[k].op == backends[i]) {
371 break;
375 if (k < num_backends_out) {
376 /* already in there */
377 continue;
380 backends_out = talloc_realloc(mem_ctx, backends_out,
381 struct gensec_security_ops_wrapper,
382 num_backends_out + 2);
383 if (!backends_out) {
384 return NULL;
387 backends_out[num_backends_out].op = backends[i];
388 backends_out[num_backends_out].oid = backends[i]->oid[j];
389 num_backends_out++;
390 backends_out[num_backends_out].op = NULL;
391 backends_out[num_backends_out].oid = NULL;
395 return backends_out;
399 * Return OIDS from the security subsystems listed
402 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
403 TALLOC_CTX *mem_ctx,
404 struct gensec_security_ops **ops,
405 const char *skip)
407 int i;
408 int j = 0;
409 int k;
410 const char **oid_list;
411 if (!ops) {
412 return NULL;
414 oid_list = talloc_array(mem_ctx, const char *, 1);
415 if (!oid_list) {
416 return NULL;
419 for (i=0; ops && ops[i]; i++) {
420 if (gensec_security != NULL &&
421 !gensec_security_ops_enabled(ops[i], gensec_security)) {
422 continue;
424 if (!ops[i]->oid) {
425 continue;
428 for (k = 0; ops[i]->oid[k]; k++) {
429 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
430 } else {
431 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
432 if (!oid_list) {
433 return NULL;
435 oid_list[j] = ops[i]->oid[k];
436 j++;
440 oid_list[j] = NULL;
441 return oid_list;
446 * Return OIDS from the security subsystems listed
449 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
450 const struct gensec_security_ops_wrapper *wops)
452 int i;
453 int j = 0;
454 int k;
455 const char **oid_list;
456 if (!wops) {
457 return NULL;
459 oid_list = talloc_array(mem_ctx, const char *, 1);
460 if (!oid_list) {
461 return NULL;
464 for (i=0; wops[i].op; i++) {
465 if (!wops[i].op->oid) {
466 continue;
469 for (k = 0; wops[i].op->oid[k]; k++) {
470 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
471 if (!oid_list) {
472 return NULL;
474 oid_list[j] = wops[i].op->oid[k];
475 j++;
478 oid_list[j] = NULL;
479 return oid_list;
484 * Return all the security subsystems currently enabled on a GENSEC context.
486 * This is taken from a list attached to the cli_credentials, and
487 * skips the OID in 'skip'. (Typically the SPNEGO OID)
491 const char **gensec_security_oids(struct gensec_security *gensec_security,
492 TALLOC_CTX *mem_ctx,
493 const char *skip)
495 struct gensec_security_ops **ops
496 = gensec_security_mechs(gensec_security, mem_ctx);
497 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
501 Start the GENSEC system, returning a context pointer.
502 @param mem_ctx The parent TALLOC memory context.
503 @param gensec_security Returned GENSEC context pointer.
504 @note The mem_ctx is only a parent and may be NULL.
505 @note, the auth context is moved to be a referenced pointer of the
506 @ gensec_security return
508 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
509 struct tevent_context *ev,
510 struct gensec_settings *settings,
511 struct auth4_context *auth_context,
512 struct gensec_security **gensec_security)
514 if (ev == NULL) {
515 DEBUG(0, ("No event context available!\n"));
516 return NT_STATUS_INTERNAL_ERROR;
519 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
520 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
522 (*gensec_security)->event_ctx = ev;
523 SMB_ASSERT(settings->lp_ctx != NULL);
524 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
526 /* We need to reference this, not steal, as the caller may be
527 * python, which won't like it if we steal it's object away
528 * from it */
529 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
531 return NT_STATUS_OK;
535 * Start a GENSEC subcontext, with a copy of the properties of the parent
536 * @param mem_ctx The parent TALLOC memory context.
537 * @param parent The parent GENSEC context
538 * @param gensec_security Returned GENSEC context pointer.
539 * @note Used by SPNEGO in particular, for the actual implementation mechanism
542 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
543 struct gensec_security *parent,
544 struct gensec_security **gensec_security)
546 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
547 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
549 (**gensec_security) = *parent;
550 (*gensec_security)->ops = NULL;
551 (*gensec_security)->private_data = NULL;
553 (*gensec_security)->subcontext = true;
554 (*gensec_security)->want_features = parent->want_features;
555 (*gensec_security)->event_ctx = parent->event_ctx;
556 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
557 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
558 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
560 return NT_STATUS_OK;
564 Start the GENSEC system, in client mode, returning a context pointer.
565 @param mem_ctx The parent TALLOC memory context.
566 @param gensec_security Returned GENSEC context pointer.
567 @note The mem_ctx is only a parent and may be NULL.
569 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
570 struct gensec_security **gensec_security,
571 struct tevent_context *ev,
572 struct gensec_settings *settings)
574 NTSTATUS status;
576 if (settings == NULL) {
577 DEBUG(0,("gensec_client_start: no settings given!\n"));
578 return NT_STATUS_INTERNAL_ERROR;
581 status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
582 if (!NT_STATUS_IS_OK(status)) {
583 return status;
585 (*gensec_security)->gensec_role = GENSEC_CLIENT;
587 return status;
593 Start the GENSEC system, in server mode, returning a context pointer.
594 @param mem_ctx The parent TALLOC memory context.
595 @param gensec_security Returned GENSEC context pointer.
596 @note The mem_ctx is only a parent and may be NULL.
598 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
599 struct tevent_context *ev,
600 struct gensec_settings *settings,
601 struct auth4_context *auth_context,
602 struct gensec_security **gensec_security)
604 NTSTATUS status;
606 if (!ev) {
607 DEBUG(0,("gensec_server_start: no event context given!\n"));
608 return NT_STATUS_INTERNAL_ERROR;
611 if (!settings) {
612 DEBUG(0,("gensec_server_start: no settings given!\n"));
613 return NT_STATUS_INTERNAL_ERROR;
616 status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
617 if (!NT_STATUS_IS_OK(status)) {
618 return status;
620 (*gensec_security)->gensec_role = GENSEC_SERVER;
622 return status;
625 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
627 NTSTATUS status;
628 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
629 gensec_security->subcontext ? "sub" : "",
630 gensec_security->ops->name));
631 switch (gensec_security->gensec_role) {
632 case GENSEC_CLIENT:
633 if (gensec_security->ops->client_start) {
634 status = gensec_security->ops->client_start(gensec_security);
635 if (!NT_STATUS_IS_OK(status)) {
636 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
637 gensec_security->ops->name, nt_errstr(status)));
639 return status;
641 break;
642 case GENSEC_SERVER:
643 if (gensec_security->ops->server_start) {
644 status = gensec_security->ops->server_start(gensec_security);
645 if (!NT_STATUS_IS_OK(status)) {
646 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
647 gensec_security->ops->name, nt_errstr(status)));
649 return status;
651 break;
653 return NT_STATUS_INVALID_PARAMETER;
657 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
661 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
662 const struct gensec_security_ops *ops)
664 gensec_security->ops = ops;
665 return gensec_start_mech(gensec_security);
670 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
671 * @param gensec_security GENSEC context pointer.
672 * @param auth_type DCERPC auth type
673 * @param auth_level DCERPC auth level
676 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
677 uint8_t auth_type, uint8_t auth_level)
679 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
680 if (!gensec_security->ops) {
681 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
682 return NT_STATUS_INVALID_PARAMETER;
684 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
685 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
686 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
687 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
688 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
689 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
690 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
691 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
692 /* Default features */
693 } else {
694 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
695 auth_level));
696 return NT_STATUS_INVALID_PARAMETER;
699 return gensec_start_mech(gensec_security);
702 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
704 const struct gensec_security_ops *ops;
705 ops = gensec_security_by_authtype(gensec_security, authtype);
706 if (ops) {
707 return ops->name;
709 return NULL;
713 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
714 const char *oid_string)
716 const struct gensec_security_ops *ops;
717 ops = gensec_security_by_oid(gensec_security, oid_string);
718 if (ops) {
719 return ops->name;
721 return oid_string;
725 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
727 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
728 * well-known #define to hook it in.
731 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
732 const char *mech_oid)
734 SMB_ASSERT(gensec_security != NULL);
736 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
737 if (!gensec_security->ops) {
738 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
739 return NT_STATUS_INVALID_PARAMETER;
741 return gensec_start_mech(gensec_security);
745 * Start a GENSEC sub-mechanism by a well know SASL name
749 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
750 const char *sasl_name)
752 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
753 if (!gensec_security->ops) {
754 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
755 return NT_STATUS_INVALID_PARAMETER;
757 return gensec_start_mech(gensec_security);
761 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
765 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
766 const char **sasl_names)
768 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
769 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
770 const struct gensec_security_ops **ops;
771 int i;
772 if (!mem_ctx) {
773 return NT_STATUS_NO_MEMORY;
775 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
776 if (!ops || !*ops) {
777 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
778 str_list_join(mem_ctx,
779 sasl_names, ' ')));
780 talloc_free(mem_ctx);
781 return NT_STATUS_INVALID_PARAMETER;
783 for (i=0; ops[i]; i++) {
784 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
785 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
786 break;
789 talloc_free(mem_ctx);
790 return nt_status;
794 * Start a GENSEC sub-mechanism by an internal name
798 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
799 const char *name)
801 gensec_security->ops = gensec_security_by_name(gensec_security, name);
802 if (!gensec_security->ops) {
803 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
804 return NT_STATUS_INVALID_PARAMETER;
806 return gensec_start_mech(gensec_security);
810 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
814 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
816 gensec_security->credentials = talloc_reference(gensec_security, credentials);
817 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
818 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
819 return NT_STATUS_OK;
823 register a GENSEC backend.
825 The 'name' can be later used by other backends to find the operations
826 structure for this backend.
828 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
830 if (gensec_security_by_name(NULL, ops->name) != NULL) {
831 /* its already registered! */
832 DEBUG(0,("GENSEC backend '%s' already registered\n",
833 ops->name));
834 return NT_STATUS_OBJECT_NAME_COLLISION;
837 generic_security_ops = talloc_realloc(talloc_autofree_context(),
838 generic_security_ops,
839 struct gensec_security_ops *,
840 gensec_num_backends+2);
841 if (!generic_security_ops) {
842 return NT_STATUS_NO_MEMORY;
845 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
846 gensec_num_backends++;
847 generic_security_ops[gensec_num_backends] = NULL;
849 DEBUG(3,("GENSEC backend '%s' registered\n",
850 ops->name));
852 return NT_STATUS_OK;
856 return the GENSEC interface version, and the size of some critical types
857 This can be used by backends to either detect compilation errors, or provide
858 multiple implementations for different smbd compilation options in one module
860 const struct gensec_critical_sizes *gensec_interface_version(void)
862 static const struct gensec_critical_sizes critical_sizes = {
863 GENSEC_INTERFACE_VERSION,
864 sizeof(struct gensec_security_ops),
865 sizeof(struct gensec_security),
868 return &critical_sizes;
871 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
872 return (*gs2)->priority - (*gs1)->priority;
875 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
877 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
880 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
882 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
886 initialise the GENSEC subsystem
888 _PUBLIC_ NTSTATUS gensec_init(void)
890 static bool initialized = false;
891 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
892 #if _SAMBA_BUILD_ == 4
893 STATIC_gensec_MODULES_PROTO;
894 init_module_fn static_init[] = { STATIC_gensec_MODULES };
895 #else
896 init_module_fn *static_init = NULL;
897 #endif
898 init_module_fn *shared_init;
900 if (initialized) return NT_STATUS_OK;
901 initialized = true;
903 shared_init = load_samba_modules(NULL, "gensec");
905 run_init_functions(static_init);
906 run_init_functions(shared_init);
908 talloc_free(shared_init);
910 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
912 return NT_STATUS_OK;