dns: The QCLASS is called IN, not IP
[Samba/gebeck_regimport.git] / source4 / auth / gensec / gensec_start.c
blobd754bb0cde1f92c7aab3a2a9f3530257985f2b8f
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 "lib/events/events.h"
26 #include "lib/socket/socket.h"
27 #include "lib/tsocket/tsocket.h"
28 #include "../lib/util/tevent_ntstatus.h"
29 #include "librpc/rpc/dcerpc.h"
30 #include "auth/credentials/credentials.h"
31 #include "auth/gensec/gensec.h"
32 #include "auth/gensec/gensec_proto.h"
33 #include "auth/auth.h"
34 #include "auth/system_session_proto.h"
35 #include "param/param.h"
36 #include "lib/util/tsort.h"
37 #include "auth/gensec/gensec_toplevel_proto.h"
39 /* the list of currently registered GENSEC backends */
40 static struct gensec_security_ops **generic_security_ops;
41 static int gensec_num_backends;
43 /* Return all the registered mechs. Don't modify the return pointer,
44 * but you may talloc_reference it if convient */
45 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
47 return generic_security_ops;
50 bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security)
52 return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled);
55 /* Sometimes we want to force only kerberos, sometimes we want to
56 * force it's avoidance. The old list could be either
57 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
58 * an existing list we have trimmed down) */
60 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
61 struct gensec_security_ops **old_gensec_list,
62 struct cli_credentials *creds)
64 struct gensec_security_ops **new_gensec_list;
65 int i, j, num_mechs_in;
66 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
68 if (creds) {
69 use_kerberos = cli_credentials_get_kerberos_state(creds);
72 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
73 if (!talloc_reference(mem_ctx, old_gensec_list)) {
74 return NULL;
76 return old_gensec_list;
79 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
80 /* noop */
83 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
84 if (!new_gensec_list) {
85 return NULL;
88 j = 0;
89 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
90 int oid_idx;
92 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
93 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
94 new_gensec_list[j] = old_gensec_list[i];
95 j++;
96 break;
99 switch (use_kerberos) {
100 case CRED_DONT_USE_KERBEROS:
101 if (old_gensec_list[i]->kerberos == false) {
102 new_gensec_list[j] = old_gensec_list[i];
103 j++;
105 break;
106 case CRED_MUST_USE_KERBEROS:
107 if (old_gensec_list[i]->kerberos == true) {
108 new_gensec_list[j] = old_gensec_list[i];
109 j++;
111 break;
112 default:
113 /* Can't happen or invalid parameter */
114 return NULL;
117 new_gensec_list[j] = NULL;
119 return new_gensec_list;
122 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
123 TALLOC_CTX *mem_ctx)
125 struct gensec_security_ops **backends;
126 backends = gensec_security_all();
127 if (!gensec_security) {
128 if (!talloc_reference(mem_ctx, backends)) {
129 return NULL;
131 return backends;
132 } else {
133 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
134 if (!creds) {
135 if (!talloc_reference(mem_ctx, backends)) {
136 return NULL;
138 return backends;
140 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
144 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
145 uint8_t auth_type)
147 int i;
148 struct gensec_security_ops **backends;
149 const struct gensec_security_ops *backend;
150 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
151 if (!mem_ctx) {
152 return NULL;
154 backends = gensec_security_mechs(gensec_security, mem_ctx);
155 for (i=0; backends && backends[i]; i++) {
156 if (!gensec_security_ops_enabled(backends[i], gensec_security))
157 continue;
158 if (backends[i]->auth_type == auth_type) {
159 backend = backends[i];
160 talloc_free(mem_ctx);
161 return backend;
164 talloc_free(mem_ctx);
166 return NULL;
169 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
170 const char *oid_string)
172 int i, j;
173 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 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
202 const char *sasl_name)
204 int i;
205 struct gensec_security_ops **backends;
206 const struct gensec_security_ops *backend;
207 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
208 if (!mem_ctx) {
209 return NULL;
211 backends = gensec_security_mechs(gensec_security, mem_ctx);
212 for (i=0; backends && backends[i]; i++) {
213 if (!gensec_security_ops_enabled(backends[i], gensec_security))
214 continue;
215 if (backends[i]->sasl_name
216 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
217 backend = backends[i];
218 talloc_free(mem_ctx);
219 return backend;
222 talloc_free(mem_ctx);
224 return NULL;
227 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
228 const char *name)
230 int i;
231 struct gensec_security_ops **backends;
232 const struct gensec_security_ops *backend;
233 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
234 if (!mem_ctx) {
235 return NULL;
237 backends = gensec_security_mechs(gensec_security, mem_ctx);
238 for (i=0; backends && backends[i]; i++) {
239 if (gensec_security != NULL &&
240 !gensec_security_ops_enabled(backends[i], gensec_security))
241 continue;
242 if (backends[i]->name
243 && (strcmp(backends[i]->name, name) == 0)) {
244 backend = backends[i];
245 talloc_free(mem_ctx);
246 return backend;
249 talloc_free(mem_ctx);
250 return NULL;
254 * Return a unique list of security subsystems from those specified in
255 * the list of SASL names.
257 * Use the list of enabled GENSEC mechanisms from the credentials
258 * attached to the gensec_security, and return in our preferred order.
261 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
262 TALLOC_CTX *mem_ctx,
263 const char **sasl_names)
265 const struct gensec_security_ops **backends_out;
266 struct gensec_security_ops **backends;
267 int i, k, sasl_idx;
268 int num_backends_out = 0;
270 if (!sasl_names) {
271 return NULL;
274 backends = gensec_security_mechs(gensec_security, mem_ctx);
276 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
277 if (!backends_out) {
278 return NULL;
280 backends_out[0] = NULL;
282 /* Find backends in our preferred order, by walking our list,
283 * then looking in the supplied list */
284 for (i=0; backends && backends[i]; i++) {
285 if (gensec_security != NULL &&
286 !gensec_security_ops_enabled(backends[i], gensec_security))
287 continue;
288 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
289 if (!backends[i]->sasl_name ||
290 !(strcmp(backends[i]->sasl_name,
291 sasl_names[sasl_idx]) == 0)) {
292 continue;
295 for (k=0; backends_out[k]; k++) {
296 if (backends_out[k] == backends[i]) {
297 break;
301 if (k < num_backends_out) {
302 /* already in there */
303 continue;
306 backends_out = talloc_realloc(mem_ctx, backends_out,
307 const struct gensec_security_ops *,
308 num_backends_out + 2);
309 if (!backends_out) {
310 return NULL;
313 backends_out[num_backends_out] = backends[i];
314 num_backends_out++;
315 backends_out[num_backends_out] = NULL;
318 return backends_out;
322 * Return a unique list of security subsystems from those specified in
323 * the OID list. That is, where two OIDs refer to the same module,
324 * return that module only once.
326 * Use the list of enabled GENSEC mechanisms from the credentials
327 * attached to the gensec_security, and return in our preferred order.
330 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
331 TALLOC_CTX *mem_ctx,
332 const char **oid_strings,
333 const char *skip)
335 struct gensec_security_ops_wrapper *backends_out;
336 struct gensec_security_ops **backends;
337 int i, j, k, oid_idx;
338 int num_backends_out = 0;
340 if (!oid_strings) {
341 return NULL;
344 backends = gensec_security_mechs(gensec_security, gensec_security);
346 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
347 if (!backends_out) {
348 return NULL;
350 backends_out[0].op = NULL;
351 backends_out[0].oid = NULL;
353 /* Find backends in our preferred order, by walking our list,
354 * then looking in the supplied list */
355 for (i=0; backends && backends[i]; i++) {
356 if (gensec_security != NULL &&
357 !gensec_security_ops_enabled(backends[i], gensec_security))
358 continue;
359 if (!backends[i]->oid) {
360 continue;
362 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
363 if (strcmp(oid_strings[oid_idx], skip) == 0) {
364 continue;
367 for (j=0; backends[i]->oid[j]; j++) {
368 if (!backends[i]->oid[j] ||
369 !(strcmp(backends[i]->oid[j],
370 oid_strings[oid_idx]) == 0)) {
371 continue;
374 for (k=0; backends_out[k].op; k++) {
375 if (backends_out[k].op == backends[i]) {
376 break;
380 if (k < num_backends_out) {
381 /* already in there */
382 continue;
385 backends_out = talloc_realloc(mem_ctx, backends_out,
386 struct gensec_security_ops_wrapper,
387 num_backends_out + 2);
388 if (!backends_out) {
389 return NULL;
392 backends_out[num_backends_out].op = backends[i];
393 backends_out[num_backends_out].oid = backends[i]->oid[j];
394 num_backends_out++;
395 backends_out[num_backends_out].op = NULL;
396 backends_out[num_backends_out].oid = NULL;
400 return backends_out;
404 * Return OIDS from the security subsystems listed
407 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
408 TALLOC_CTX *mem_ctx,
409 struct gensec_security_ops **ops,
410 const char *skip)
412 int i;
413 int j = 0;
414 int k;
415 const char **oid_list;
416 if (!ops) {
417 return NULL;
419 oid_list = talloc_array(mem_ctx, const char *, 1);
420 if (!oid_list) {
421 return NULL;
424 for (i=0; ops && ops[i]; i++) {
425 if (gensec_security != NULL &&
426 !gensec_security_ops_enabled(ops[i], gensec_security)) {
427 continue;
429 if (!ops[i]->oid) {
430 continue;
433 for (k = 0; ops[i]->oid[k]; k++) {
434 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
435 } else {
436 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
437 if (!oid_list) {
438 return NULL;
440 oid_list[j] = ops[i]->oid[k];
441 j++;
445 oid_list[j] = NULL;
446 return oid_list;
451 * Return OIDS from the security subsystems listed
454 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
455 const struct gensec_security_ops_wrapper *wops)
457 int i;
458 int j = 0;
459 int k;
460 const char **oid_list;
461 if (!wops) {
462 return NULL;
464 oid_list = talloc_array(mem_ctx, const char *, 1);
465 if (!oid_list) {
466 return NULL;
469 for (i=0; wops[i].op; i++) {
470 if (!wops[i].op->oid) {
471 continue;
474 for (k = 0; wops[i].op->oid[k]; k++) {
475 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
476 if (!oid_list) {
477 return NULL;
479 oid_list[j] = wops[i].op->oid[k];
480 j++;
483 oid_list[j] = NULL;
484 return oid_list;
489 * Return all the security subsystems currently enabled on a GENSEC context.
491 * This is taken from a list attached to the cli_credentials, and
492 * skips the OID in 'skip'. (Typically the SPNEGO OID)
496 const char **gensec_security_oids(struct gensec_security *gensec_security,
497 TALLOC_CTX *mem_ctx,
498 const char *skip)
500 struct gensec_security_ops **ops
501 = gensec_security_mechs(gensec_security, mem_ctx);
502 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
506 Start the GENSEC system, returning a context pointer.
507 @param mem_ctx The parent TALLOC memory context.
508 @param gensec_security Returned GENSEC context pointer.
509 @note The mem_ctx is only a parent and may be NULL.
510 @note, the auth context is moved to be a referenced pointer of the
511 @ gensec_security return
513 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
514 struct tevent_context *ev,
515 struct gensec_settings *settings,
516 struct auth4_context *auth_context,
517 struct gensec_security **gensec_security)
519 if (ev == NULL) {
520 DEBUG(0, ("No event context available!\n"));
521 return NT_STATUS_INTERNAL_ERROR;
524 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
525 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
527 (*gensec_security)->event_ctx = ev;
528 SMB_ASSERT(settings->lp_ctx != NULL);
529 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
531 /* We need to reference this, not steal, as the caller may be
532 * python, which won't like it if we steal it's object away
533 * from it */
534 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
536 return NT_STATUS_OK;
540 * Start a GENSEC subcontext, with a copy of the properties of the parent
541 * @param mem_ctx The parent TALLOC memory context.
542 * @param parent The parent GENSEC context
543 * @param gensec_security Returned GENSEC context pointer.
544 * @note Used by SPNEGO in particular, for the actual implementation mechanism
547 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
548 struct gensec_security *parent,
549 struct gensec_security **gensec_security)
551 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
552 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
554 (**gensec_security) = *parent;
555 (*gensec_security)->ops = NULL;
556 (*gensec_security)->private_data = NULL;
558 (*gensec_security)->subcontext = true;
559 (*gensec_security)->want_features = parent->want_features;
560 (*gensec_security)->event_ctx = parent->event_ctx;
561 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
562 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
563 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
565 return NT_STATUS_OK;
569 Start the GENSEC system, in client mode, returning a context pointer.
570 @param mem_ctx The parent TALLOC memory context.
571 @param gensec_security Returned GENSEC context pointer.
572 @note The mem_ctx is only a parent and may be NULL.
574 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
575 struct gensec_security **gensec_security,
576 struct tevent_context *ev,
577 struct gensec_settings *settings)
579 NTSTATUS status;
581 if (settings == NULL) {
582 DEBUG(0,("gensec_client_start: no settings given!\n"));
583 return NT_STATUS_INTERNAL_ERROR;
586 status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
587 if (!NT_STATUS_IS_OK(status)) {
588 return status;
590 (*gensec_security)->gensec_role = GENSEC_CLIENT;
592 return status;
598 Start the GENSEC system, in server mode, returning a context pointer.
599 @param mem_ctx The parent TALLOC memory context.
600 @param gensec_security Returned GENSEC context pointer.
601 @note The mem_ctx is only a parent and may be NULL.
603 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
604 struct tevent_context *ev,
605 struct gensec_settings *settings,
606 struct auth4_context *auth_context,
607 struct gensec_security **gensec_security)
609 NTSTATUS status;
611 if (!ev) {
612 DEBUG(0,("gensec_server_start: no event context given!\n"));
613 return NT_STATUS_INTERNAL_ERROR;
616 if (!settings) {
617 DEBUG(0,("gensec_server_start: no settings given!\n"));
618 return NT_STATUS_INTERNAL_ERROR;
621 status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
622 if (!NT_STATUS_IS_OK(status)) {
623 return status;
625 (*gensec_security)->gensec_role = GENSEC_SERVER;
627 return status;
630 NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
632 NTSTATUS status;
633 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
634 gensec_security->subcontext ? "sub" : "",
635 gensec_security->ops->name));
636 switch (gensec_security->gensec_role) {
637 case GENSEC_CLIENT:
638 if (gensec_security->ops->client_start) {
639 status = gensec_security->ops->client_start(gensec_security);
640 if (!NT_STATUS_IS_OK(status)) {
641 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
642 gensec_security->ops->name, nt_errstr(status)));
644 return status;
646 break;
647 case GENSEC_SERVER:
648 if (gensec_security->ops->server_start) {
649 status = gensec_security->ops->server_start(gensec_security);
650 if (!NT_STATUS_IS_OK(status)) {
651 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
652 gensec_security->ops->name, nt_errstr(status)));
654 return status;
656 break;
658 return NT_STATUS_INVALID_PARAMETER;
662 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
666 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
667 const struct gensec_security_ops *ops)
669 gensec_security->ops = ops;
670 return gensec_start_mech(gensec_security);
675 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
676 * @param gensec_security GENSEC context pointer.
677 * @param auth_type DCERPC auth type
678 * @param auth_level DCERPC auth level
681 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
682 uint8_t auth_type, uint8_t auth_level)
684 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
685 if (!gensec_security->ops) {
686 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
687 return NT_STATUS_INVALID_PARAMETER;
689 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
690 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
691 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
692 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
693 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
694 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
695 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
696 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
697 /* Default features */
698 } else {
699 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
700 auth_level));
701 return NT_STATUS_INVALID_PARAMETER;
704 return gensec_start_mech(gensec_security);
707 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
709 const struct gensec_security_ops *ops;
710 ops = gensec_security_by_authtype(gensec_security, authtype);
711 if (ops) {
712 return ops->name;
714 return NULL;
718 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
719 const char *oid_string)
721 const struct gensec_security_ops *ops;
722 ops = gensec_security_by_oid(gensec_security, oid_string);
723 if (ops) {
724 return ops->name;
726 return oid_string;
730 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
732 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
733 * well-known #define to hook it in.
736 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
737 const char *mech_oid)
739 SMB_ASSERT(gensec_security != NULL);
741 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
742 if (!gensec_security->ops) {
743 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
744 return NT_STATUS_INVALID_PARAMETER;
746 return gensec_start_mech(gensec_security);
750 * Start a GENSEC sub-mechanism by a well know SASL name
754 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
755 const char *sasl_name)
757 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
758 if (!gensec_security->ops) {
759 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
760 return NT_STATUS_INVALID_PARAMETER;
762 return gensec_start_mech(gensec_security);
766 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
770 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
771 const char **sasl_names)
773 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
774 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
775 const struct gensec_security_ops **ops;
776 int i;
777 if (!mem_ctx) {
778 return NT_STATUS_NO_MEMORY;
780 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
781 if (!ops || !*ops) {
782 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
783 str_list_join(mem_ctx,
784 sasl_names, ' ')));
785 talloc_free(mem_ctx);
786 return NT_STATUS_INVALID_PARAMETER;
788 for (i=0; ops[i]; i++) {
789 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
790 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
791 break;
794 talloc_free(mem_ctx);
795 return nt_status;
799 * Start a GENSEC sub-mechanism by an internal name
803 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
804 const char *name)
806 gensec_security->ops = gensec_security_by_name(gensec_security, name);
807 if (!gensec_security->ops) {
808 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
809 return NT_STATUS_INVALID_PARAMETER;
811 return gensec_start_mech(gensec_security);
815 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
819 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
821 gensec_security->credentials = talloc_reference(gensec_security, credentials);
822 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
823 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
824 return NT_STATUS_OK;
827 NTSTATUS gensec_generate_session_info(TALLOC_CTX *mem_ctx,
828 struct gensec_security *gensec_security,
829 struct auth_user_info_dc *user_info_dc,
830 struct auth_session_info **session_info)
832 NTSTATUS nt_status;
833 uint32_t session_info_flags = 0;
835 if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
836 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
839 session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS;
840 if (user_info_dc->info->authenticated) {
841 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
844 if (gensec_security->auth_context) {
845 nt_status = gensec_security->auth_context->generate_session_info(mem_ctx, gensec_security->auth_context,
846 user_info_dc,
847 session_info_flags,
848 session_info);
849 } else {
850 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
851 nt_status = auth_generate_session_info(mem_ctx,
852 NULL,
853 NULL,
854 user_info_dc, session_info_flags,
855 session_info);
857 return nt_status;
861 register a GENSEC backend.
863 The 'name' can be later used by other backends to find the operations
864 structure for this backend.
866 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
868 if (gensec_security_by_name(NULL, ops->name) != NULL) {
869 /* its already registered! */
870 DEBUG(0,("GENSEC backend '%s' already registered\n",
871 ops->name));
872 return NT_STATUS_OBJECT_NAME_COLLISION;
875 generic_security_ops = talloc_realloc(talloc_autofree_context(),
876 generic_security_ops,
877 struct gensec_security_ops *,
878 gensec_num_backends+2);
879 if (!generic_security_ops) {
880 return NT_STATUS_NO_MEMORY;
883 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
884 gensec_num_backends++;
885 generic_security_ops[gensec_num_backends] = NULL;
887 DEBUG(3,("GENSEC backend '%s' registered\n",
888 ops->name));
890 return NT_STATUS_OK;
894 return the GENSEC interface version, and the size of some critical types
895 This can be used by backends to either detect compilation errors, or provide
896 multiple implementations for different smbd compilation options in one module
898 const struct gensec_critical_sizes *gensec_interface_version(void)
900 static const struct gensec_critical_sizes critical_sizes = {
901 GENSEC_INTERFACE_VERSION,
902 sizeof(struct gensec_security_ops),
903 sizeof(struct gensec_security),
906 return &critical_sizes;
909 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
910 return (*gs2)->priority - (*gs1)->priority;
913 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
915 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
918 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
920 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
924 initialise the GENSEC subsystem
926 _PUBLIC_ NTSTATUS gensec_init(void)
928 static bool initialized = false;
929 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
930 STATIC_gensec_MODULES_PROTO;
931 init_module_fn static_init[] = { STATIC_gensec_MODULES };
932 init_module_fn *shared_init;
934 if (initialized) return NT_STATUS_OK;
935 initialized = true;
937 shared_init = load_samba_modules(NULL, "gensec");
939 run_init_functions(static_init);
940 run_init_functions(shared_init);
942 talloc_free(shared_init);
944 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
946 return NT_STATUS_OK;