lib: Align nt_time_to_unix_timespec with unix_timespec_to_nt_time
[Samba.git] / auth / gensec / gensec_start.c
blob9910f1a1917ba004ea4536b1d31dd5ad787b31a8
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/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
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 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
161 struct gensec_security *gensec_security,
162 const char *oid_string)
164 int i, j;
165 const struct gensec_security_ops **backends;
166 const struct gensec_security_ops *backend;
167 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
168 if (!mem_ctx) {
169 return NULL;
171 backends = gensec_security_mechs(gensec_security, mem_ctx);
172 for (i=0; backends && backends[i]; i++) {
173 if (gensec_security != NULL &&
174 !gensec_security_ops_enabled(backends[i],
175 gensec_security))
176 continue;
177 if (backends[i]->oid) {
178 for (j=0; backends[i]->oid[j]; j++) {
179 if (backends[i]->oid[j] &&
180 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
181 backend = backends[i];
182 talloc_free(mem_ctx);
183 return backend;
188 talloc_free(mem_ctx);
190 return NULL;
193 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
194 struct gensec_security *gensec_security,
195 const char *sasl_name)
197 int i;
198 const struct gensec_security_ops **backends;
199 const struct gensec_security_ops *backend;
200 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
201 if (!mem_ctx) {
202 return NULL;
204 backends = gensec_security_mechs(gensec_security, mem_ctx);
205 for (i=0; backends && backends[i]; i++) {
206 if (!gensec_security_ops_enabled(backends[i], gensec_security))
207 continue;
208 if (backends[i]->sasl_name
209 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
210 backend = backends[i];
211 talloc_free(mem_ctx);
212 return backend;
215 talloc_free(mem_ctx);
217 return NULL;
220 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
221 struct gensec_security *gensec_security,
222 uint32_t auth_type)
224 int i;
225 const struct gensec_security_ops **backends;
226 const struct gensec_security_ops *backend;
227 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
228 if (!mem_ctx) {
229 return NULL;
231 backends = gensec_security_mechs(gensec_security, mem_ctx);
232 for (i=0; backends && backends[i]; i++) {
233 if (gensec_security != NULL &&
234 !gensec_security_ops_enabled(backends[i], gensec_security)) {
235 continue;
237 if (backends[i]->auth_type == auth_type) {
238 backend = backends[i];
239 talloc_free(mem_ctx);
240 return backend;
243 talloc_free(mem_ctx);
245 return NULL;
248 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
249 const char *name)
251 int i;
252 const struct gensec_security_ops **backends;
253 const struct gensec_security_ops *backend;
254 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
255 if (!mem_ctx) {
256 return NULL;
258 backends = gensec_security_mechs(gensec_security, mem_ctx);
259 for (i=0; backends && backends[i]; i++) {
260 if (gensec_security != NULL &&
261 !gensec_security_ops_enabled(backends[i], gensec_security))
262 continue;
263 if (backends[i]->name
264 && (strcmp(backends[i]->name, name) == 0)) {
265 backend = backends[i];
266 talloc_free(mem_ctx);
267 return backend;
270 talloc_free(mem_ctx);
271 return NULL;
275 * Return a unique list of security subsystems from those specified in
276 * the list of SASL names.
278 * Use the list of enabled GENSEC mechanisms from the credentials
279 * attached to the gensec_security, and return in our preferred order.
282 static const struct gensec_security_ops **gensec_security_by_sasl_list(
283 struct gensec_security *gensec_security,
284 TALLOC_CTX *mem_ctx,
285 const char **sasl_names)
287 const struct gensec_security_ops **backends_out;
288 const struct gensec_security_ops **backends;
289 int i, k, sasl_idx;
290 int num_backends_out = 0;
292 if (!sasl_names) {
293 return NULL;
296 backends = gensec_security_mechs(gensec_security, mem_ctx);
298 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
299 if (!backends_out) {
300 return NULL;
302 backends_out[0] = NULL;
304 /* Find backends in our preferred order, by walking our list,
305 * then looking in the supplied list */
306 for (i=0; backends && backends[i]; i++) {
307 if (gensec_security != NULL &&
308 !gensec_security_ops_enabled(backends[i], gensec_security))
309 continue;
310 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
311 if (!backends[i]->sasl_name ||
312 !(strcmp(backends[i]->sasl_name,
313 sasl_names[sasl_idx]) == 0)) {
314 continue;
317 for (k=0; backends_out[k]; k++) {
318 if (backends_out[k] == backends[i]) {
319 break;
323 if (k < num_backends_out) {
324 /* already in there */
325 continue;
328 backends_out = talloc_realloc(mem_ctx, backends_out,
329 const struct gensec_security_ops *,
330 num_backends_out + 2);
331 if (!backends_out) {
332 return NULL;
335 backends_out[num_backends_out] = backends[i];
336 num_backends_out++;
337 backends_out[num_backends_out] = NULL;
340 return backends_out;
344 * Return a unique list of security subsystems from those specified in
345 * the OID list. That is, where two OIDs refer to the same module,
346 * return that module only once.
348 * Use the list of enabled GENSEC mechanisms from the credentials
349 * attached to the gensec_security, and return in our preferred order.
352 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
353 struct gensec_security *gensec_security,
354 TALLOC_CTX *mem_ctx,
355 const char * const *oid_strings,
356 const char *skip)
358 struct gensec_security_ops_wrapper *backends_out;
359 const struct gensec_security_ops **backends;
360 int i, j, k, oid_idx;
361 int num_backends_out = 0;
363 if (!oid_strings) {
364 return NULL;
367 backends = gensec_security_mechs(gensec_security, gensec_security);
369 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
370 if (!backends_out) {
371 return NULL;
373 backends_out[0].op = NULL;
374 backends_out[0].oid = NULL;
376 /* Find backends in our preferred order, by walking our list,
377 * then looking in the supplied list */
378 for (i=0; backends && backends[i]; i++) {
379 if (gensec_security != NULL &&
380 !gensec_security_ops_enabled(backends[i], gensec_security))
381 continue;
382 if (!backends[i]->oid) {
383 continue;
385 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
386 if (strcmp(oid_strings[oid_idx], skip) == 0) {
387 continue;
390 for (j=0; backends[i]->oid[j]; j++) {
391 if (!backends[i]->oid[j] ||
392 !(strcmp(backends[i]->oid[j],
393 oid_strings[oid_idx]) == 0)) {
394 continue;
397 for (k=0; backends_out[k].op; k++) {
398 if (backends_out[k].op == backends[i]) {
399 break;
403 if (k < num_backends_out) {
404 /* already in there */
405 continue;
408 backends_out = talloc_realloc(mem_ctx, backends_out,
409 struct gensec_security_ops_wrapper,
410 num_backends_out + 2);
411 if (!backends_out) {
412 return NULL;
415 backends_out[num_backends_out].op = backends[i];
416 backends_out[num_backends_out].oid = backends[i]->oid[j];
417 num_backends_out++;
418 backends_out[num_backends_out].op = NULL;
419 backends_out[num_backends_out].oid = NULL;
423 return backends_out;
427 * Return OIDS from the security subsystems listed
430 static const char **gensec_security_oids_from_ops(
431 struct gensec_security *gensec_security,
432 TALLOC_CTX *mem_ctx,
433 const struct gensec_security_ops * const *ops,
434 const char *skip)
436 int i;
437 int j = 0;
438 int k;
439 const char **oid_list;
440 if (!ops) {
441 return NULL;
443 oid_list = talloc_array(mem_ctx, const char *, 1);
444 if (!oid_list) {
445 return NULL;
448 for (i=0; ops && ops[i]; i++) {
449 if (gensec_security != NULL &&
450 !gensec_security_ops_enabled(ops[i], gensec_security)) {
451 continue;
453 if (!ops[i]->oid) {
454 continue;
457 for (k = 0; ops[i]->oid[k]; k++) {
458 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
459 } else {
460 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
461 if (!oid_list) {
462 return NULL;
464 oid_list[j] = ops[i]->oid[k];
465 j++;
469 oid_list[j] = NULL;
470 return oid_list;
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)
481 int i;
482 int j = 0;
483 int k;
484 const char **oid_list;
485 if (!wops) {
486 return NULL;
488 oid_list = talloc_array(mem_ctx, const char *, 1);
489 if (!oid_list) {
490 return NULL;
493 for (i=0; wops[i].op; i++) {
494 if (!wops[i].op->oid) {
495 continue;
498 for (k = 0; wops[i].op->oid[k]; k++) {
499 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
500 if (!oid_list) {
501 return NULL;
503 oid_list[j] = wops[i].op->oid[k];
504 j++;
507 oid_list[j] = NULL;
508 return oid_list;
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,
521 TALLOC_CTX *mem_ctx,
522 const char *skip)
524 const struct gensec_security_ops **ops;
526 ops = gensec_security_mechs(gensec_security, mem_ctx);
528 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
532 Start the GENSEC system, returning a context pointer.
533 @param mem_ctx The parent TALLOC memory context.
534 @param gensec_security Returned GENSEC context pointer.
535 @note The mem_ctx is only a parent and may be NULL.
536 @note, the auth context is moved to be a referenced pointer of the
537 @ gensec_security return
539 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
540 struct gensec_settings *settings,
541 struct auth4_context *auth_context,
542 struct gensec_security **gensec_security)
544 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
545 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
547 (*gensec_security)->max_update_size = 0;
549 SMB_ASSERT(settings->lp_ctx != NULL);
550 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
552 /* We need to reference this, not steal, as the caller may be
553 * python, which won't like it if we steal it's object away
554 * from it */
555 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
557 return NT_STATUS_OK;
561 * Start a GENSEC subcontext, with a copy of the properties of the parent
562 * @param mem_ctx The parent TALLOC memory context.
563 * @param parent The parent GENSEC context
564 * @param gensec_security Returned GENSEC context pointer.
565 * @note Used by SPNEGO in particular, for the actual implementation mechanism
568 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
569 struct gensec_security *parent,
570 struct gensec_security **gensec_security)
572 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
573 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
575 (**gensec_security) = *parent;
576 (*gensec_security)->ops = NULL;
577 (*gensec_security)->private_data = NULL;
579 (*gensec_security)->subcontext = true;
580 (*gensec_security)->want_features = parent->want_features;
581 (*gensec_security)->max_update_size = parent->max_update_size;
582 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
583 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
584 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
585 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
587 return NT_STATUS_OK;
591 Start the GENSEC system, in client mode, returning a context pointer.
592 @param mem_ctx The parent TALLOC memory context.
593 @param gensec_security Returned GENSEC context pointer.
594 @note The mem_ctx is only a parent and may be NULL.
596 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
597 struct gensec_security **gensec_security,
598 struct gensec_settings *settings)
600 NTSTATUS status;
602 if (settings == NULL) {
603 DEBUG(0,("gensec_client_start: no settings given!\n"));
604 return NT_STATUS_INTERNAL_ERROR;
607 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
608 if (!NT_STATUS_IS_OK(status)) {
609 return status;
611 (*gensec_security)->gensec_role = GENSEC_CLIENT;
613 return status;
619 Start the GENSEC system, in server mode, returning a context pointer.
620 @param mem_ctx The parent TALLOC memory context.
621 @param gensec_security Returned GENSEC context pointer.
622 @note The mem_ctx is only a parent and may be NULL.
624 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
625 struct gensec_settings *settings,
626 struct auth4_context *auth_context,
627 struct gensec_security **gensec_security)
629 NTSTATUS status;
631 if (!settings) {
632 DEBUG(0,("gensec_server_start: no settings given!\n"));
633 return NT_STATUS_INTERNAL_ERROR;
636 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
637 if (!NT_STATUS_IS_OK(status)) {
638 return status;
640 (*gensec_security)->gensec_role = GENSEC_SERVER;
642 return status;
645 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
647 NTSTATUS status;
649 if (gensec_security->credentials) {
650 const char *forced_mech = cli_credentials_get_forced_sasl_mech(gensec_security->credentials);
651 if (forced_mech &&
652 (gensec_security->ops->sasl_name == NULL ||
653 strcasecmp(forced_mech, gensec_security->ops->sasl_name) != 0)) {
654 DEBUG(5, ("GENSEC mechanism %s (%s) skipped, as it "
655 "did not match forced mechanism %s\n",
656 gensec_security->ops->name,
657 gensec_security->ops->sasl_name,
658 forced_mech));
659 return NT_STATUS_INVALID_PARAMETER;
662 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
663 gensec_security->subcontext ? "sub" : "",
664 gensec_security->ops->name));
665 switch (gensec_security->gensec_role) {
666 case GENSEC_CLIENT:
667 if (gensec_security->ops->client_start) {
668 status = gensec_security->ops->client_start(gensec_security);
669 if (!NT_STATUS_IS_OK(status)) {
670 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
671 gensec_security->ops->name, nt_errstr(status)));
673 return status;
675 break;
676 case GENSEC_SERVER:
677 if (gensec_security->ops->server_start) {
678 status = gensec_security->ops->server_start(gensec_security);
679 if (!NT_STATUS_IS_OK(status)) {
680 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
681 gensec_security->ops->name, nt_errstr(status)));
683 return status;
685 break;
687 return NT_STATUS_INVALID_PARAMETER;
691 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
695 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
696 const struct gensec_security_ops *ops)
698 gensec_security->ops = ops;
699 return gensec_start_mech(gensec_security);
704 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
705 * @param gensec_security GENSEC context pointer.
706 * @param auth_type DCERPC auth type
707 * @param auth_level DCERPC auth level
710 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
711 uint8_t auth_type, uint8_t auth_level)
713 gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type);
714 if (!gensec_security->ops) {
715 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
716 return NT_STATUS_INVALID_PARAMETER;
718 gensec_security->dcerpc_auth_level = auth_level;
719 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
720 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
721 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
722 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
723 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
724 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
725 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
726 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
727 /* Default features */
728 } else {
729 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
730 auth_level));
731 return NT_STATUS_INVALID_PARAMETER;
734 return gensec_start_mech(gensec_security);
737 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
739 const struct gensec_security_ops *ops;
740 ops = gensec_security_by_auth_type(gensec_security, authtype);
741 if (ops) {
742 return ops->name;
744 return NULL;
748 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
749 const char *oid_string)
751 const struct gensec_security_ops *ops;
752 ops = gensec_security_by_oid(gensec_security, oid_string);
753 if (ops) {
754 return ops->name;
756 return oid_string;
760 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
762 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
763 * well-known #define to hook it in.
766 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
767 const char *mech_oid)
769 SMB_ASSERT(gensec_security != NULL);
771 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
772 if (!gensec_security->ops) {
773 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
774 return NT_STATUS_INVALID_PARAMETER;
776 return gensec_start_mech(gensec_security);
780 * Start a GENSEC sub-mechanism by a well know SASL name
784 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
785 const char *sasl_name)
787 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
788 if (!gensec_security->ops) {
789 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
790 return NT_STATUS_INVALID_PARAMETER;
792 return gensec_start_mech(gensec_security);
796 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
800 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
801 const char **sasl_names)
803 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
804 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
805 const struct gensec_security_ops **ops;
806 int i;
807 if (!mem_ctx) {
808 return NT_STATUS_NO_MEMORY;
810 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
811 if (!ops || !*ops) {
812 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
813 str_list_join(mem_ctx,
814 sasl_names, ' ')));
815 talloc_free(mem_ctx);
816 return NT_STATUS_INVALID_PARAMETER;
818 for (i=0; ops[i]; i++) {
819 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
820 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
821 break;
824 talloc_free(mem_ctx);
825 return nt_status;
829 * Start a GENSEC sub-mechanism by an internal name
833 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
834 const char *name)
836 gensec_security->ops = gensec_security_by_name(gensec_security, name);
837 if (!gensec_security->ops) {
838 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
839 return NT_STATUS_INVALID_PARAMETER;
841 return gensec_start_mech(gensec_security);
845 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
849 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
851 gensec_security->credentials = talloc_reference(gensec_security, credentials);
852 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
853 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
854 return NT_STATUS_OK;
858 register a GENSEC backend.
860 The 'name' can be later used by other backends to find the operations
861 structure for this backend.
863 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
865 if (gensec_security_by_name(NULL, ops->name) != NULL) {
866 /* its already registered! */
867 DEBUG(0,("GENSEC backend '%s' already registered\n",
868 ops->name));
869 return NT_STATUS_OBJECT_NAME_COLLISION;
872 generic_security_ops = talloc_realloc(talloc_autofree_context(),
873 generic_security_ops,
874 const struct gensec_security_ops *,
875 gensec_num_backends+2);
876 if (!generic_security_ops) {
877 return NT_STATUS_NO_MEMORY;
880 generic_security_ops[gensec_num_backends] = ops;
881 gensec_num_backends++;
882 generic_security_ops[gensec_num_backends] = NULL;
884 DEBUG(3,("GENSEC backend '%s' registered\n",
885 ops->name));
887 return NT_STATUS_OK;
891 return the GENSEC interface version, and the size of some critical types
892 This can be used by backends to either detect compilation errors, or provide
893 multiple implementations for different smbd compilation options in one module
895 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
897 static const struct gensec_critical_sizes critical_sizes = {
898 GENSEC_INTERFACE_VERSION,
899 sizeof(struct gensec_security_ops),
900 sizeof(struct gensec_security),
903 return &critical_sizes;
906 static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
907 return (*gs2)->priority - (*gs1)->priority;
910 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
912 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
915 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
917 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
921 initialise the GENSEC subsystem
923 _PUBLIC_ NTSTATUS gensec_init(void)
925 static bool initialized = false;
926 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
927 #ifdef STATIC_gensec_MODULES
928 STATIC_gensec_MODULES_PROTO;
929 init_module_fn static_init[] = { STATIC_gensec_MODULES };
930 #else
931 init_module_fn *static_init = NULL;
932 #endif
933 init_module_fn *shared_init;
935 if (initialized) return NT_STATUS_OK;
936 initialized = true;
938 shared_init = load_samba_modules(NULL, "gensec");
940 run_init_functions(static_init);
941 run_init_functions(shared_init);
943 talloc_free(shared_init);
945 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
947 return NT_STATUS_OK;