s3/smbd: in call_trans2qfilepathinfo call lstat when dealing with posix pathnames
[Samba.git] / auth / gensec / gensec_start.c
blob4c43519f26d415e2dfd0f895eb62ea89e3ac0cd0
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;
78 bool keep_schannel = false;
80 if (creds) {
81 use_kerberos = cli_credentials_get_kerberos_state(creds);
82 if (cli_credentials_get_netlogon_creds(creds) != NULL) {
83 keep_schannel = true;
87 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
88 /* noop */
91 new_gensec_list = talloc_array(mem_ctx,
92 const struct gensec_security_ops *,
93 num_mechs_in + 1);
94 if (!new_gensec_list) {
95 return NULL;
98 j = 0;
99 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
100 int oid_idx;
101 bool keep = false;
103 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
104 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
105 keep = true;
106 break;
110 if (old_gensec_list[i]->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
111 keep = keep_schannel;
114 switch (use_kerberos) {
115 case CRED_AUTO_USE_KERBEROS:
116 keep = true;
117 break;
119 case CRED_DONT_USE_KERBEROS:
120 if (old_gensec_list[i]->kerberos == false) {
121 keep = true;
124 break;
126 case CRED_MUST_USE_KERBEROS:
127 if (old_gensec_list[i]->kerberos == true) {
128 keep = true;
131 break;
132 default:
133 /* Can't happen or invalid parameter */
134 return NULL;
137 if (!keep) {
138 continue;
141 new_gensec_list[j] = old_gensec_list[i];
142 j++;
144 new_gensec_list[j] = NULL;
146 return new_gensec_list;
149 _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs(
150 struct gensec_security *gensec_security,
151 TALLOC_CTX *mem_ctx)
153 struct cli_credentials *creds = NULL;
154 const struct gensec_security_ops * const *backends = gensec_security_all();
156 if (gensec_security != NULL) {
157 creds = gensec_get_credentials(gensec_security);
159 if (gensec_security->settings->backends) {
160 backends = gensec_security->settings->backends;
164 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
168 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
169 struct gensec_security *gensec_security,
170 const char *oid_string)
172 int i, j;
173 const struct gensec_security_ops **backends;
174 const struct gensec_security_ops *backend;
175 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
176 if (!mem_ctx) {
177 return NULL;
179 backends = gensec_security_mechs(gensec_security, mem_ctx);
180 for (i=0; backends && backends[i]; i++) {
181 if (gensec_security != NULL &&
182 !gensec_security_ops_enabled(backends[i],
183 gensec_security))
184 continue;
185 if (backends[i]->oid) {
186 for (j=0; backends[i]->oid[j]; j++) {
187 if (backends[i]->oid[j] &&
188 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
189 backend = backends[i];
190 talloc_free(mem_ctx);
191 return backend;
196 talloc_free(mem_ctx);
198 return NULL;
201 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
202 struct gensec_security *gensec_security,
203 const char *sasl_name)
205 int i;
206 const struct gensec_security_ops **backends;
207 const struct gensec_security_ops *backend;
208 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
209 if (!mem_ctx) {
210 return NULL;
212 backends = gensec_security_mechs(gensec_security, mem_ctx);
213 for (i=0; backends && backends[i]; i++) {
214 if (gensec_security != NULL &&
215 !gensec_security_ops_enabled(backends[i], gensec_security)) {
216 continue;
218 if (backends[i]->sasl_name
219 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
220 backend = backends[i];
221 talloc_free(mem_ctx);
222 return backend;
225 talloc_free(mem_ctx);
227 return NULL;
230 _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
231 struct gensec_security *gensec_security,
232 uint32_t auth_type)
234 int i;
235 const struct gensec_security_ops **backends;
236 const struct gensec_security_ops *backend;
237 TALLOC_CTX *mem_ctx;
239 if (auth_type == DCERPC_AUTH_TYPE_NONE) {
240 return NULL;
243 mem_ctx = talloc_new(gensec_security);
244 if (!mem_ctx) {
245 return NULL;
247 backends = gensec_security_mechs(gensec_security, mem_ctx);
248 for (i=0; backends && backends[i]; i++) {
249 if (gensec_security != NULL &&
250 !gensec_security_ops_enabled(backends[i], gensec_security)) {
251 continue;
253 if (backends[i]->auth_type == auth_type) {
254 backend = backends[i];
255 talloc_free(mem_ctx);
256 return backend;
259 talloc_free(mem_ctx);
261 return NULL;
264 const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
265 const char *name)
267 int i;
268 const struct gensec_security_ops **backends;
269 const struct gensec_security_ops *backend;
270 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
271 if (!mem_ctx) {
272 return NULL;
274 backends = gensec_security_mechs(gensec_security, mem_ctx);
275 for (i=0; backends && backends[i]; i++) {
276 if (gensec_security != NULL &&
277 !gensec_security_ops_enabled(backends[i], gensec_security))
278 continue;
279 if (backends[i]->name
280 && (strcmp(backends[i]->name, name) == 0)) {
281 backend = backends[i];
282 talloc_free(mem_ctx);
283 return backend;
286 talloc_free(mem_ctx);
287 return NULL;
291 * Return a unique list of security subsystems from those specified in
292 * the list of SASL names.
294 * Use the list of enabled GENSEC mechanisms from the credentials
295 * attached to the gensec_security, and return in our preferred order.
298 static const struct gensec_security_ops **gensec_security_by_sasl_list(
299 struct gensec_security *gensec_security,
300 TALLOC_CTX *mem_ctx,
301 const char **sasl_names)
303 const struct gensec_security_ops **backends_out;
304 const struct gensec_security_ops **backends;
305 int i, k, sasl_idx;
306 int num_backends_out = 0;
308 if (!sasl_names) {
309 return NULL;
312 backends = gensec_security_mechs(gensec_security, mem_ctx);
314 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
315 if (!backends_out) {
316 return NULL;
318 backends_out[0] = NULL;
320 /* Find backends in our preferred order, by walking our list,
321 * then looking in the supplied list */
322 for (i=0; backends && backends[i]; i++) {
323 if (gensec_security != NULL &&
324 !gensec_security_ops_enabled(backends[i], gensec_security))
325 continue;
326 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
327 if (!backends[i]->sasl_name ||
328 !(strcmp(backends[i]->sasl_name,
329 sasl_names[sasl_idx]) == 0)) {
330 continue;
333 for (k=0; backends_out[k]; k++) {
334 if (backends_out[k] == backends[i]) {
335 break;
339 if (k < num_backends_out) {
340 /* already in there */
341 continue;
344 backends_out = talloc_realloc(mem_ctx, backends_out,
345 const struct gensec_security_ops *,
346 num_backends_out + 2);
347 if (!backends_out) {
348 return NULL;
351 backends_out[num_backends_out] = backends[i];
352 num_backends_out++;
353 backends_out[num_backends_out] = NULL;
356 return backends_out;
360 * Return a unique list of security subsystems from those specified in
361 * the OID list. That is, where two OIDs refer to the same module,
362 * return that module only once.
364 * Use the list of enabled GENSEC mechanisms from the credentials
365 * attached to the gensec_security, and return in our preferred order.
368 _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
369 struct gensec_security *gensec_security,
370 TALLOC_CTX *mem_ctx,
371 const char * const *oid_strings,
372 const char *skip)
374 struct gensec_security_ops_wrapper *backends_out;
375 const struct gensec_security_ops **backends;
376 int i, j, k, oid_idx;
377 int num_backends_out = 0;
379 if (!oid_strings) {
380 return NULL;
383 backends = gensec_security_mechs(gensec_security, gensec_security);
385 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
386 if (!backends_out) {
387 return NULL;
389 backends_out[0].op = NULL;
390 backends_out[0].oid = NULL;
392 /* Find backends in our preferred order, by walking our list,
393 * then looking in the supplied list */
394 for (i=0; backends && backends[i]; i++) {
395 if (gensec_security != NULL &&
396 !gensec_security_ops_enabled(backends[i], gensec_security))
397 continue;
398 if (!backends[i]->oid) {
399 continue;
401 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
402 if (strcmp(oid_strings[oid_idx], skip) == 0) {
403 continue;
406 for (j=0; backends[i]->oid[j]; j++) {
407 if (!backends[i]->oid[j] ||
408 !(strcmp(backends[i]->oid[j],
409 oid_strings[oid_idx]) == 0)) {
410 continue;
413 for (k=0; backends_out[k].op; k++) {
414 if (backends_out[k].op == backends[i]) {
415 break;
419 if (k < num_backends_out) {
420 /* already in there */
421 continue;
424 backends_out = talloc_realloc(mem_ctx, backends_out,
425 struct gensec_security_ops_wrapper,
426 num_backends_out + 2);
427 if (!backends_out) {
428 return NULL;
431 backends_out[num_backends_out].op = backends[i];
432 backends_out[num_backends_out].oid = backends[i]->oid[j];
433 num_backends_out++;
434 backends_out[num_backends_out].op = NULL;
435 backends_out[num_backends_out].oid = NULL;
439 return backends_out;
443 * Return OIDS from the security subsystems listed
446 static const char **gensec_security_oids_from_ops(
447 struct gensec_security *gensec_security,
448 TALLOC_CTX *mem_ctx,
449 const struct gensec_security_ops * const *ops,
450 const char *skip)
452 int i;
453 int j = 0;
454 int k;
455 const char **oid_list;
456 if (!ops) {
457 return NULL;
459 oid_list = talloc_array(mem_ctx, const char *, 1);
460 if (!oid_list) {
461 return NULL;
464 for (i=0; ops && ops[i]; i++) {
465 if (gensec_security != NULL &&
466 !gensec_security_ops_enabled(ops[i], gensec_security)) {
467 continue;
469 if (!ops[i]->oid) {
470 continue;
473 for (k = 0; ops[i]->oid[k]; k++) {
474 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
475 } else {
476 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
477 if (!oid_list) {
478 return NULL;
480 oid_list[j] = ops[i]->oid[k];
481 j++;
485 oid_list[j] = NULL;
486 return oid_list;
491 * Return OIDS from the security subsystems listed
494 _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
495 const struct gensec_security_ops_wrapper *wops)
497 int i;
498 int j = 0;
499 int k;
500 const char **oid_list;
501 if (!wops) {
502 return NULL;
504 oid_list = talloc_array(mem_ctx, const char *, 1);
505 if (!oid_list) {
506 return NULL;
509 for (i=0; wops[i].op; i++) {
510 if (!wops[i].op->oid) {
511 continue;
514 for (k = 0; wops[i].op->oid[k]; k++) {
515 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
516 if (!oid_list) {
517 return NULL;
519 oid_list[j] = wops[i].op->oid[k];
520 j++;
523 oid_list[j] = NULL;
524 return oid_list;
529 * Return all the security subsystems currently enabled on a GENSEC context.
531 * This is taken from a list attached to the cli_credentials, and
532 * skips the OID in 'skip'. (Typically the SPNEGO OID)
536 _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
537 TALLOC_CTX *mem_ctx,
538 const char *skip)
540 const struct gensec_security_ops **ops;
542 ops = gensec_security_mechs(gensec_security, mem_ctx);
544 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
548 Start the GENSEC system, returning a context pointer.
549 @param mem_ctx The parent TALLOC memory context.
550 @param gensec_security Returned GENSEC context pointer.
551 @note The mem_ctx is only a parent and may be NULL.
552 @note, the auth context is moved to be a referenced pointer of the
553 @ gensec_security return
555 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
556 struct gensec_settings *settings,
557 struct auth4_context *auth_context,
558 struct gensec_security **gensec_security)
560 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
561 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
563 (*gensec_security)->max_update_size = 0;
565 SMB_ASSERT(settings->lp_ctx != NULL);
566 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
568 /* We need to reference this, not steal, as the caller may be
569 * python, which won't like it if we steal it's object away
570 * from it */
571 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
573 return NT_STATUS_OK;
577 * Start a GENSEC subcontext, with a copy of the properties of the parent
578 * @param mem_ctx The parent TALLOC memory context.
579 * @param parent The parent GENSEC context
580 * @param gensec_security Returned GENSEC context pointer.
581 * @note Used by SPNEGO in particular, for the actual implementation mechanism
584 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
585 struct gensec_security *parent,
586 struct gensec_security **gensec_security)
588 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
589 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
591 (**gensec_security) = *parent;
592 (*gensec_security)->ops = NULL;
593 (*gensec_security)->private_data = NULL;
595 (*gensec_security)->subcontext = true;
596 (*gensec_security)->want_features = parent->want_features;
597 (*gensec_security)->max_update_size = parent->max_update_size;
598 (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
599 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
600 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
601 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
603 return NT_STATUS_OK;
607 Start the GENSEC system, in client mode, returning a context pointer.
608 @param mem_ctx The parent TALLOC memory context.
609 @param gensec_security Returned GENSEC context pointer.
610 @note The mem_ctx is only a parent and may be NULL.
612 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
613 struct gensec_security **gensec_security,
614 struct gensec_settings *settings)
616 NTSTATUS status;
618 if (settings == NULL) {
619 DEBUG(0,("gensec_client_start: no settings given!\n"));
620 return NT_STATUS_INTERNAL_ERROR;
623 status = gensec_start(mem_ctx, settings, NULL, gensec_security);
624 if (!NT_STATUS_IS_OK(status)) {
625 return status;
627 (*gensec_security)->gensec_role = GENSEC_CLIENT;
629 return status;
635 Start the GENSEC system, in server mode, returning a context pointer.
636 @param mem_ctx The parent TALLOC memory context.
637 @param gensec_security Returned GENSEC context pointer.
638 @note The mem_ctx is only a parent and may be NULL.
640 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
641 struct gensec_settings *settings,
642 struct auth4_context *auth_context,
643 struct gensec_security **gensec_security)
645 NTSTATUS status;
647 if (!settings) {
648 DEBUG(0,("gensec_server_start: no settings given!\n"));
649 return NT_STATUS_INTERNAL_ERROR;
652 status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
653 if (!NT_STATUS_IS_OK(status)) {
654 return status;
656 (*gensec_security)->gensec_role = GENSEC_SERVER;
658 return status;
661 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
663 NTSTATUS status;
665 if (gensec_security->credentials) {
666 const char *forced_mech = cli_credentials_get_forced_sasl_mech(gensec_security->credentials);
667 if (forced_mech &&
668 (gensec_security->ops->sasl_name == NULL ||
669 strcasecmp(forced_mech, gensec_security->ops->sasl_name) != 0)) {
670 DEBUG(5, ("GENSEC mechanism %s (%s) skipped, as it "
671 "did not match forced mechanism %s\n",
672 gensec_security->ops->name,
673 gensec_security->ops->sasl_name,
674 forced_mech));
675 return NT_STATUS_INVALID_PARAMETER;
678 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
679 gensec_security->subcontext ? "sub" : "",
680 gensec_security->ops->name));
681 switch (gensec_security->gensec_role) {
682 case GENSEC_CLIENT:
683 if (gensec_security->ops->client_start) {
684 status = gensec_security->ops->client_start(gensec_security);
685 if (!NT_STATUS_IS_OK(status)) {
686 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
687 gensec_security->ops->name, nt_errstr(status)));
689 return status;
691 break;
692 case GENSEC_SERVER:
693 if (gensec_security->ops->server_start) {
694 status = gensec_security->ops->server_start(gensec_security);
695 if (!NT_STATUS_IS_OK(status)) {
696 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
697 gensec_security->ops->name, nt_errstr(status)));
699 return status;
701 break;
703 return NT_STATUS_INVALID_PARAMETER;
707 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
711 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
712 const struct gensec_security_ops *ops)
714 gensec_security->ops = ops;
715 return gensec_start_mech(gensec_security);
720 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
721 * @param gensec_security GENSEC context pointer.
722 * @param auth_type DCERPC auth type
723 * @param auth_level DCERPC auth level
726 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
727 uint8_t auth_type, uint8_t auth_level)
729 gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type);
730 if (!gensec_security->ops) {
731 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
732 return NT_STATUS_INVALID_PARAMETER;
734 gensec_security->dcerpc_auth_level = auth_level;
736 * We need to reset sign/seal in order to reset it.
737 * We may got some default features inherited by the credentials
739 gensec_security->want_features &= ~GENSEC_FEATURE_SIGN;
740 gensec_security->want_features &= ~GENSEC_FEATURE_SEAL;
741 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
742 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
743 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
744 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
745 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
746 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
747 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
748 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
749 /* Default features */
750 } else {
751 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
752 auth_level));
753 return NT_STATUS_INVALID_PARAMETER;
756 return gensec_start_mech(gensec_security);
759 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
761 const struct gensec_security_ops *ops;
762 ops = gensec_security_by_auth_type(gensec_security, authtype);
763 if (ops) {
764 return ops->name;
766 return NULL;
770 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
771 const char *oid_string)
773 const struct gensec_security_ops *ops;
774 ops = gensec_security_by_oid(gensec_security, oid_string);
775 if (ops) {
776 return ops->name;
778 return oid_string;
782 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
784 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
785 * well-known #define to hook it in.
788 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
789 const char *mech_oid)
791 SMB_ASSERT(gensec_security != NULL);
793 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
794 if (!gensec_security->ops) {
795 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
796 return NT_STATUS_INVALID_PARAMETER;
798 return gensec_start_mech(gensec_security);
802 * Start a GENSEC sub-mechanism by a well know SASL name
806 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
807 const char *sasl_name)
809 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
810 if (!gensec_security->ops) {
811 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
812 return NT_STATUS_INVALID_PARAMETER;
814 return gensec_start_mech(gensec_security);
818 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
822 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
823 const char **sasl_names)
825 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
826 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
827 const struct gensec_security_ops **ops;
828 int i;
829 if (!mem_ctx) {
830 return NT_STATUS_NO_MEMORY;
832 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
833 if (!ops || !*ops) {
834 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
835 str_list_join(mem_ctx,
836 sasl_names, ' ')));
837 talloc_free(mem_ctx);
838 return NT_STATUS_INVALID_PARAMETER;
840 for (i=0; ops[i]; i++) {
841 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
842 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
843 break;
846 talloc_free(mem_ctx);
847 return nt_status;
851 * Start a GENSEC sub-mechanism by an internal name
855 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
856 const char *name)
858 gensec_security->ops = gensec_security_by_name(gensec_security, name);
859 if (!gensec_security->ops) {
860 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
861 return NT_STATUS_INVALID_PARAMETER;
863 return gensec_start_mech(gensec_security);
867 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
871 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
873 gensec_security->credentials = talloc_reference(gensec_security, credentials);
874 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
875 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
876 return NT_STATUS_OK;
880 register a GENSEC backend.
882 The 'name' can be later used by other backends to find the operations
883 structure for this backend.
885 _PUBLIC_ NTSTATUS gensec_register(const struct gensec_security_ops *ops)
887 if (gensec_security_by_name(NULL, ops->name) != NULL) {
888 /* its already registered! */
889 DEBUG(0,("GENSEC backend '%s' already registered\n",
890 ops->name));
891 return NT_STATUS_OBJECT_NAME_COLLISION;
894 generic_security_ops = talloc_realloc(talloc_autofree_context(),
895 generic_security_ops,
896 const struct gensec_security_ops *,
897 gensec_num_backends+2);
898 if (!generic_security_ops) {
899 return NT_STATUS_NO_MEMORY;
902 generic_security_ops[gensec_num_backends] = ops;
903 gensec_num_backends++;
904 generic_security_ops[gensec_num_backends] = NULL;
906 DEBUG(3,("GENSEC backend '%s' registered\n",
907 ops->name));
909 return NT_STATUS_OK;
913 return the GENSEC interface version, and the size of some critical types
914 This can be used by backends to either detect compilation errors, or provide
915 multiple implementations for different smbd compilation options in one module
917 _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
919 static const struct gensec_critical_sizes critical_sizes = {
920 GENSEC_INTERFACE_VERSION,
921 sizeof(struct gensec_security_ops),
922 sizeof(struct gensec_security),
925 return &critical_sizes;
928 static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
929 return (*gs2)->priority - (*gs1)->priority;
932 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
934 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
937 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
939 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
943 initialise the GENSEC subsystem
945 _PUBLIC_ NTSTATUS gensec_init(void)
947 static bool initialized = false;
948 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
949 #ifdef STATIC_gensec_MODULES
950 STATIC_gensec_MODULES_PROTO;
951 init_module_fn static_init[] = { STATIC_gensec_MODULES };
952 #else
953 init_module_fn *static_init = NULL;
954 #endif
955 init_module_fn *shared_init;
957 if (initialized) return NT_STATUS_OK;
958 initialized = true;
960 shared_init = load_samba_modules(NULL, "gensec");
962 run_init_functions(static_init);
963 run_init_functions(shared_init);
965 talloc_free(shared_init);
967 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
969 return NT_STATUS_OK;