2 Unix SMB/CIFS implementation.
4 Generic Authentication Interface
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "auth/auth.h"
26 #include "lib/events/events.h"
28 #include "librpc/rpc/dcerpc.h"
30 /* the list of currently registered GENSEC backends */
31 static struct gensec_security_ops **generic_security_ops;
32 static int gensec_num_backends;
34 /* Return all the registered mechs. Don't modify the return pointer,
35 * but you may talloc_reference it if convient */
36 struct gensec_security_ops **gensec_security_all(void)
38 return generic_security_ops;
41 /* Sometimes we want to force only kerberos, sometimes we want to
42 * force it's avoidance. The old list could be either
43 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
44 * an existing list we have trimmed down) */
46 struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
47 struct gensec_security_ops **old_gensec_list,
48 enum credentials_use_kerberos use_kerberos)
50 struct gensec_security_ops **new_gensec_list;
51 int i, j, num_mechs_in;
53 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
54 talloc_reference(mem_ctx, old_gensec_list);
55 return old_gensec_list;
58 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
62 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
63 if (!new_gensec_list) {
68 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
70 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
71 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
72 new_gensec_list[j] = old_gensec_list[i];
77 switch (use_kerberos) {
78 case CRED_DONT_USE_KERBEROS:
79 if (old_gensec_list[i]->kerberos == False) {
80 new_gensec_list[j] = old_gensec_list[i];
84 case CRED_MUST_USE_KERBEROS:
85 if (old_gensec_list[i]->kerberos == True) {
86 new_gensec_list[j] = old_gensec_list[i];
91 /* Can't happen or invalid parameter */
95 new_gensec_list[j] = NULL;
97 return new_gensec_list;
100 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
103 struct gensec_security_ops **backends;
104 backends = gensec_security_all();
105 if (!gensec_security) {
106 talloc_reference(mem_ctx, backends);
109 enum credentials_use_kerberos use_kerberos;
110 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
112 talloc_reference(mem_ctx, backends);
115 use_kerberos = cli_credentials_get_kerberos_state(creds);
116 return gensec_use_kerberos_mechs(mem_ctx, backends, use_kerberos);
120 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
124 struct gensec_security_ops **backends;
125 const struct gensec_security_ops *backend;
126 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
130 backends = gensec_security_mechs(gensec_security, mem_ctx);
131 for (i=0; backends && backends[i]; i++) {
132 if (backends[i]->auth_type == auth_type) {
133 backend = backends[i];
134 talloc_free(mem_ctx);
138 talloc_free(mem_ctx);
143 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
144 const char *oid_string)
147 struct gensec_security_ops **backends;
148 const struct gensec_security_ops *backend;
149 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
153 backends = gensec_security_mechs(gensec_security, mem_ctx);
154 for (i=0; backends && backends[i]; i++) {
155 if (backends[i]->oid) {
156 for (j=0; backends[i]->oid[j]; j++) {
157 if (backends[i]->oid[j] &&
158 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
159 backend = backends[i];
160 talloc_free(mem_ctx);
166 talloc_free(mem_ctx);
171 static const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
172 const char *sasl_name)
175 struct gensec_security_ops **backends;
176 const struct gensec_security_ops *backend;
177 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
181 backends = gensec_security_mechs(gensec_security, mem_ctx);
182 for (i=0; backends && backends[i]; i++) {
183 if (backends[i]->sasl_name
184 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
185 backend = backends[i];
186 talloc_free(mem_ctx);
190 talloc_free(mem_ctx);
195 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
199 struct gensec_security_ops **backends;
200 const struct gensec_security_ops *backend;
201 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
205 backends = gensec_security_mechs(gensec_security, mem_ctx);
206 for (i=0; backends && backends[i]; i++) {
207 if (backends[i]->name
208 && (strcmp(backends[i]->name, name) == 0)) {
209 backend = backends[i];
210 talloc_free(mem_ctx);
214 talloc_free(mem_ctx);
219 * Return a unique list of security subsystems from those specified in
220 * the list of SASL names.
222 * Use the list of enabled GENSEC mechanisms from the credentials
223 * attached to the gensec_security, and return in our preferred order.
226 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
228 const char **sasl_names)
230 const struct gensec_security_ops **backends_out;
231 struct gensec_security_ops **backends;
233 int num_backends_out = 0;
239 backends = gensec_security_mechs(gensec_security, mem_ctx);
241 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
245 backends_out[0] = NULL;
247 /* Find backends in our preferred order, by walking our list,
248 * then looking in the supplied list */
249 for (i=0; backends && backends[i]; i++) {
250 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
251 if (!backends[i]->sasl_name ||
252 !(strcmp(backends[i]->sasl_name,
253 sasl_names[sasl_idx]) == 0)) {
257 for (k=0; backends_out[k]; k++) {
258 if (backends_out[k] == backends[i]) {
263 if (k < num_backends_out) {
264 /* already in there */
268 backends_out = talloc_realloc(mem_ctx, backends_out,
269 const struct gensec_security_ops *,
270 num_backends_out + 2);
275 backends_out[num_backends_out] = backends[i];
277 backends_out[num_backends_out] = NULL;
284 * Return a unique list of security subsystems from those specified in
285 * the OID list. That is, where two OIDs refer to the same module,
286 * return that module only once.
288 * Use the list of enabled GENSEC mechanisms from the credentials
289 * attached to the gensec_security, and return in our preferred order.
292 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
294 const char **oid_strings,
297 struct gensec_security_ops_wrapper *backends_out;
298 struct gensec_security_ops **backends;
299 int i, j, k, oid_idx;
300 int num_backends_out = 0;
306 backends = gensec_security_mechs(gensec_security, gensec_security);
308 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
312 backends_out[0].op = NULL;
313 backends_out[0].oid = NULL;
315 /* Find backends in our preferred order, by walking our list,
316 * then looking in the supplied list */
317 for (i=0; backends && backends[i]; i++) {
318 if (!backends[i]->oid) {
321 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
322 if (strcmp(oid_strings[oid_idx], skip) == 0) {
326 for (j=0; backends[i]->oid[j]; j++) {
327 if (!backends[i]->oid[j] ||
328 !(strcmp(backends[i]->oid[j],
329 oid_strings[oid_idx]) == 0)) {
333 for (k=0; backends_out[k].op; k++) {
334 if (backends_out[k].op == backends[i]) {
339 if (k < num_backends_out) {
340 /* already in there */
344 backends_out = talloc_realloc(mem_ctx, backends_out,
345 struct gensec_security_ops_wrapper,
346 num_backends_out + 2);
351 backends_out[num_backends_out].op = backends[i];
352 backends_out[num_backends_out].oid = backends[i]->oid[j];
354 backends_out[num_backends_out].op = NULL;
355 backends_out[num_backends_out].oid = NULL;
363 * Return OIDS from the security subsystems listed
366 const char **gensec_security_oids_from_ops(TALLOC_CTX *mem_ctx,
367 struct gensec_security_ops **ops,
373 const char **oid_list;
377 oid_list = talloc_array(mem_ctx, const char *, 1);
382 for (i=0; ops && ops[i]; i++) {
387 for (k = 0; ops[i]->oid[k]; k++) {
388 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
390 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
394 oid_list[j] = ops[i]->oid[k];
405 * Return OIDS from the security subsystems listed
408 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
409 const struct gensec_security_ops_wrapper *wops)
414 const char **oid_list;
418 oid_list = talloc_array(mem_ctx, const char *, 1);
423 for (i=0; wops[i].op; i++) {
424 if (!wops[i].op->oid) {
428 for (k = 0; wops[i].op->oid[k]; k++) {
429 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
433 oid_list[j] = wops[i].op->oid[k];
443 * Return all the security subsystems currently enabled on a GENSEC context.
445 * This is taken from a list attached to the cli_credentails, and
446 * skips the OID in 'skip'. (Typically the SPNEGO OID)
450 const char **gensec_security_oids(struct gensec_security *gensec_security,
454 struct gensec_security_ops **ops
455 = gensec_security_mechs(gensec_security, mem_ctx);
456 return gensec_security_oids_from_ops(mem_ctx, ops, skip);
462 Start the GENSEC system, returning a context pointer.
463 @param mem_ctx The parent TALLOC memory context.
464 @param gensec_security Returned GENSEC context pointer.
465 @note The mem_ctx is only a parent and may be NULL.
467 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
468 struct gensec_security **gensec_security,
469 struct event_context *ev)
471 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
472 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
474 (*gensec_security)->ops = NULL;
476 ZERO_STRUCT((*gensec_security)->target);
477 ZERO_STRUCT((*gensec_security)->peer_addr);
478 ZERO_STRUCT((*gensec_security)->my_addr);
480 (*gensec_security)->subcontext = False;
481 (*gensec_security)->want_features = 0;
484 ev = event_context_init(*gensec_security);
486 talloc_free(*gensec_security);
487 return NT_STATUS_NO_MEMORY;
491 (*gensec_security)->event_ctx = ev;
497 * Start a GENSEC subcontext, with a copy of the properties of the parent
498 * @param mem_ctx The parent TALLOC memory context.
499 * @param parent The parent GENSEC context
500 * @param gensec_security Returned GENSEC context pointer.
501 * @note Used by SPNEGO in particular, for the actual implementation mechanism
504 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
505 struct gensec_security *parent,
506 struct gensec_security **gensec_security)
508 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
509 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
511 (**gensec_security) = *parent;
512 (*gensec_security)->ops = NULL;
513 (*gensec_security)->private_data = NULL;
515 (*gensec_security)->subcontext = True;
516 (*gensec_security)->event_ctx = parent->event_ctx;
522 Start the GENSEC system, in client mode, returning a context pointer.
523 @param mem_ctx The parent TALLOC memory context.
524 @param gensec_security Returned GENSEC context pointer.
525 @note The mem_ctx is only a parent and may be NULL.
527 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
528 struct gensec_security **gensec_security,
529 struct event_context *ev)
532 status = gensec_start(mem_ctx, gensec_security, ev);
533 if (!NT_STATUS_IS_OK(status)) {
536 (*gensec_security)->gensec_role = GENSEC_CLIENT;
542 Start the GENSEC system, in server mode, returning a context pointer.
543 @param mem_ctx The parent TALLOC memory context.
544 @param gensec_security Returned GENSEC context pointer.
545 @note The mem_ctx is only a parent and may be NULL.
547 NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
548 struct gensec_security **gensec_security,
549 struct event_context *ev)
552 status = gensec_start(mem_ctx, gensec_security, ev);
553 if (!NT_STATUS_IS_OK(status)) {
556 (*gensec_security)->gensec_role = GENSEC_SERVER;
561 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
564 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
565 gensec_security->subcontext ? "sub" : "",
566 gensec_security->ops->name));
567 switch (gensec_security->gensec_role) {
569 if (gensec_security->ops->client_start) {
570 status = gensec_security->ops->client_start(gensec_security);
571 if (!NT_STATUS_IS_OK(status)) {
572 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
573 gensec_security->ops->name, nt_errstr(status)));
579 if (gensec_security->ops->server_start) {
580 status = gensec_security->ops->server_start(gensec_security);
581 if (!NT_STATUS_IS_OK(status)) {
582 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
583 gensec_security->ops->name, nt_errstr(status)));
589 return NT_STATUS_INVALID_PARAMETER;
593 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
594 * @param gensec_security GENSEC context pointer.
595 * @param auth_type DCERPC auth type
596 * @param auth_level DCERPC auth level
599 NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
600 uint8_t auth_type, uint8_t auth_level)
602 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
603 if (!gensec_security->ops) {
604 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
605 return NT_STATUS_INVALID_PARAMETER;
607 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
608 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
609 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
610 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
611 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
612 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
613 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
614 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
615 /* Default features */
617 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
619 return NT_STATUS_INVALID_PARAMETER;
622 return gensec_start_mech(gensec_security);
625 const char *gensec_get_name_by_authtype(uint8_t authtype)
627 const struct gensec_security_ops *ops;
628 ops = gensec_security_by_authtype(NULL, authtype);
636 const char *gensec_get_name_by_oid(const char *oid_string)
638 const struct gensec_security_ops *ops;
639 ops = gensec_security_by_oid(NULL, oid_string);
648 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
652 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
653 const struct gensec_security_ops *ops)
655 gensec_security->ops = ops;
656 return gensec_start_mech(gensec_security);
660 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
662 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
663 * well-known #define to hook it in.
666 NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
667 const char *mech_oid)
669 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
670 if (!gensec_security->ops) {
671 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
672 return NT_STATUS_INVALID_PARAMETER;
674 return gensec_start_mech(gensec_security);
678 * Start a GENSEC sub-mechanism by a well know SASL name
682 NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
683 const char *sasl_name)
685 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
686 if (!gensec_security->ops) {
687 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
688 return NT_STATUS_INVALID_PARAMETER;
690 return gensec_start_mech(gensec_security);
694 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
698 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
699 const char **sasl_names)
702 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
703 const struct gensec_security_ops **ops;
705 return NT_STATUS_NO_MEMORY;
707 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
709 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
710 str_list_join(mem_ctx,
712 talloc_free(mem_ctx);
713 return NT_STATUS_INVALID_PARAMETER;
715 nt_status = gensec_start_mech_by_ops(gensec_security, ops[0]);
716 talloc_free(mem_ctx);
721 * Start a GENSEC sub-mechanism by an internal name
725 NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
728 gensec_security->ops = gensec_security_by_name(gensec_security, name);
729 if (!gensec_security->ops) {
730 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
731 return NT_STATUS_INVALID_PARAMETER;
733 return gensec_start_mech(gensec_security);
737 wrappers for the gensec function pointers
739 NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
741 uint8_t *data, size_t length,
742 const uint8_t *whole_pdu, size_t pdu_length,
743 const DATA_BLOB *sig)
745 if (!gensec_security->ops->unseal_packet) {
746 return NT_STATUS_NOT_IMPLEMENTED;
748 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
749 return NT_STATUS_INVALID_PARAMETER;
752 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
754 whole_pdu, pdu_length,
758 NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
760 const uint8_t *data, size_t length,
761 const uint8_t *whole_pdu, size_t pdu_length,
762 const DATA_BLOB *sig)
764 if (!gensec_security->ops->check_packet) {
765 return NT_STATUS_NOT_IMPLEMENTED;
767 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
768 return NT_STATUS_INVALID_PARAMETER;
771 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
774 NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
776 uint8_t *data, size_t length,
777 const uint8_t *whole_pdu, size_t pdu_length,
780 if (!gensec_security->ops->seal_packet) {
781 return NT_STATUS_NOT_IMPLEMENTED;
783 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
784 return NT_STATUS_INVALID_PARAMETER;
787 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
790 NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
792 const uint8_t *data, size_t length,
793 const uint8_t *whole_pdu, size_t pdu_length,
796 if (!gensec_security->ops->sign_packet) {
797 return NT_STATUS_NOT_IMPLEMENTED;
799 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
800 return NT_STATUS_INVALID_PARAMETER;
803 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
806 size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
808 if (!gensec_security->ops->sig_size) {
811 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
815 return gensec_security->ops->sig_size(gensec_security, data_size);
818 size_t gensec_max_input_size(struct gensec_security *gensec_security)
820 if (!gensec_security->ops->max_input_size) {
821 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
824 return gensec_security->ops->max_input_size(gensec_security);
827 size_t gensec_max_wrapped_size(struct gensec_security *gensec_security)
829 if (!gensec_security->ops->max_wrapped_size) {
833 return gensec_security->ops->max_wrapped_size(gensec_security);
836 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
841 if (!gensec_security->ops->wrap) {
842 return NT_STATUS_NOT_IMPLEMENTED;
844 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
847 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
852 if (!gensec_security->ops->unwrap) {
853 return NT_STATUS_NOT_IMPLEMENTED;
855 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
858 NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
859 DATA_BLOB *session_key)
861 if (!gensec_security->ops->session_key) {
862 return NT_STATUS_NOT_IMPLEMENTED;
864 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
865 return NT_STATUS_NO_USER_SESSION_KEY;
868 return gensec_security->ops->session_key(gensec_security, session_key);
872 * Return the credentials of a logged on user, including session keys
875 * Only valid after a successful authentication
877 * May only be called once per authentication.
881 NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
882 struct auth_session_info **session_info)
884 if (!gensec_security->ops->session_info) {
885 return NT_STATUS_NOT_IMPLEMENTED;
887 return gensec_security->ops->session_info(gensec_security, session_info);
891 * Next state function for the GENSEC state machine
893 * @param gensec_security GENSEC State
894 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
895 * @param in The request, as a DATA_BLOB
896 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
897 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
898 * or NT_STATUS_OK if the user is authenticated.
901 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
902 const DATA_BLOB in, DATA_BLOB *out)
904 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
908 * Set the requirement for a certain feature on the connection
912 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
915 gensec_security->want_features |= feature;
919 * Check the requirement for a certain feature on the connection
923 _PUBLIC_ BOOL gensec_have_feature(struct gensec_security *gensec_security,
926 if (!gensec_security->ops->have_feature) {
930 /* Can only 'have' a feature if you already 'want'ed it */
931 if (gensec_security->want_features & feature) {
932 return gensec_security->ops->have_feature(gensec_security, feature);
938 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
942 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
944 gensec_security->credentials = talloc_reference(gensec_security, credentials);
949 * Return the credentials structure associated with a GENSEC context
953 struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
955 if (!gensec_security) {
958 return gensec_security->credentials;
962 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
966 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
968 gensec_security->target.service = talloc_strdup(gensec_security, service);
969 if (!gensec_security->target.service) {
970 return NT_STATUS_NO_MEMORY;
975 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security)
977 if (gensec_security->target.service) {
978 return gensec_security->target.service;
985 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
989 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
991 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
992 if (!gensec_security->target.hostname) {
993 return NT_STATUS_NO_MEMORY;
998 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
1000 /* We allow the target hostname to be overriden for testing purposes */
1001 const char *target_hostname = lp_parm_string(-1, "gensec", "target_hostname");
1002 if (target_hostname) {
1003 return target_hostname;
1006 if (gensec_security->target.hostname) {
1007 return gensec_security->target.hostname;
1010 /* We could add use the 'set sockaddr' call, and do a reverse
1011 * lookup, but this would be both insecure (compromising the
1012 * way kerberos works) and add DNS timeouts */
1017 * Set (and talloc_reference) local and peer socket addresses onto a socket context on the GENSEC context
1019 * This is so that kerberos can include these addresses in
1020 * cryptographic tokens, to avoid certain attacks.
1023 NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, struct socket_address *my_addr)
1025 gensec_security->my_addr = my_addr;
1026 if (my_addr && !talloc_reference(gensec_security, my_addr)) {
1027 return NT_STATUS_NO_MEMORY;
1029 return NT_STATUS_OK;
1032 NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, struct socket_address *peer_addr)
1034 gensec_security->peer_addr = peer_addr;
1035 if (peer_addr && !talloc_reference(gensec_security, peer_addr)) {
1036 return NT_STATUS_NO_MEMORY;
1038 return NT_STATUS_OK;
1041 struct socket_address *gensec_get_my_addr(struct gensec_security *gensec_security)
1043 if (gensec_security->my_addr) {
1044 return gensec_security->my_addr;
1047 /* We could add a 'set sockaddr' call, and do a lookup. This
1048 * would avoid needing to do system calls if nothing asks. */
1052 struct socket_address *gensec_get_peer_addr(struct gensec_security *gensec_security)
1054 if (gensec_security->peer_addr) {
1055 return gensec_security->peer_addr;
1058 /* We could add a 'set sockaddr' call, and do a lookup. This
1059 * would avoid needing to do system calls if nothing asks.
1060 * However, this is not appropriate for the peer addres on
1061 * datagram sockets */
1068 * Set the target principal (assuming it it known, say from the SPNEGO reply)
1069 * - ensures it is talloc()ed
1073 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
1075 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1076 if (!gensec_security->target.principal) {
1077 return NT_STATUS_NO_MEMORY;
1079 return NT_STATUS_OK;
1082 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
1084 if (gensec_security->target.principal) {
1085 return gensec_security->target.principal;
1092 register a GENSEC backend.
1094 The 'name' can be later used by other backends to find the operations
1095 structure for this backend.
1097 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
1099 if (!lp_parm_bool(-1, "gensec", ops->name, ops->enabled)) {
1100 DEBUG(2,("gensec subsystem %s is disabled\n", ops->name));
1101 return NT_STATUS_OK;
1104 if (gensec_security_by_name(NULL, ops->name) != NULL) {
1105 /* its already registered! */
1106 DEBUG(0,("GENSEC backend '%s' already registered\n",
1108 return NT_STATUS_OBJECT_NAME_COLLISION;
1111 generic_security_ops = talloc_realloc(talloc_autofree_context(),
1112 generic_security_ops,
1113 struct gensec_security_ops *,
1114 gensec_num_backends+2);
1115 if (!generic_security_ops) {
1116 return NT_STATUS_NO_MEMORY;
1119 generic_security_ops[gensec_num_backends] = discard_const(ops);
1120 gensec_num_backends++;
1121 generic_security_ops[gensec_num_backends] = NULL;
1123 DEBUG(3,("GENSEC backend '%s' registered\n",
1126 return NT_STATUS_OK;
1130 return the GENSEC interface version, and the size of some critical types
1131 This can be used by backends to either detect compilation errors, or provide
1132 multiple implementations for different smbd compilation options in one module
1134 const struct gensec_critical_sizes *gensec_interface_version(void)
1136 static const struct gensec_critical_sizes critical_sizes = {
1137 GENSEC_INTERFACE_VERSION,
1138 sizeof(struct gensec_security_ops),
1139 sizeof(struct gensec_security),
1142 return &critical_sizes;
1146 initialise the GENSEC subsystem
1148 NTSTATUS gensec_init(void)
1150 static BOOL initialized = False;
1152 init_module_fn static_init[] = STATIC_gensec_MODULES;
1153 init_module_fn *shared_init;
1155 if (initialized) return NT_STATUS_OK;
1158 shared_init = load_samba_modules(NULL, "gensec");
1160 run_init_functions(static_init);
1161 run_init_functions(shared_init);
1163 talloc_free(shared_init);
1165 return NT_STATUS_OK;