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/>.
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/auth.h"
33 #include "auth/system_session_proto.h"
34 #include "param/param.h"
35 #include "lib/util/tsort.h"
37 /* the list of currently registered GENSEC backends */
38 static struct gensec_security_ops **generic_security_ops;
39 static int gensec_num_backends;
41 /* Return all the registered mechs. Don't modify the return pointer,
42 * but you may talloc_reference it if convient */
43 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
45 return generic_security_ops;
48 bool gensec_security_ops_enabled(struct gensec_security_ops *ops, struct gensec_security *security)
50 return lpcfg_parm_bool(security->settings->lp_ctx, NULL, "gensec", ops->name, ops->enabled);
53 /* Sometimes we want to force only kerberos, sometimes we want to
54 * force it's avoidance. The old list could be either
55 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
56 * an existing list we have trimmed down) */
58 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
59 struct gensec_security_ops **old_gensec_list,
60 struct cli_credentials *creds)
62 struct gensec_security_ops **new_gensec_list;
63 int i, j, num_mechs_in;
64 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
67 use_kerberos = cli_credentials_get_kerberos_state(creds);
70 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
71 if (!talloc_reference(mem_ctx, old_gensec_list)) {
74 return old_gensec_list;
77 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
81 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
82 if (!new_gensec_list) {
87 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
90 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
91 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
92 new_gensec_list[j] = old_gensec_list[i];
97 switch (use_kerberos) {
98 case CRED_DONT_USE_KERBEROS:
99 if (old_gensec_list[i]->kerberos == false) {
100 new_gensec_list[j] = old_gensec_list[i];
104 case CRED_MUST_USE_KERBEROS:
105 if (old_gensec_list[i]->kerberos == true) {
106 new_gensec_list[j] = old_gensec_list[i];
111 /* Can't happen or invalid parameter */
115 new_gensec_list[j] = NULL;
117 return new_gensec_list;
120 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
123 struct gensec_security_ops **backends;
124 backends = gensec_security_all();
125 if (!gensec_security) {
126 if (!talloc_reference(mem_ctx, backends)) {
131 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
133 if (!talloc_reference(mem_ctx, backends)) {
138 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
142 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
146 struct gensec_security_ops **backends;
147 const struct gensec_security_ops *backend;
148 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
152 backends = gensec_security_mechs(gensec_security, mem_ctx);
153 for (i=0; backends && backends[i]; i++) {
154 if (!gensec_security_ops_enabled(backends[i], gensec_security))
156 if (backends[i]->auth_type == auth_type) {
157 backend = backends[i];
158 talloc_free(mem_ctx);
162 talloc_free(mem_ctx);
167 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
168 const char *oid_string)
171 struct gensec_security_ops **backends;
172 const struct gensec_security_ops *backend;
173 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
177 backends = gensec_security_mechs(gensec_security, mem_ctx);
178 for (i=0; backends && backends[i]; i++) {
179 if (gensec_security != NULL &&
180 !gensec_security_ops_enabled(backends[i],
183 if (backends[i]->oid) {
184 for (j=0; backends[i]->oid[j]; j++) {
185 if (backends[i]->oid[j] &&
186 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
187 backend = backends[i];
188 talloc_free(mem_ctx);
194 talloc_free(mem_ctx);
199 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
200 const char *sasl_name)
203 struct gensec_security_ops **backends;
204 const struct gensec_security_ops *backend;
205 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
209 backends = gensec_security_mechs(gensec_security, mem_ctx);
210 for (i=0; backends && backends[i]; i++) {
211 if (!gensec_security_ops_enabled(backends[i], gensec_security))
213 if (backends[i]->sasl_name
214 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
215 backend = backends[i];
216 talloc_free(mem_ctx);
220 talloc_free(mem_ctx);
225 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
229 struct gensec_security_ops **backends;
230 const struct gensec_security_ops *backend;
231 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
235 backends = gensec_security_mechs(gensec_security, mem_ctx);
236 for (i=0; backends && backends[i]; i++) {
237 if (gensec_security != NULL &&
238 !gensec_security_ops_enabled(backends[i], gensec_security))
240 if (backends[i]->name
241 && (strcmp(backends[i]->name, name) == 0)) {
242 backend = backends[i];
243 talloc_free(mem_ctx);
247 talloc_free(mem_ctx);
252 * Return a unique list of security subsystems from those specified in
253 * the list of SASL names.
255 * Use the list of enabled GENSEC mechanisms from the credentials
256 * attached to the gensec_security, and return in our preferred order.
259 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
261 const char **sasl_names)
263 const struct gensec_security_ops **backends_out;
264 struct gensec_security_ops **backends;
266 int num_backends_out = 0;
272 backends = gensec_security_mechs(gensec_security, mem_ctx);
274 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
278 backends_out[0] = NULL;
280 /* Find backends in our preferred order, by walking our list,
281 * then looking in the supplied list */
282 for (i=0; backends && backends[i]; i++) {
283 if (gensec_security != NULL &&
284 !gensec_security_ops_enabled(backends[i], gensec_security))
286 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
287 if (!backends[i]->sasl_name ||
288 !(strcmp(backends[i]->sasl_name,
289 sasl_names[sasl_idx]) == 0)) {
293 for (k=0; backends_out[k]; k++) {
294 if (backends_out[k] == backends[i]) {
299 if (k < num_backends_out) {
300 /* already in there */
304 backends_out = talloc_realloc(mem_ctx, backends_out,
305 const struct gensec_security_ops *,
306 num_backends_out + 2);
311 backends_out[num_backends_out] = backends[i];
313 backends_out[num_backends_out] = NULL;
320 * Return a unique list of security subsystems from those specified in
321 * the OID list. That is, where two OIDs refer to the same module,
322 * return that module only once.
324 * Use the list of enabled GENSEC mechanisms from the credentials
325 * attached to the gensec_security, and return in our preferred order.
328 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
330 const char **oid_strings,
333 struct gensec_security_ops_wrapper *backends_out;
334 struct gensec_security_ops **backends;
335 int i, j, k, oid_idx;
336 int num_backends_out = 0;
342 backends = gensec_security_mechs(gensec_security, gensec_security);
344 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
348 backends_out[0].op = NULL;
349 backends_out[0].oid = NULL;
351 /* Find backends in our preferred order, by walking our list,
352 * then looking in the supplied list */
353 for (i=0; backends && backends[i]; i++) {
354 if (gensec_security != NULL &&
355 !gensec_security_ops_enabled(backends[i], gensec_security))
357 if (!backends[i]->oid) {
360 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
361 if (strcmp(oid_strings[oid_idx], skip) == 0) {
365 for (j=0; backends[i]->oid[j]; j++) {
366 if (!backends[i]->oid[j] ||
367 !(strcmp(backends[i]->oid[j],
368 oid_strings[oid_idx]) == 0)) {
372 for (k=0; backends_out[k].op; k++) {
373 if (backends_out[k].op == backends[i]) {
378 if (k < num_backends_out) {
379 /* already in there */
383 backends_out = talloc_realloc(mem_ctx, backends_out,
384 struct gensec_security_ops_wrapper,
385 num_backends_out + 2);
390 backends_out[num_backends_out].op = backends[i];
391 backends_out[num_backends_out].oid = backends[i]->oid[j];
393 backends_out[num_backends_out].op = NULL;
394 backends_out[num_backends_out].oid = NULL;
402 * Return OIDS from the security subsystems listed
405 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
407 struct gensec_security_ops **ops,
413 const char **oid_list;
417 oid_list = talloc_array(mem_ctx, const char *, 1);
422 for (i=0; ops && ops[i]; i++) {
423 if (gensec_security != NULL &&
424 !gensec_security_ops_enabled(ops[i], gensec_security)) {
431 for (k = 0; ops[i]->oid[k]; k++) {
432 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
434 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
438 oid_list[j] = ops[i]->oid[k];
449 * Return OIDS from the security subsystems listed
452 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
453 const struct gensec_security_ops_wrapper *wops)
458 const char **oid_list;
462 oid_list = talloc_array(mem_ctx, const char *, 1);
467 for (i=0; wops[i].op; i++) {
468 if (!wops[i].op->oid) {
472 for (k = 0; wops[i].op->oid[k]; k++) {
473 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
477 oid_list[j] = wops[i].op->oid[k];
487 * Return all the security subsystems currently enabled on a GENSEC context.
489 * This is taken from a list attached to the cli_credentials, and
490 * skips the OID in 'skip'. (Typically the SPNEGO OID)
494 const char **gensec_security_oids(struct gensec_security *gensec_security,
498 struct gensec_security_ops **ops
499 = gensec_security_mechs(gensec_security, mem_ctx);
500 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 child 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 auth_context *auth_context,
517 struct gensec_security **gensec_security)
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);
530 (*gensec_security)->auth_context = talloc_steal(*gensec_security, auth_context);
536 * Start a GENSEC subcontext, with a copy of the properties of the parent
537 * @param mem_ctx The parent TALLOC memory context.
538 * @param parent The parent GENSEC context
539 * @param gensec_security Returned GENSEC context pointer.
540 * @note Used by SPNEGO in particular, for the actual implementation mechanism
543 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
544 struct gensec_security *parent,
545 struct gensec_security **gensec_security)
547 (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
548 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
550 (**gensec_security) = *parent;
551 (*gensec_security)->ops = NULL;
552 (*gensec_security)->private_data = NULL;
554 (*gensec_security)->subcontext = true;
555 (*gensec_security)->want_features = parent->want_features;
556 (*gensec_security)->event_ctx = parent->event_ctx;
557 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
558 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
559 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
565 Start the GENSEC system, in client mode, returning a context pointer.
566 @param mem_ctx The parent TALLOC memory context.
567 @param gensec_security Returned GENSEC context pointer.
568 @note The mem_ctx is only a parent and may be NULL.
570 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
571 struct gensec_security **gensec_security,
572 struct tevent_context *ev,
573 struct gensec_settings *settings)
577 if (settings == NULL) {
578 DEBUG(0,("gensec_client_start: no settings given!\n"));
579 return NT_STATUS_INTERNAL_ERROR;
582 status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
583 if (!NT_STATUS_IS_OK(status)) {
586 (*gensec_security)->gensec_role = GENSEC_CLIENT;
594 Start the GENSEC system, in server mode, returning a context pointer.
595 @param mem_ctx The parent TALLOC memory context.
596 @param gensec_security Returned GENSEC context pointer.
597 @note The mem_ctx is only a parent and may be NULL.
599 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
600 struct tevent_context *ev,
601 struct gensec_settings *settings,
602 struct auth_context *auth_context,
603 struct gensec_security **gensec_security)
608 DEBUG(0,("gensec_server_start: no event context given!\n"));
609 return NT_STATUS_INTERNAL_ERROR;
613 DEBUG(0,("gensec_server_start: no settings given!\n"));
614 return NT_STATUS_INTERNAL_ERROR;
617 status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
618 if (!NT_STATUS_IS_OK(status)) {
621 (*gensec_security)->gensec_role = GENSEC_SERVER;
626 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
629 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
630 gensec_security->subcontext ? "sub" : "",
631 gensec_security->ops->name));
632 switch (gensec_security->gensec_role) {
634 if (gensec_security->ops->client_start) {
635 status = gensec_security->ops->client_start(gensec_security);
636 if (!NT_STATUS_IS_OK(status)) {
637 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
638 gensec_security->ops->name, nt_errstr(status)));
644 if (gensec_security->ops->server_start) {
645 status = gensec_security->ops->server_start(gensec_security);
646 if (!NT_STATUS_IS_OK(status)) {
647 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
648 gensec_security->ops->name, nt_errstr(status)));
654 return NT_STATUS_INVALID_PARAMETER;
658 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
659 * @param gensec_security GENSEC context pointer.
660 * @param auth_type DCERPC auth type
661 * @param auth_level DCERPC auth level
664 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
665 uint8_t auth_type, uint8_t auth_level)
667 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
668 if (!gensec_security->ops) {
669 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
670 return NT_STATUS_INVALID_PARAMETER;
672 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
673 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
674 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
675 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
676 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
677 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
678 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
679 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
680 /* Default features */
682 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
684 return NT_STATUS_INVALID_PARAMETER;
687 return gensec_start_mech(gensec_security);
690 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
692 const struct gensec_security_ops *ops;
693 ops = gensec_security_by_authtype(gensec_security, authtype);
701 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
702 const char *oid_string)
704 const struct gensec_security_ops *ops;
705 ops = gensec_security_by_oid(gensec_security, oid_string);
713 * Start a GENSEC sub-mechanism with a specified mechansim structure, used in SPNEGO
717 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
718 const struct gensec_security_ops *ops)
720 gensec_security->ops = ops;
721 return gensec_start_mech(gensec_security);
725 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
727 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
728 * well-known #define to hook it in.
731 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
732 const char *mech_oid)
734 SMB_ASSERT(gensec_security != NULL);
736 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
737 if (!gensec_security->ops) {
738 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
739 return NT_STATUS_INVALID_PARAMETER;
741 return gensec_start_mech(gensec_security);
745 * Start a GENSEC sub-mechanism by a well know SASL name
749 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
750 const char *sasl_name)
752 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
753 if (!gensec_security->ops) {
754 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
755 return NT_STATUS_INVALID_PARAMETER;
757 return gensec_start_mech(gensec_security);
761 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
765 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
766 const char **sasl_names)
768 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
769 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
770 const struct gensec_security_ops **ops;
773 return NT_STATUS_NO_MEMORY;
775 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
777 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
778 str_list_join(mem_ctx,
780 talloc_free(mem_ctx);
781 return NT_STATUS_INVALID_PARAMETER;
783 for (i=0; ops[i]; i++) {
784 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
785 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
789 talloc_free(mem_ctx);
794 * Start a GENSEC sub-mechanism by an internal name
798 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
801 gensec_security->ops = gensec_security_by_name(gensec_security, name);
802 if (!gensec_security->ops) {
803 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
804 return NT_STATUS_INVALID_PARAMETER;
806 return gensec_start_mech(gensec_security);
810 wrappers for the gensec function pointers
812 _PUBLIC_ NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
814 uint8_t *data, size_t length,
815 const uint8_t *whole_pdu, size_t pdu_length,
816 const DATA_BLOB *sig)
818 if (!gensec_security->ops->unseal_packet) {
819 return NT_STATUS_NOT_IMPLEMENTED;
821 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
822 return NT_STATUS_INVALID_PARAMETER;
825 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
827 whole_pdu, pdu_length,
831 _PUBLIC_ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
833 const uint8_t *data, size_t length,
834 const uint8_t *whole_pdu, size_t pdu_length,
835 const DATA_BLOB *sig)
837 if (!gensec_security->ops->check_packet) {
838 return NT_STATUS_NOT_IMPLEMENTED;
840 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
841 return NT_STATUS_INVALID_PARAMETER;
844 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
847 _PUBLIC_ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
849 uint8_t *data, size_t length,
850 const uint8_t *whole_pdu, size_t pdu_length,
853 if (!gensec_security->ops->seal_packet) {
854 return NT_STATUS_NOT_IMPLEMENTED;
856 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
857 return NT_STATUS_INVALID_PARAMETER;
860 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
863 _PUBLIC_ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
865 const uint8_t *data, size_t length,
866 const uint8_t *whole_pdu, size_t pdu_length,
869 if (!gensec_security->ops->sign_packet) {
870 return NT_STATUS_NOT_IMPLEMENTED;
872 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
873 return NT_STATUS_INVALID_PARAMETER;
876 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
879 _PUBLIC_ size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
881 if (!gensec_security->ops->sig_size) {
884 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
888 return gensec_security->ops->sig_size(gensec_security, data_size);
891 size_t gensec_max_wrapped_size(struct gensec_security *gensec_security)
893 if (!gensec_security->ops->max_wrapped_size) {
897 return gensec_security->ops->max_wrapped_size(gensec_security);
900 size_t gensec_max_input_size(struct gensec_security *gensec_security)
902 if (!gensec_security->ops->max_input_size) {
903 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
906 return gensec_security->ops->max_input_size(gensec_security);
909 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
914 if (!gensec_security->ops->wrap) {
915 return NT_STATUS_NOT_IMPLEMENTED;
917 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
920 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
925 if (!gensec_security->ops->unwrap) {
926 return NT_STATUS_NOT_IMPLEMENTED;
928 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
931 _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
932 DATA_BLOB *session_key)
934 if (!gensec_security->ops->session_key) {
935 return NT_STATUS_NOT_IMPLEMENTED;
937 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
938 return NT_STATUS_NO_USER_SESSION_KEY;
941 return gensec_security->ops->session_key(gensec_security, session_key);
945 * Return the credentials of a logged on user, including session keys
948 * Only valid after a successful authentication
950 * May only be called once per authentication.
954 _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
955 struct auth_session_info **session_info)
957 if (!gensec_security->ops->session_info) {
958 return NT_STATUS_NOT_IMPLEMENTED;
960 return gensec_security->ops->session_info(gensec_security, session_info);
964 * Next state function for the GENSEC state machine
966 * @param gensec_security GENSEC State
967 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
968 * @param in The request, as a DATA_BLOB
969 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
970 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
971 * or NT_STATUS_OK if the user is authenticated.
974 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
975 const DATA_BLOB in, DATA_BLOB *out)
977 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
980 struct gensec_update_state {
981 struct tevent_immediate *im;
982 struct gensec_security *gensec_security;
987 static void gensec_update_async_trigger(struct tevent_context *ctx,
988 struct tevent_immediate *im,
991 * Next state function for the GENSEC state machine async version
993 * @param mem_ctx The memory context for the request
994 * @param ev The event context for the request
995 * @param gensec_security GENSEC State
996 * @param in The request, as a DATA_BLOB
998 * @return The request handle or NULL on no memory failure
1001 _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx,
1002 struct tevent_context *ev,
1003 struct gensec_security *gensec_security,
1006 struct tevent_req *req;
1007 struct gensec_update_state *state = NULL;
1009 req = tevent_req_create(mem_ctx, &state,
1010 struct gensec_update_state);
1015 state->gensec_security = gensec_security;
1017 state->out = data_blob(NULL, 0);
1018 state->im = tevent_create_immediate(state);
1019 if (tevent_req_nomem(state->im, req)) {
1020 return tevent_req_post(req, ev);
1023 tevent_schedule_immediate(state->im, ev,
1024 gensec_update_async_trigger,
1030 static void gensec_update_async_trigger(struct tevent_context *ctx,
1031 struct tevent_immediate *im,
1034 struct tevent_req *req =
1035 talloc_get_type_abort(private_data, struct tevent_req);
1036 struct gensec_update_state *state =
1037 tevent_req_data(req, struct gensec_update_state);
1040 status = gensec_update(state->gensec_security, state,
1041 state->in, &state->out);
1042 if (tevent_req_nterror(req, status)) {
1046 tevent_req_done(req);
1050 * Next state function for the GENSEC state machine
1052 * @param req request state
1053 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
1054 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
1055 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
1056 * or NT_STATUS_OK if the user is authenticated.
1058 _PUBLIC_ NTSTATUS gensec_update_recv(struct tevent_req *req,
1059 TALLOC_CTX *out_mem_ctx,
1062 struct gensec_update_state *state =
1063 tevent_req_data(req, struct gensec_update_state);
1066 if (tevent_req_is_nterror(req, &status)) {
1067 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1068 tevent_req_received(req);
1072 status = NT_STATUS_OK;
1076 talloc_steal(out_mem_ctx, out->data);
1078 tevent_req_received(req);
1083 * Set the requirement for a certain feature on the connection
1087 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
1090 if (!gensec_security->ops || !gensec_security->ops->want_feature) {
1091 gensec_security->want_features |= feature;
1094 gensec_security->ops->want_feature(gensec_security, feature);
1098 * Check the requirement for a certain feature on the connection
1102 _PUBLIC_ bool gensec_have_feature(struct gensec_security *gensec_security,
1105 if (!gensec_security->ops->have_feature) {
1109 /* We might 'have' features that we don't 'want', because the
1110 * other end demanded them, or we can't neotiate them off */
1111 return gensec_security->ops->have_feature(gensec_security, feature);
1115 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
1119 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
1121 gensec_security->credentials = talloc_reference(gensec_security, credentials);
1122 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1123 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1124 return NT_STATUS_OK;
1128 * Return the credentials structure associated with a GENSEC context
1132 _PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
1134 if (!gensec_security) {
1137 return gensec_security->credentials;
1141 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
1145 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
1147 gensec_security->target.service = talloc_strdup(gensec_security, service);
1148 if (!gensec_security->target.service) {
1149 return NT_STATUS_NO_MEMORY;
1151 return NT_STATUS_OK;
1154 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security)
1156 if (gensec_security->target.service) {
1157 return gensec_security->target.service;
1164 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
1168 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
1170 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
1171 if (hostname && !gensec_security->target.hostname) {
1172 return NT_STATUS_NO_MEMORY;
1174 return NT_STATUS_OK;
1177 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
1179 /* We allow the target hostname to be overriden for testing purposes */
1180 if (gensec_security->settings->target_hostname) {
1181 return gensec_security->settings->target_hostname;
1184 if (gensec_security->target.hostname) {
1185 return gensec_security->target.hostname;
1188 /* We could add use the 'set sockaddr' call, and do a reverse
1189 * lookup, but this would be both insecure (compromising the
1190 * way kerberos works) and add DNS timeouts */
1195 * Set (and talloc_reference) local and peer socket addresses onto a socket
1196 * context on the GENSEC context.
1198 * This is so that kerberos can include these addresses in
1199 * cryptographic tokens, to avoid certain attacks.
1203 * @brief Set the local gensec address.
1205 * @param gensec_security The gensec security context to use.
1207 * @param remote The local address to set.
1209 * @return On success NT_STATUS_OK is returned or an NT_STATUS
1212 _PUBLIC_ NTSTATUS gensec_set_local_address(struct gensec_security *gensec_security,
1213 const struct tsocket_address *local)
1215 TALLOC_FREE(gensec_security->local_addr);
1217 if (local == NULL) {
1218 return NT_STATUS_OK;
1221 gensec_security->local_addr = tsocket_address_copy(local, gensec_security);
1222 if (gensec_security->local_addr == NULL) {
1223 return NT_STATUS_NO_MEMORY;
1226 return NT_STATUS_OK;
1230 * @brief Set the remote gensec address.
1232 * @param gensec_security The gensec security context to use.
1234 * @param remote The remote address to set.
1236 * @return On success NT_STATUS_OK is returned or an NT_STATUS
1239 _PUBLIC_ NTSTATUS gensec_set_remote_address(struct gensec_security *gensec_security,
1240 const struct tsocket_address *remote)
1242 TALLOC_FREE(gensec_security->remote_addr);
1244 if (remote == NULL) {
1245 return NT_STATUS_OK;
1248 gensec_security->remote_addr = tsocket_address_copy(remote, gensec_security);
1249 if (gensec_security->remote_addr == NULL) {
1250 return NT_STATUS_NO_MEMORY;
1253 return NT_STATUS_OK;
1257 * @brief Get the local address from a gensec security context.
1259 * @param gensec_security The security context to get the address from.
1261 * @return The address as tsocket_address which could be NULL if
1262 * no address is set.
1264 _PUBLIC_ const struct tsocket_address *gensec_get_local_address(struct gensec_security *gensec_security)
1266 if (gensec_security == NULL) {
1269 return gensec_security->local_addr;
1273 * @brief Get the remote address from a gensec security context.
1275 * @param gensec_security The security context to get the address from.
1277 * @return The address as tsocket_address which could be NULL if
1278 * no address is set.
1280 _PUBLIC_ const struct tsocket_address *gensec_get_remote_address(struct gensec_security *gensec_security)
1282 if (gensec_security == NULL) {
1285 return gensec_security->remote_addr;
1289 * Set the target principal (assuming it it known, say from the SPNEGO reply)
1290 * - ensures it is talloc()ed
1294 _PUBLIC_ NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
1296 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1297 if (!gensec_security->target.principal) {
1298 return NT_STATUS_NO_MEMORY;
1300 return NT_STATUS_OK;
1303 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
1305 if (gensec_security->target.principal) {
1306 return gensec_security->target.principal;
1312 NTSTATUS gensec_generate_session_info(TALLOC_CTX *mem_ctx,
1313 struct gensec_security *gensec_security,
1314 struct auth_serversupplied_info *server_info,
1315 struct auth_session_info **session_info)
1318 if (gensec_security->auth_context) {
1319 uint32_t flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
1320 if (server_info->authenticated) {
1321 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
1323 nt_status = gensec_security->auth_context->generate_session_info(mem_ctx, gensec_security->auth_context,
1328 nt_status = auth_generate_simple_session_info(mem_ctx,
1329 server_info, session_info);
1335 register a GENSEC backend.
1337 The 'name' can be later used by other backends to find the operations
1338 structure for this backend.
1340 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
1342 if (gensec_security_by_name(NULL, ops->name) != NULL) {
1343 /* its already registered! */
1344 DEBUG(0,("GENSEC backend '%s' already registered\n",
1346 return NT_STATUS_OBJECT_NAME_COLLISION;
1349 generic_security_ops = talloc_realloc(talloc_autofree_context(),
1350 generic_security_ops,
1351 struct gensec_security_ops *,
1352 gensec_num_backends+2);
1353 if (!generic_security_ops) {
1354 return NT_STATUS_NO_MEMORY;
1357 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
1358 gensec_num_backends++;
1359 generic_security_ops[gensec_num_backends] = NULL;
1361 DEBUG(3,("GENSEC backend '%s' registered\n",
1364 return NT_STATUS_OK;
1368 return the GENSEC interface version, and the size of some critical types
1369 This can be used by backends to either detect compilation errors, or provide
1370 multiple implementations for different smbd compilation options in one module
1372 const struct gensec_critical_sizes *gensec_interface_version(void)
1374 static const struct gensec_critical_sizes critical_sizes = {
1375 GENSEC_INTERFACE_VERSION,
1376 sizeof(struct gensec_security_ops),
1377 sizeof(struct gensec_security),
1380 return &critical_sizes;
1383 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
1384 return (*gs2)->priority - (*gs1)->priority;
1387 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
1389 return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1392 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
1394 return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1398 initialise the GENSEC subsystem
1400 _PUBLIC_ NTSTATUS gensec_init(struct loadparm_context *lp_ctx)
1402 static bool initialized = false;
1403 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
1404 STATIC_gensec_MODULES_PROTO;
1405 init_module_fn static_init[] = { STATIC_gensec_MODULES };
1406 init_module_fn *shared_init;
1408 if (initialized) return NT_STATUS_OK;
1411 shared_init = load_samba_modules(NULL, lp_ctx, "gensec");
1413 run_init_functions(static_init);
1414 run_init_functions(shared_init);
1416 talloc_free(shared_init);
1418 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
1420 return NT_STATUS_OK;