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 lp_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(mem_ctx, struct gensec_security);
525 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
527 (*gensec_security)->ops = NULL;
528 (*gensec_security)->local_addr = NULL;
529 (*gensec_security)->remote_addr = NULL;
530 (*gensec_security)->private_data = NULL;
532 ZERO_STRUCT((*gensec_security)->target);
534 (*gensec_security)->subcontext = false;
535 (*gensec_security)->want_features = 0;
537 (*gensec_security)->event_ctx = ev;
538 SMB_ASSERT(settings->lp_ctx != NULL);
539 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
540 (*gensec_security)->auth_context = talloc_steal(*gensec_security, auth_context);
546 * Start a GENSEC subcontext, with a copy of the properties of the parent
547 * @param mem_ctx The parent TALLOC memory context.
548 * @param parent The parent GENSEC context
549 * @param gensec_security Returned GENSEC context pointer.
550 * @note Used by SPNEGO in particular, for the actual implementation mechanism
553 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
554 struct gensec_security *parent,
555 struct gensec_security **gensec_security)
557 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
558 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
560 (**gensec_security) = *parent;
561 (*gensec_security)->ops = NULL;
562 (*gensec_security)->private_data = NULL;
564 (*gensec_security)->subcontext = true;
565 (*gensec_security)->want_features = parent->want_features;
566 (*gensec_security)->event_ctx = parent->event_ctx;
567 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
568 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
569 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
575 Start the GENSEC system, in client mode, returning a context pointer.
576 @param mem_ctx The parent TALLOC memory context.
577 @param gensec_security Returned GENSEC context pointer.
578 @note The mem_ctx is only a parent and may be NULL.
580 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
581 struct gensec_security **gensec_security,
582 struct tevent_context *ev,
583 struct gensec_settings *settings)
587 if (settings == NULL) {
588 DEBUG(0,("gensec_client_start: no settings given!\n"));
589 return NT_STATUS_INTERNAL_ERROR;
592 status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
593 if (!NT_STATUS_IS_OK(status)) {
596 (*gensec_security)->gensec_role = GENSEC_CLIENT;
604 Start the GENSEC system, in server mode, returning a context pointer.
605 @param mem_ctx The parent TALLOC memory context.
606 @param gensec_security Returned GENSEC context pointer.
607 @note The mem_ctx is only a parent and may be NULL.
609 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
610 struct tevent_context *ev,
611 struct gensec_settings *settings,
612 struct auth_context *auth_context,
613 struct gensec_security **gensec_security)
618 DEBUG(0,("gensec_server_start: no event context given!\n"));
619 return NT_STATUS_INTERNAL_ERROR;
623 DEBUG(0,("gensec_server_start: no settings given!\n"));
624 return NT_STATUS_INTERNAL_ERROR;
627 status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
628 if (!NT_STATUS_IS_OK(status)) {
631 (*gensec_security)->gensec_role = GENSEC_SERVER;
636 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
639 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
640 gensec_security->subcontext ? "sub" : "",
641 gensec_security->ops->name));
642 switch (gensec_security->gensec_role) {
644 if (gensec_security->ops->client_start) {
645 status = gensec_security->ops->client_start(gensec_security);
646 if (!NT_STATUS_IS_OK(status)) {
647 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
648 gensec_security->ops->name, nt_errstr(status)));
654 if (gensec_security->ops->server_start) {
655 status = gensec_security->ops->server_start(gensec_security);
656 if (!NT_STATUS_IS_OK(status)) {
657 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
658 gensec_security->ops->name, nt_errstr(status)));
664 return NT_STATUS_INVALID_PARAMETER;
668 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
669 * @param gensec_security GENSEC context pointer.
670 * @param auth_type DCERPC auth type
671 * @param auth_level DCERPC auth level
674 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
675 uint8_t auth_type, uint8_t auth_level)
677 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
678 if (!gensec_security->ops) {
679 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
680 return NT_STATUS_INVALID_PARAMETER;
682 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
683 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
684 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
685 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
686 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
687 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
688 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
689 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
690 /* Default features */
692 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
694 return NT_STATUS_INVALID_PARAMETER;
697 return gensec_start_mech(gensec_security);
700 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
702 const struct gensec_security_ops *ops;
703 ops = gensec_security_by_authtype(gensec_security, authtype);
711 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
712 const char *oid_string)
714 const struct gensec_security_ops *ops;
715 ops = gensec_security_by_oid(gensec_security, oid_string);
724 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
728 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
729 const struct gensec_security_ops *ops)
731 gensec_security->ops = ops;
732 return gensec_start_mech(gensec_security);
736 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
738 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
739 * well-known #define to hook it in.
742 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
743 const char *mech_oid)
745 SMB_ASSERT(gensec_security != NULL);
747 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
748 if (!gensec_security->ops) {
749 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
750 return NT_STATUS_INVALID_PARAMETER;
752 return gensec_start_mech(gensec_security);
756 * Start a GENSEC sub-mechanism by a well know SASL name
760 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
761 const char *sasl_name)
763 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
764 if (!gensec_security->ops) {
765 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
766 return NT_STATUS_INVALID_PARAMETER;
768 return gensec_start_mech(gensec_security);
772 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
776 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
777 const char **sasl_names)
779 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
780 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
781 const struct gensec_security_ops **ops;
784 return NT_STATUS_NO_MEMORY;
786 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
788 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
789 str_list_join(mem_ctx,
791 talloc_free(mem_ctx);
792 return NT_STATUS_INVALID_PARAMETER;
794 for (i=0; ops[i]; i++) {
795 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
796 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
800 talloc_free(mem_ctx);
805 * Start a GENSEC sub-mechanism by an internal name
809 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
812 gensec_security->ops = gensec_security_by_name(gensec_security, name);
813 if (!gensec_security->ops) {
814 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
815 return NT_STATUS_INVALID_PARAMETER;
817 return gensec_start_mech(gensec_security);
821 wrappers for the gensec function pointers
823 _PUBLIC_ NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
825 uint8_t *data, size_t length,
826 const uint8_t *whole_pdu, size_t pdu_length,
827 const DATA_BLOB *sig)
829 if (!gensec_security->ops->unseal_packet) {
830 return NT_STATUS_NOT_IMPLEMENTED;
832 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
833 return NT_STATUS_INVALID_PARAMETER;
836 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
838 whole_pdu, pdu_length,
842 _PUBLIC_ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
844 const uint8_t *data, size_t length,
845 const uint8_t *whole_pdu, size_t pdu_length,
846 const DATA_BLOB *sig)
848 if (!gensec_security->ops->check_packet) {
849 return NT_STATUS_NOT_IMPLEMENTED;
851 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
852 return NT_STATUS_INVALID_PARAMETER;
855 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
858 _PUBLIC_ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
860 uint8_t *data, size_t length,
861 const uint8_t *whole_pdu, size_t pdu_length,
864 if (!gensec_security->ops->seal_packet) {
865 return NT_STATUS_NOT_IMPLEMENTED;
867 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
868 return NT_STATUS_INVALID_PARAMETER;
871 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
874 _PUBLIC_ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
876 const uint8_t *data, size_t length,
877 const uint8_t *whole_pdu, size_t pdu_length,
880 if (!gensec_security->ops->sign_packet) {
881 return NT_STATUS_NOT_IMPLEMENTED;
883 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
884 return NT_STATUS_INVALID_PARAMETER;
887 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
890 _PUBLIC_ size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
892 if (!gensec_security->ops->sig_size) {
895 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
899 return gensec_security->ops->sig_size(gensec_security, data_size);
902 size_t gensec_max_wrapped_size(struct gensec_security *gensec_security)
904 if (!gensec_security->ops->max_wrapped_size) {
908 return gensec_security->ops->max_wrapped_size(gensec_security);
911 size_t gensec_max_input_size(struct gensec_security *gensec_security)
913 if (!gensec_security->ops->max_input_size) {
914 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
917 return gensec_security->ops->max_input_size(gensec_security);
920 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
925 if (!gensec_security->ops->wrap) {
926 return NT_STATUS_NOT_IMPLEMENTED;
928 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
931 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
936 if (!gensec_security->ops->unwrap) {
937 return NT_STATUS_NOT_IMPLEMENTED;
939 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
942 _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
943 DATA_BLOB *session_key)
945 if (!gensec_security->ops->session_key) {
946 return NT_STATUS_NOT_IMPLEMENTED;
948 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
949 return NT_STATUS_NO_USER_SESSION_KEY;
952 return gensec_security->ops->session_key(gensec_security, session_key);
956 * Return the credentials of a logged on user, including session keys
959 * Only valid after a successful authentication
961 * May only be called once per authentication.
965 _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
966 struct auth_session_info **session_info)
968 if (!gensec_security->ops->session_info) {
969 return NT_STATUS_NOT_IMPLEMENTED;
971 return gensec_security->ops->session_info(gensec_security, session_info);
975 * Next state function for the GENSEC state machine
977 * @param gensec_security GENSEC State
978 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
979 * @param in The request, as a DATA_BLOB
980 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
981 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
982 * or NT_STATUS_OK if the user is authenticated.
985 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
986 const DATA_BLOB in, DATA_BLOB *out)
988 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
991 struct gensec_update_state {
992 struct tevent_immediate *im;
993 struct gensec_security *gensec_security;
998 static void gensec_update_async_trigger(struct tevent_context *ctx,
999 struct tevent_immediate *im,
1000 void *private_data);
1002 * Next state function for the GENSEC state machine async version
1004 * @param mem_ctx The memory context for the request
1005 * @param ev The event context for the request
1006 * @param gensec_security GENSEC State
1007 * @param in The request, as a DATA_BLOB
1009 * @return The request handle or NULL on no memory failure
1012 _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx,
1013 struct tevent_context *ev,
1014 struct gensec_security *gensec_security,
1017 struct tevent_req *req;
1018 struct gensec_update_state *state = NULL;
1020 req = tevent_req_create(mem_ctx, &state,
1021 struct gensec_update_state);
1026 state->gensec_security = gensec_security;
1028 state->out = data_blob(NULL, 0);
1029 state->im = tevent_create_immediate(state);
1030 if (tevent_req_nomem(state->im, req)) {
1031 return tevent_req_post(req, ev);
1034 tevent_schedule_immediate(state->im, ev,
1035 gensec_update_async_trigger,
1041 static void gensec_update_async_trigger(struct tevent_context *ctx,
1042 struct tevent_immediate *im,
1045 struct tevent_req *req =
1046 talloc_get_type_abort(private_data, struct tevent_req);
1047 struct gensec_update_state *state =
1048 tevent_req_data(req, struct gensec_update_state);
1051 status = gensec_update(state->gensec_security, state,
1052 state->in, &state->out);
1053 if (tevent_req_nterror(req, status)) {
1057 tevent_req_done(req);
1061 * Next state function for the GENSEC state machine
1063 * @param req request state
1064 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
1065 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
1066 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
1067 * or NT_STATUS_OK if the user is authenticated.
1069 _PUBLIC_ NTSTATUS gensec_update_recv(struct tevent_req *req,
1070 TALLOC_CTX *out_mem_ctx,
1073 struct gensec_update_state *state =
1074 tevent_req_data(req, struct gensec_update_state);
1077 if (tevent_req_is_nterror(req, &status)) {
1078 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1079 tevent_req_received(req);
1083 status = NT_STATUS_OK;
1087 talloc_steal(out_mem_ctx, out->data);
1089 tevent_req_received(req);
1094 * Set the requirement for a certain feature on the connection
1098 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
1101 if (!gensec_security->ops || !gensec_security->ops->want_feature) {
1102 gensec_security->want_features |= feature;
1105 gensec_security->ops->want_feature(gensec_security, feature);
1109 * Check the requirement for a certain feature on the connection
1113 _PUBLIC_ bool gensec_have_feature(struct gensec_security *gensec_security,
1116 if (!gensec_security->ops->have_feature) {
1120 /* We might 'have' features that we don't 'want', because the
1121 * other end demanded them, or we can't neotiate them off */
1122 return gensec_security->ops->have_feature(gensec_security, feature);
1126 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
1130 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
1132 gensec_security->credentials = talloc_reference(gensec_security, credentials);
1133 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1134 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1135 return NT_STATUS_OK;
1139 * Return the credentials structure associated with a GENSEC context
1143 _PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
1145 if (!gensec_security) {
1148 return gensec_security->credentials;
1152 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
1156 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
1158 gensec_security->target.service = talloc_strdup(gensec_security, service);
1159 if (!gensec_security->target.service) {
1160 return NT_STATUS_NO_MEMORY;
1162 return NT_STATUS_OK;
1165 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security)
1167 if (gensec_security->target.service) {
1168 return gensec_security->target.service;
1175 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
1179 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
1181 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
1182 if (hostname && !gensec_security->target.hostname) {
1183 return NT_STATUS_NO_MEMORY;
1185 return NT_STATUS_OK;
1188 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
1190 /* We allow the target hostname to be overriden for testing purposes */
1191 if (gensec_security->settings->target_hostname) {
1192 return gensec_security->settings->target_hostname;
1195 if (gensec_security->target.hostname) {
1196 return gensec_security->target.hostname;
1199 /* We could add use the 'set sockaddr' call, and do a reverse
1200 * lookup, but this would be both insecure (compromising the
1201 * way kerberos works) and add DNS timeouts */
1206 * Set (and talloc_reference) local and peer socket addresses onto a socket
1207 * context on the GENSEC context.
1209 * This is so that kerberos can include these addresses in
1210 * cryptographic tokens, to avoid certain attacks.
1214 * @brief Set the local gensec address.
1216 * @param gensec_security The gensec security context to use.
1218 * @param remote The local address to set.
1220 * @return On success NT_STATUS_OK is returned or an NT_STATUS
1223 _PUBLIC_ NTSTATUS gensec_set_local_address(struct gensec_security *gensec_security,
1224 const struct tsocket_address *local)
1226 TALLOC_FREE(gensec_security->local_addr);
1228 if (local == NULL) {
1229 return NT_STATUS_OK;
1232 gensec_security->local_addr = tsocket_address_copy(local, gensec_security);
1233 if (gensec_security->local_addr == NULL) {
1234 return NT_STATUS_NO_MEMORY;
1237 return NT_STATUS_OK;
1241 * @brief Set the remote gensec address.
1243 * @param gensec_security The gensec security context to use.
1245 * @param remote The remote address to set.
1247 * @return On success NT_STATUS_OK is returned or an NT_STATUS
1250 _PUBLIC_ NTSTATUS gensec_set_remote_address(struct gensec_security *gensec_security,
1251 const struct tsocket_address *remote)
1253 TALLOC_FREE(gensec_security->remote_addr);
1255 if (remote == NULL) {
1256 return NT_STATUS_OK;
1259 gensec_security->remote_addr = tsocket_address_copy(remote, gensec_security);
1260 if (gensec_security->remote_addr == NULL) {
1261 return NT_STATUS_NO_MEMORY;
1264 return NT_STATUS_OK;
1268 * @brief Get the local address from a gensec security context.
1270 * @param gensec_security The security context to get the address from.
1272 * @return The address as tsocket_address which could be NULL if
1273 * no address is set.
1275 _PUBLIC_ const struct tsocket_address *gensec_get_local_address(struct gensec_security *gensec_security)
1277 if (gensec_security == NULL) {
1280 return gensec_security->local_addr;
1284 * @brief Get the remote address from a gensec security context.
1286 * @param gensec_security The security context to get the address from.
1288 * @return The address as tsocket_address which could be NULL if
1289 * no address is set.
1291 _PUBLIC_ const struct tsocket_address *gensec_get_remote_address(struct gensec_security *gensec_security)
1293 if (gensec_security == NULL) {
1296 return gensec_security->remote_addr;
1300 * Set the target principal (assuming it it known, say from the SPNEGO reply)
1301 * - ensures it is talloc()ed
1305 _PUBLIC_ NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
1307 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1308 if (!gensec_security->target.principal) {
1309 return NT_STATUS_NO_MEMORY;
1311 return NT_STATUS_OK;
1314 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
1316 if (gensec_security->target.principal) {
1317 return gensec_security->target.principal;
1323 NTSTATUS gensec_generate_session_info(TALLOC_CTX *mem_ctx,
1324 struct gensec_security *gensec_security,
1325 struct auth_serversupplied_info *server_info,
1326 struct auth_session_info **session_info)
1329 if (gensec_security->auth_context) {
1330 uint32_t flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
1331 if (server_info->authenticated) {
1332 flags |= AUTH_SESSION_INFO_AUTHENTICATED;
1334 nt_status = gensec_security->auth_context->generate_session_info(mem_ctx, gensec_security->auth_context,
1339 nt_status = auth_generate_simple_session_info(mem_ctx,
1340 server_info, session_info);
1346 register a GENSEC backend.
1348 The 'name' can be later used by other backends to find the operations
1349 structure for this backend.
1351 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
1353 if (gensec_security_by_name(NULL, ops->name) != NULL) {
1354 /* its already registered! */
1355 DEBUG(0,("GENSEC backend '%s' already registered\n",
1357 return NT_STATUS_OBJECT_NAME_COLLISION;
1360 generic_security_ops = talloc_realloc(talloc_autofree_context(),
1361 generic_security_ops,
1362 struct gensec_security_ops *,
1363 gensec_num_backends+2);
1364 if (!generic_security_ops) {
1365 return NT_STATUS_NO_MEMORY;
1368 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
1369 gensec_num_backends++;
1370 generic_security_ops[gensec_num_backends] = NULL;
1372 DEBUG(3,("GENSEC backend '%s' registered\n",
1375 return NT_STATUS_OK;
1379 return the GENSEC interface version, and the size of some critical types
1380 This can be used by backends to either detect compilation errors, or provide
1381 multiple implementations for different smbd compilation options in one module
1383 const struct gensec_critical_sizes *gensec_interface_version(void)
1385 static const struct gensec_critical_sizes critical_sizes = {
1386 GENSEC_INTERFACE_VERSION,
1387 sizeof(struct gensec_security_ops),
1388 sizeof(struct gensec_security),
1391 return &critical_sizes;
1394 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
1395 return (*gs2)->priority - (*gs1)->priority;
1398 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
1400 return lp_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1403 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
1405 return lp_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1409 initialise the GENSEC subsystem
1411 _PUBLIC_ NTSTATUS gensec_init(struct loadparm_context *lp_ctx)
1413 static bool initialized = false;
1414 extern NTSTATUS gensec_sasl_init(void);
1415 extern NTSTATUS gensec_krb5_init(void);
1416 extern NTSTATUS gensec_schannel_init(void);
1417 extern NTSTATUS gensec_spnego_init(void);
1418 extern NTSTATUS gensec_gssapi_init(void);
1419 extern NTSTATUS gensec_ntlmssp_init(void);
1421 init_module_fn static_init[] = { STATIC_gensec_MODULES };
1422 init_module_fn *shared_init;
1424 if (initialized) return NT_STATUS_OK;
1427 shared_init = load_samba_modules(NULL, lp_ctx, "gensec");
1429 run_init_functions(static_init);
1430 run_init_functions(shared_init);
1432 talloc_free(shared_init);
1434 TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
1436 return NT_STATUS_OK;