torture: extend FSCTL_[GET/SET]_COMPRESSION tests
[Samba.git] / auth / gensec / gensec_start.c
blob3ae64d5683fd86270c5a58d8f61854c7b9c0e57b
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 "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
60 * otherwise
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
68 * more compplex.
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;
79 if (creds) {
80 use_kerberos = cli_credentials_get_kerberos_state(creds);
83 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
84 /* noop */
87 new_gensec_list = talloc_array(mem_ctx,
88 const struct gensec_security_ops *,
89 num_mechs_in + 1);
90 if (!new_gensec_list) {
91 return NULL;
94 j = 0;
95 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
96 int oid_idx;
97 bool keep = false;
99 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
100 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
101 keep = true;
102 break;
106 switch (use_kerberos) {
107 case CRED_AUTO_USE_KERBEROS:
108 keep = true;
109 break;
111 case CRED_DONT_USE_KERBEROS:
112 if (old_gensec_list[i]->kerberos == false) {
113 keep = true;
116 break;
118 case CRED_MUST_USE_KERBEROS:
119 if (old_gensec_list[i]->kerberos == true) {
120 keep = true;
123 break;
124 default:
125 /* Can't happen or invalid parameter */
126 return NULL;
129 if (!keep) {
130 continue;
133 new_gensec_list[j] = old_gensec_list[i];
134 j++;
136 new_gensec_list[j] = NULL;
138 return new_gensec_list;
141 _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs(
142 struct gensec_security *gensec_security,
143 TALLOC_CTX *mem_ctx)
145 struct cli_credentials *creds = NULL;
146 const struct gensec_security_ops * const *backends = gensec_security_all();
148 if (gensec_security != NULL) {
149 creds = gensec_get_credentials(gensec_security);
151 if (gensec_security->settings->backends) {
152 backends = gensec_security->settings->backends;
156 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
160 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
161 uint8_t auth_type)
163 int i;
164 const struct gensec_security_ops **backends;
165 const struct gensec_security_ops *backend;
166 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
167 if (!mem_ctx) {
168 return NULL;
170 backends = gensec_security_mechs(gensec_security, mem_ctx);
171 for (i=0; backends && backends[i]; i++) {
172 if (!gensec_security_ops_enabled(backends[i], gensec_security))
173 continue;
174 if (backends[i]->auth_type == auth_type) {
175 backend = backends[i];
176 talloc_free(mem_ctx);
177 return backend;
180 talloc_free(mem_ctx);
182 return NULL;
185 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
186 struct gensec_security *gensec_security,
187 const char *oid_string)
189 int i, j;
190 const struct gensec_security_ops **backends;
191 const struct gensec_security_ops *backend;
192 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
193 if (!mem_ctx) {
194 return NULL;
196 backends = gensec_security_mechs(gensec_security, mem_ctx);
197 for (i=0; backends && backends[i]; i++) {
198 if (gensec_security != NULL &&
199 !gensec_security_ops_enabled(backends[i],
200 gensec_security))
201 continue;
202 if (backends[i]->oid) {
203 for (j=0; backends[i]->oid[j]; j++) {
204 if (backends[i]->oid[j] &&
205 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
206 backend = backends[i];
207 talloc_free(mem_ctx);
208 return backend;
213 talloc_free(mem_ctx);
215 return NULL;
218 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
219 struct gensec_security *gensec_security,
220 const char *sasl_name)
222 int i;
223 const struct gensec_security_ops **backends;
224 const struct gensec_security_ops *backend;
225 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
226 if (!mem_ctx) {
227 return NULL;
229 backends = gensec_security_mechs(gensec_security, mem_ctx);
230 for (i=0; backends && backends[i]; i++) {
231 if (!gensec_security_ops_enabled(backends[i], gensec_security))
232 continue;
233 if (backends[i]->sasl_name
234 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
235 backend = backends[i];
236 talloc_free(mem_ctx);
237 return backend;
240 talloc_free(mem_ctx);
242 return NULL;
245 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
246 struct gensec_security *gensec_security,
247 uint32_t auth_type)
249 int i;
250 const struct gensec_security_ops **backends;
251 const struct gensec_security_ops *backend;
252 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
253 if (!mem_ctx) {
254 return NULL;
256 backends = gensec_security_mechs(gensec_security, mem_ctx);
257 for (i=0; backends && backends[i]; i++) {
258 if (!gensec_security_ops_enabled(backends[i], gensec_security))
259 continue;
260 if (backends[i]->auth_type == auth_type) {
261 backend = backends[i];
262 talloc_free(mem_ctx);
263 return backend;
266 talloc_free(mem_ctx);
268 return NULL;
271 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
272 const char *name)
274 int i;
275 const struct gensec_security_ops **backends;
276 const struct gensec_security_ops *backend;
277 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
278 if (!mem_ctx) {
279 return NULL;
281 backends = gensec_security_mechs(gensec_security, mem_ctx);
282 for (i=0; backends && backends[i]; i++) {
283 if (gensec_security != NULL &&
284 !gensec_security_ops_enabled(backends[i], gensec_security))
285 continue;
286 if (backends[i]->name
287 && (strcmp(backends[i]->name, name) == 0)) {
288 backend = backends[i];
289 talloc_free(mem_ctx);
290 return backend;
293 talloc_free(mem_ctx);
294 return NULL;
298 * Return a unique list of security subsystems from those specified in
299 * the list of SASL names.
301 * Use the list of enabled GENSEC mechanisms from the credentials
302 * attached to the gensec_security, and return in our preferred order.
305 static const struct gensec_security_ops **gensec_security_by_sasl_list(
306 struct gensec_security *gensec_security,
307 TALLOC_CTX *mem_ctx,
308 const char **sasl_names)
310 const struct gensec_security_ops **backends_out;
311 const struct gensec_security_ops **backends;
312 int i, k, sasl_idx;
313 int num_backends_out = 0;
315 if (!sasl_names) {
316 return NULL;
319 backends = gensec_security_mechs(gensec_security, mem_ctx);
321 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
322 if (!backends_out) {
323 return NULL;
325 backends_out[0] = NULL;
327 /* Find backends in our preferred order, by walking our list,
328 * then looking in the supplied list */
329 for (i=0; backends && backends[i]; i++) {
330 if (gensec_security != NULL &&
331 !gensec_security_ops_enabled(backends[i], gensec_security))
332 continue;
333 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
334 if (!backends[i]->sasl_name ||
335 !(strcmp(backends[i]->sasl_name,
336 sasl_names[sasl_idx]) == 0)) {
337 continue;
340 for (k=0; backends_out[k]; k++) {
341 if (backends_out[k] == backends[i]) {
342 break;
346 if (k < num_backends_out) {
347 /* already in there */
348 continue;
351 backends_out = talloc_realloc(mem_ctx, backends_out,
352 const struct gensec_security_ops *,
353 num_backends_out + 2);
354 if (!backends_out) {
355 return NULL;
358 backends_out[num_backends_out] = backends[i];
359 num_backends_out++;
360 backends_out[num_backends_out] = NULL;
363 return backends_out;
367 * Return a unique list of security subsystems from those specified in
368 * the OID list. That is, where two OIDs refer to the same module,
369 * return that module only once.
371 * Use the list of enabled GENSEC mechanisms from the credentials
372 * attached to the gensec_security, and return in our preferred order.
375 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
376 struct gensec_security *gensec_security,
377 TALLOC_CTX *mem_ctx,
378 const char * const *oid_strings,
379 const char *skip)
381 struct gensec_security_ops_wrapper *backends_out;
382 const struct gensec_security_ops **backends;
383 int i, j, k, oid_idx;
384 int num_backends_out = 0;
386 if (!oid_strings) {
387 return NULL;
390 backends = gensec_security_mechs(gensec_security, gensec_security);
392 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
393 if (!backends_out) {
394 return NULL;
396 backends_out[0].op = NULL;
397 backends_out[0].oid = NULL;
399 /* Find backends in our preferred order, by walking our list,
400 * then looking in the supplied list */
401 for (i=0; backends && backends[i]; i++) {
402 if (gensec_security != NULL &&
403 !gensec_security_ops_enabled(backends[i], gensec_security))
404 continue;
405 if (!backends[i]->oid) {
406 continue;
408 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
409 if (strcmp(oid_strings[oid_idx], skip) == 0) {
410 continue;
413 for (j=0; backends[i]->oid[j]; j++) {
414 if (!backends[i]->oid[j] ||
415 !(strcmp(backends[i]->oid[j],
416 oid_strings[oid_idx]) == 0)) {
417 continue;
420 for (k=0; backends_out[k].op; k++) {
421 if (backends_out[k].op == backends[i]) {
422 break;
426 if (k < num_backends_out) {
427 /* already in there */
428 continue;
431 backends_out = talloc_realloc(mem_ctx, backends_out,
432 struct gensec_security_ops_wrapper,
433 num_backends_out + 2);
434 if (!backends_out) {
435 return NULL;
438 backends_out[num_backends_out].op = backends[i];
439 backends_out[num_backends_out].oid = backends[i]->oid[j];
440 num_backends_out++;
441 backends_out[num_backends_out].op = NULL;
442 backends_out[num_backends_out].oid = NULL;
446 return backends_out;
450 * Return OIDS from the security subsystems listed
453 static const char **gensec_security_oids_from_ops(
454 struct gensec_security *gensec_security,
455 TALLOC_CTX *mem_ctx,
456 const struct gensec_security_ops * const *ops,
457 const char *skip)
459 int i;
460 int j = 0;
461 int k;
462 const char **oid_list;
463 if (!ops) {
464 return NULL;
466 oid_list = talloc_array(mem_ctx, const char *, 1);
467 if (!oid_list) {
468 return NULL;
471 for (i=0; ops && ops[i]; i++) {
472 if (gensec_security != NULL &&
473 !gensec_security_ops_enabled(ops[i], gensec_security)) {
474 continue;
476 if (!ops[i]->oid) {
477 continue;
480 for (k = 0; ops[i]->oid[k]; k++) {
481 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
482 } else {
483 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
484 if (!oid_list) {
485 return NULL;
487 oid_list[j] = ops[i]->oid[k];
488 j++;
492 oid_list[j] = NULL;
493 return oid_list;
498 * Return OIDS from the security subsystems listed
501 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
502 const struct gensec_security_ops_wrapper *wops)
504 int i;
505 int j = 0;
506 int k;
507 const char **oid_list;
508 if (!wops) {
509 return NULL;
511 oid_list = talloc_array(mem_ctx, const char *, 1);
512 if (!oid_list) {
513 return NULL;
516 for (i=0; wops[i].op; i++) {
517 if (!wops[i].op->oid) {
518 continue;
521 for (k = 0; wops[i].op->oid[k]; k++) {
522 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
523 if (!oid_list) {
524 return NULL;
526 oid_list[j] = wops[i].op->oid[k];
527 j++;
530 oid_list[j] = NULL;
531 return oid_list;
536 * Return all the security subsystems currently enabled on a GENSEC context.
538 * This is taken from a list attached to the cli_credentials, and
539 * skips the OID in 'skip'. (Typically the SPNEGO OID)
543 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
544 TALLOC_CTX *mem_ctx,
545 const char *skip)
547 const struct gensec_security_ops **ops;
549 ops = gensec_security_mechs(gensec_security, mem_ctx);
551 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
555 Start the GENSEC system, returning a context pointer.
556 @param mem_ctx The parent TALLOC memory context.
557 @param gensec_security Returned GENSEC context pointer.
558 @note The mem_ctx is only a parent and may be NULL.
559 @note, the auth context is moved to be a referenced pointer of the
560 @ gensec_security return
562 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
563 struct gensec_settings *settings,
564 struct auth4_context *auth_context,
565 struct gensec_security **gensec_security)
567 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
568 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
570 (*gensec_security)->max_update_size = 0;
572 SMB_ASSERT(settings->lp_ctx != NULL);
573 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
575 /* We need to reference this, not steal, as the caller may be
576 * python, which won't like it if we steal it's object away
577 * from it */
578 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
580 return NT_STATUS_OK;
584 * Start a GENSEC subcontext, with a copy of the properties of the parent
585 * @param mem_ctx The parent TALLOC memory context.
586 * @param parent The parent GENSEC context
587 * @param gensec_security Returned GENSEC context pointer.
588 * @note Used by SPNEGO in particular, for the actual implementation mechanism
591 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
592 struct gensec_security *parent,
593 struct gensec_security **gensec_security)
595 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
596 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
598 (**gensec_security) = *parent;
599 (*gensec_security)->ops = NULL;
600 (*gensec_security)->private_data = NULL;
602 (*gensec_security)->subcontext = true;
603 (*gensec_security)->want_features = parent->want_features;
604 (*gensec_security)->max_update_size = parent->max_update_size;
605 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
606 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
607 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
608 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
610 return NT_STATUS_OK;
614 Start the GENSEC system, in client mode, returning a context pointer.
615 @param mem_ctx The parent TALLOC memory context.
616 @param gensec_security Returned GENSEC context pointer.
617 @note The mem_ctx is only a parent and may be NULL.
619 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
620 struct gensec_security **gensec_security,
621 struct gensec_settings *settings)
623 NTSTATUS status;
625 if (settings == NULL) {
626 DEBUG(0,("gensec_client_start: no settings given!\n"));
627 return NT_STATUS_INTERNAL_ERROR;
630 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
631 if (!NT_STATUS_IS_OK(status)) {
632 return status;
634 (*gensec_security)->gensec_role = GENSEC_CLIENT;
636 return status;
642 Start the GENSEC system, in server mode, returning a context pointer.
643 @param mem_ctx The parent TALLOC memory context.
644 @param gensec_security Returned GENSEC context pointer.
645 @note The mem_ctx is only a parent and may be NULL.
647 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
648 struct gensec_settings *settings,
649 struct auth4_context *auth_context,
650 struct gensec_security **gensec_security)
652 NTSTATUS status;
654 if (!settings) {
655 DEBUG(0,("gensec_server_start: no settings given!\n"));
656 return NT_STATUS_INTERNAL_ERROR;
659 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
660 if (!NT_STATUS_IS_OK(status)) {
661 return status;
663 (*gensec_security)->gensec_role = GENSEC_SERVER;
665 return status;
668 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
670 NTSTATUS status;
671 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
672 gensec_security->subcontext ? "sub" : "",
673 gensec_security->ops->name));
674 switch (gensec_security->gensec_role) {
675 case GENSEC_CLIENT:
676 if (gensec_security->ops->client_start) {
677 status = gensec_security->ops->client_start(gensec_security);
678 if (!NT_STATUS_IS_OK(status)) {
679 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
680 gensec_security->ops->name, nt_errstr(status)));
682 return status;
684 break;
685 case GENSEC_SERVER:
686 if (gensec_security->ops->server_start) {
687 status = gensec_security->ops->server_start(gensec_security);
688 if (!NT_STATUS_IS_OK(status)) {
689 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
690 gensec_security->ops->name, nt_errstr(status)));
692 return status;
694 break;
696 return NT_STATUS_INVALID_PARAMETER;
700 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
704 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
705 const struct gensec_security_ops *ops)
707 gensec_security->ops = ops;
708 return gensec_start_mech(gensec_security);
713 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
714 * @param gensec_security GENSEC context pointer.
715 * @param auth_type DCERPC auth type
716 * @param auth_level DCERPC auth level
719 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
720 uint8_t auth_type, uint8_t auth_level)
722 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
723 if (!gensec_security->ops) {
724 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
725 return NT_STATUS_INVALID_PARAMETER;
727 gensec_security->dcerpc_auth_level = auth_level;
728 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
729 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
730 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
731 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
732 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
733 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
734 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
735 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
736 /* Default features */
737 } else {
738 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
739 auth_level));
740 return NT_STATUS_INVALID_PARAMETER;
743 return gensec_start_mech(gensec_security);
746 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
748 const struct gensec_security_ops *ops;
749 ops = gensec_security_by_authtype(gensec_security, authtype);
750 if (ops) {
751 return ops->name;
753 return NULL;
757 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
758 const char *oid_string)
760 const struct gensec_security_ops *ops;
761 ops = gensec_security_by_oid(gensec_security, oid_string);
762 if (ops) {
763 return ops->name;
765 return oid_string;
769 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
771 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
772 * well-known #define to hook it in.
775 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
776 const char *mech_oid)
778 SMB_ASSERT(gensec_security != NULL);
780 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
781 if (!gensec_security->ops) {
782 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
783 return NT_STATUS_INVALID_PARAMETER;
785 return gensec_start_mech(gensec_security);
789 * Start a GENSEC sub-mechanism by a well know SASL name
793 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
794 const char *sasl_name)
796 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
797 if (!gensec_security->ops) {
798 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
799 return NT_STATUS_INVALID_PARAMETER;
801 return gensec_start_mech(gensec_security);
805 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
809 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
810 const char **sasl_names)
812 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
813 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
814 const struct gensec_security_ops **ops;
815 int i;
816 if (!mem_ctx) {
817 return NT_STATUS_NO_MEMORY;
819 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
820 if (!ops || !*ops) {
821 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
822 str_list_join(mem_ctx,
823 sasl_names, ' ')));
824 talloc_free(mem_ctx);
825 return NT_STATUS_INVALID_PARAMETER;
827 for (i=0; ops[i]; i++) {
828 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
829 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
830 break;
833 talloc_free(mem_ctx);
834 return nt_status;
838 * Start a GENSEC sub-mechanism by an internal name
842 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
843 const char *name)
845 gensec_security->ops = gensec_security_by_name(gensec_security, name);
846 if (!gensec_security->ops) {
847 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
848 return NT_STATUS_INVALID_PARAMETER;
850 return gensec_start_mech(gensec_security);
854 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
858 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
860 gensec_security->credentials = talloc_reference(gensec_security, credentials);
861 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
862 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
863 return NT_STATUS_OK;
867 register a GENSEC backend.
869 The 'name' can be later used by other backends to find the operations
870 structure for this backend.
872 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
874 if (gensec_security_by_name(NULL, ops->name) != NULL) {
875 /* its already registered! */
876 DEBUG(0,("GENSEC backend '%s' already registered\n",
877 ops->name));
878 return NT_STATUS_OBJECT_NAME_COLLISION;
881 generic_security_ops = talloc_realloc(talloc_autofree_context(),
882 generic_security_ops,
883 const struct gensec_security_ops *,
884 gensec_num_backends+2);
885 if (!generic_security_ops) {
886 return NT_STATUS_NO_MEMORY;
889 generic_security_ops[gensec_num_backends] = ops;
890 gensec_num_backends++;
891 generic_security_ops[gensec_num_backends] = NULL;
893 DEBUG(3,("GENSEC backend '%s' registered\n",
894 ops->name));
896 return NT_STATUS_OK;
900 return the GENSEC interface version, and the size of some critical types
901 This can be used by backends to either detect compilation errors, or provide
902 multiple implementations for different smbd compilation options in one module
904 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
906 static const struct gensec_critical_sizes critical_sizes = {
907 GENSEC_INTERFACE_VERSION,
908 sizeof(struct gensec_security_ops),
909 sizeof(struct gensec_security),
912 return &critical_sizes;
915 static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
916 return (*gs2)->priority - (*gs1)->priority;
919 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
921 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
924 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
926 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
930 initialise the GENSEC subsystem
932 _PUBLIC_ NTSTATUS gensec_init(void)
934 static bool initialized = false;
935 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
936 #ifdef STATIC_gensec_MODULES
937 STATIC_gensec_MODULES_PROTO;
938 init_module_fn static_init[] = { STATIC_gensec_MODULES };
939 #else
940 init_module_fn *static_init = NULL;
941 #endif
942 init_module_fn *shared_init;
944 if (initialized) return NT_STATUS_OK;
945 initialized = true;
947 shared_init = load_samba_modules(NULL, "gensec");
949 run_init_functions(static_init);
950 run_init_functions(shared_init);
952 talloc_free(shared_init);
954 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
956 return NT_STATUS_OK;