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"
27 #include "smb_build.h"
29 /* the list of currently registered GENSEC backends */
30 static struct gensec_security_ops **generic_security_ops;
31 static int gensec_num_backends;
33 /* Return all the registered mechs. Don't modify the return pointer,
34 * but you may talloc_reference it if convient */
35 struct gensec_security_ops **gensec_security_all(void)
37 return generic_security_ops;
40 /* Sometimes we want to force only kerberos, sometimes we want to
41 * force it's avoidance. The old list could be either
42 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
43 * an existing list we have trimmed down) */
45 struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
46 struct gensec_security_ops **old_gensec_list,
47 enum credentials_use_kerberos use_kerberos)
49 struct gensec_security_ops **new_gensec_list;
50 int i, j, num_mechs_in;
52 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
53 talloc_reference(mem_ctx, old_gensec_list);
54 return old_gensec_list;
57 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
61 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
62 if (!new_gensec_list) {
67 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
69 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
70 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
71 new_gensec_list[j] = old_gensec_list[i];
76 switch (use_kerberos) {
77 case CRED_DONT_USE_KERBEROS:
78 if (old_gensec_list[i]->kerberos == False) {
79 new_gensec_list[j] = old_gensec_list[i];
83 case CRED_MUST_USE_KERBEROS:
84 if (old_gensec_list[i]->kerberos == True) {
85 new_gensec_list[j] = old_gensec_list[i];
89 case CRED_AUTO_USE_KERBEROS:
93 new_gensec_list[j] = NULL;
95 return new_gensec_list;
98 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
101 struct gensec_security_ops **backends;
102 backends = gensec_security_all();
103 if (!gensec_security) {
104 talloc_reference(mem_ctx, backends);
107 enum credentials_use_kerberos use_kerberos;
108 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
110 talloc_reference(mem_ctx, backends);
113 use_kerberos = cli_credentials_get_kerberos_state(creds);
114 return gensec_use_kerberos_mechs(mem_ctx, backends, use_kerberos);
118 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
122 struct gensec_security_ops **backends;
123 const struct gensec_security_ops *backend;
124 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
128 backends = gensec_security_mechs(gensec_security, mem_ctx);
129 for (i=0; backends && backends[i]; i++) {
130 if (backends[i]->auth_type == auth_type) {
131 backend = backends[i];
132 talloc_free(mem_ctx);
136 talloc_free(mem_ctx);
141 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
142 const char *oid_string)
145 struct gensec_security_ops **backends;
146 const struct gensec_security_ops *backend;
147 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
151 backends = gensec_security_mechs(gensec_security, mem_ctx);
152 for (i=0; backends && backends[i]; i++) {
153 if (backends[i]->oid) {
154 for (j=0; backends[i]->oid[j]; j++) {
155 if (backends[i]->oid[j] &&
156 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
157 backend = backends[i];
158 talloc_free(mem_ctx);
164 talloc_free(mem_ctx);
169 static const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
170 const char *sasl_name)
173 struct gensec_security_ops **backends;
174 const struct gensec_security_ops *backend;
175 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
179 backends = gensec_security_mechs(gensec_security, mem_ctx);
180 for (i=0; backends && backends[i]; i++) {
181 if (backends[i]->sasl_name
182 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
183 backend = backends[i];
184 talloc_free(mem_ctx);
188 talloc_free(mem_ctx);
193 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
197 struct gensec_security_ops **backends;
198 const struct gensec_security_ops *backend;
199 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
203 backends = gensec_security_mechs(gensec_security, mem_ctx);
204 for (i=0; backends && backends[i]; i++) {
205 if (backends[i]->name
206 && (strcmp(backends[i]->name, name) == 0)) {
207 backend = backends[i];
208 talloc_free(mem_ctx);
212 talloc_free(mem_ctx);
217 * Return a unique list of security subsystems from those specified in
218 * the list of SASL names.
220 * Use the list of enabled GENSEC mechanisms from the credentials
221 * attached to the gensec_security, and return in our preferred order.
224 const struct gensec_security_ops **gensec_security_by_sasl(struct gensec_security *gensec_security,
226 const char **sasl_names)
228 const struct gensec_security_ops **backends_out;
229 struct gensec_security_ops **backends;
231 int num_backends_out = 0;
237 backends = gensec_security_mechs(gensec_security, mem_ctx);
239 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
243 backends_out[0] = NULL;
245 /* Find backends in our preferred order, by walking our list,
246 * then looking in the supplied list */
247 for (i=0; backends && backends[i]; i++) {
248 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
249 if (!backends[i]->sasl_name ||
250 !(strcmp(backends[i]->sasl_name,
251 sasl_names[sasl_idx]) == 0)) {
255 for (k=0; backends_out[k]; k++) {
256 if (backends_out[k] == backends[i]) {
261 if (k < num_backends_out) {
262 /* already in there */
266 backends_out = talloc_realloc(mem_ctx, backends_out,
267 const struct gensec_security_ops *,
268 num_backends_out + 2);
273 backends_out[num_backends_out] = backends[i];
275 backends_out[num_backends_out] = NULL;
282 * Return a unique list of security subsystems from those specified in
283 * the OID list. That is, where two OIDs refer to the same module,
284 * return that module only once.
286 * Use the list of enabled GENSEC mechanisms from the credentials
287 * attached to the gensec_security, and return in our preferred order.
290 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
292 const char **oid_strings,
295 struct gensec_security_ops_wrapper *backends_out;
296 struct gensec_security_ops **backends;
297 int i, j, k, oid_idx;
298 int num_backends_out = 0;
304 backends = gensec_security_mechs(gensec_security, gensec_security);
306 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
310 backends_out[0].op = NULL;
311 backends_out[0].oid = NULL;
313 /* Find backends in our preferred order, by walking our list,
314 * then looking in the supplied list */
315 for (i=0; backends && backends[i]; i++) {
316 if (!backends[i]->oid) {
319 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
320 if (strcmp(oid_strings[oid_idx], skip) == 0) {
324 for (j=0; backends[i]->oid[j]; j++) {
325 if (!backends[i]->oid[j] ||
326 !(strcmp(backends[i]->oid[j],
327 oid_strings[oid_idx]) == 0)) {
331 for (k=0; backends_out[k].op; k++) {
332 if (backends_out[k].op == backends[i]) {
337 if (k < num_backends_out) {
338 /* already in there */
342 backends_out = talloc_realloc(mem_ctx, backends_out,
343 struct gensec_security_ops_wrapper,
344 num_backends_out + 2);
349 backends_out[num_backends_out].op = backends[i];
350 backends_out[num_backends_out].oid = backends[i]->oid[j];
352 backends_out[num_backends_out].op = NULL;
353 backends_out[num_backends_out].oid = NULL;
361 * Return OIDS from the security subsystems listed
364 const char **gensec_security_oids_from_ops(TALLOC_CTX *mem_ctx,
365 struct gensec_security_ops **ops,
371 const char **oid_list;
375 oid_list = talloc_array(mem_ctx, const char *, 1);
380 for (i=0; ops && ops[i]; i++) {
385 for (k = 0; ops[i]->oid[k]; k++) {
386 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
388 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
392 oid_list[j] = ops[i]->oid[k];
403 * Return OIDS from the security subsystems listed
406 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
407 const struct gensec_security_ops_wrapper *wops)
412 const char **oid_list;
416 oid_list = talloc_array(mem_ctx, const char *, 1);
421 for (i=0; wops[i].op; i++) {
422 if (!wops[i].op->oid) {
426 for (k = 0; wops[i].op->oid[k]; k++) {
427 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
431 oid_list[j] = wops[i].op->oid[k];
441 * Return all the security subsystems currently enabled on a GENSEC context.
443 * This is taken from a list attached to the cli_credentails, and
444 * skips the OID in 'skip'. (Typically the SPNEGO OID)
448 const char **gensec_security_oids(struct gensec_security *gensec_security,
452 struct gensec_security_ops **ops
453 = gensec_security_mechs(gensec_security, mem_ctx);
454 return gensec_security_oids_from_ops(mem_ctx, ops, skip);
460 Start the GENSEC system, returning a context pointer.
461 @param mem_ctx The parent TALLOC memory context.
462 @param gensec_security Returned GENSEC context pointer.
463 @note The mem_ctx is only a parent and may be NULL.
465 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
466 struct gensec_security **gensec_security,
467 struct event_context *ev)
469 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
470 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
472 (*gensec_security)->ops = NULL;
474 ZERO_STRUCT((*gensec_security)->target);
475 ZERO_STRUCT((*gensec_security)->peer_addr);
476 ZERO_STRUCT((*gensec_security)->my_addr);
478 (*gensec_security)->subcontext = False;
479 (*gensec_security)->want_features = 0;
482 ev = event_context_init(*gensec_security);
484 talloc_free(*gensec_security);
485 return NT_STATUS_NO_MEMORY;
489 (*gensec_security)->event_ctx = ev;
495 * Start a GENSEC subcontext, with a copy of the properties of the parent
496 * @param mem_ctx The parent TALLOC memory context.
497 * @param parent The parent GENSEC context
498 * @param gensec_security Returned GENSEC context pointer.
499 * @note Used by SPNEGO in particular, for the actual implementation mechanism
502 NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
503 struct gensec_security *parent,
504 struct gensec_security **gensec_security)
506 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
507 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
509 (**gensec_security) = *parent;
510 (*gensec_security)->ops = NULL;
511 (*gensec_security)->private_data = NULL;
513 (*gensec_security)->subcontext = True;
514 (*gensec_security)->event_ctx = parent->event_ctx;
520 Start the GENSEC system, in client mode, returning a context pointer.
521 @param mem_ctx The parent TALLOC memory context.
522 @param gensec_security Returned GENSEC context pointer.
523 @note The mem_ctx is only a parent and may be NULL.
525 NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
526 struct gensec_security **gensec_security,
527 struct event_context *ev)
530 status = gensec_start(mem_ctx, gensec_security, ev);
531 if (!NT_STATUS_IS_OK(status)) {
534 (*gensec_security)->gensec_role = GENSEC_CLIENT;
540 Start the GENSEC system, in server mode, returning a context pointer.
541 @param mem_ctx The parent TALLOC memory context.
542 @param gensec_security Returned GENSEC context pointer.
543 @note The mem_ctx is only a parent and may be NULL.
545 NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
546 struct gensec_security **gensec_security,
547 struct event_context *ev)
550 status = gensec_start(mem_ctx, gensec_security, ev);
551 if (!NT_STATUS_IS_OK(status)) {
554 (*gensec_security)->gensec_role = GENSEC_SERVER;
559 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
562 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
563 gensec_security->subcontext ? "sub" : "",
564 gensec_security->ops->name));
565 switch (gensec_security->gensec_role) {
567 if (gensec_security->ops->client_start) {
568 status = gensec_security->ops->client_start(gensec_security);
569 if (!NT_STATUS_IS_OK(status)) {
570 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
571 gensec_security->ops->name, nt_errstr(status)));
576 if (gensec_security->ops->server_start) {
577 status = gensec_security->ops->server_start(gensec_security);
578 if (!NT_STATUS_IS_OK(status)) {
579 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
580 gensec_security->ops->name, nt_errstr(status)));
585 return NT_STATUS_INVALID_PARAMETER;
589 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
590 * @param gensec_security GENSEC context pointer.
591 * @param auth_type DCERPC auth type
592 * @param auth_level DCERPC auth level
595 NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
596 uint8_t auth_type, uint8_t auth_level)
598 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
599 if (!gensec_security->ops) {
600 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
601 return NT_STATUS_INVALID_PARAMETER;
603 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
604 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
605 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
606 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
607 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
608 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
609 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
610 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
611 /* Default features */
613 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
615 return NT_STATUS_INVALID_PARAMETER;
618 return gensec_start_mech(gensec_security);
621 const char *gensec_get_name_by_authtype(uint8_t authtype)
623 const struct gensec_security_ops *ops;
624 ops = gensec_security_by_authtype(NULL, authtype);
632 const char *gensec_get_name_by_oid(const char *oid_string)
634 const struct gensec_security_ops *ops;
635 ops = gensec_security_by_oid(NULL, oid_string);
644 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
648 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
649 const struct gensec_security_ops *ops)
651 gensec_security->ops = ops;
652 return gensec_start_mech(gensec_security);
656 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
658 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
659 * well-known #define to hook it in.
662 NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
663 const char *mech_oid)
665 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
666 if (!gensec_security->ops) {
667 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
668 return NT_STATUS_INVALID_PARAMETER;
670 return gensec_start_mech(gensec_security);
674 * Start a GENSEC sub-mechanism by a well know SASL name
678 NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
679 const char *sasl_name)
681 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
682 if (!gensec_security->ops) {
683 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
684 return NT_STATUS_INVALID_PARAMETER;
686 return gensec_start_mech(gensec_security);
690 * Start a GENSEC sub-mechanism by an internal name
694 NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
697 gensec_security->ops = gensec_security_by_name(gensec_security, name);
698 if (!gensec_security->ops) {
699 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
700 return NT_STATUS_INVALID_PARAMETER;
702 return gensec_start_mech(gensec_security);
706 wrappers for the gensec function pointers
708 NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
710 uint8_t *data, size_t length,
711 const uint8_t *whole_pdu, size_t pdu_length,
712 const DATA_BLOB *sig)
714 if (!gensec_security->ops->unseal_packet) {
715 return NT_STATUS_NOT_IMPLEMENTED;
717 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
718 return NT_STATUS_INVALID_PARAMETER;
721 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
723 whole_pdu, pdu_length,
727 NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
729 const uint8_t *data, size_t length,
730 const uint8_t *whole_pdu, size_t pdu_length,
731 const DATA_BLOB *sig)
733 if (!gensec_security->ops->check_packet) {
734 return NT_STATUS_NOT_IMPLEMENTED;
736 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
737 return NT_STATUS_INVALID_PARAMETER;
740 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
743 NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
745 uint8_t *data, size_t length,
746 const uint8_t *whole_pdu, size_t pdu_length,
749 if (!gensec_security->ops->seal_packet) {
750 return NT_STATUS_NOT_IMPLEMENTED;
752 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
753 return NT_STATUS_INVALID_PARAMETER;
756 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
759 NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
761 const uint8_t *data, size_t length,
762 const uint8_t *whole_pdu, size_t pdu_length,
765 if (!gensec_security->ops->sign_packet) {
766 return NT_STATUS_NOT_IMPLEMENTED;
768 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
769 return NT_STATUS_INVALID_PARAMETER;
772 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
775 size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
777 if (!gensec_security->ops->sig_size) {
780 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
784 return gensec_security->ops->sig_size(gensec_security, data_size);
787 NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
792 if (!gensec_security->ops->wrap) {
793 return NT_STATUS_NOT_IMPLEMENTED;
795 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
798 NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
803 if (!gensec_security->ops->unwrap) {
804 return NT_STATUS_NOT_IMPLEMENTED;
806 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
809 NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
810 DATA_BLOB *session_key)
812 if (!gensec_security->ops->session_key) {
813 return NT_STATUS_NOT_IMPLEMENTED;
815 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
816 return NT_STATUS_NO_USER_SESSION_KEY;
819 return gensec_security->ops->session_key(gensec_security, session_key);
823 * Return the credentials of a logged on user, including session keys
826 * Only valid after a successful authentication
828 * May only be called once per authentication.
832 NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
833 struct auth_session_info **session_info)
835 if (!gensec_security->ops->session_info) {
836 return NT_STATUS_NOT_IMPLEMENTED;
838 return gensec_security->ops->session_info(gensec_security, session_info);
842 * Next state function for the GENSEC state machine
844 * @param gensec_security GENSEC State
845 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
846 * @param in The request, as a DATA_BLOB
847 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
848 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
849 * or NT_STATUS_OK if the user is authenticated.
852 NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
853 const DATA_BLOB in, DATA_BLOB *out)
855 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
859 * Set the requirement for a certain feature on the connection
863 void gensec_want_feature(struct gensec_security *gensec_security,
866 gensec_security->want_features |= feature;
870 * Check the requirement for a certain feature on the connection
874 BOOL gensec_have_feature(struct gensec_security *gensec_security,
877 if (!gensec_security->ops->have_feature) {
881 /* Can only 'have' a feature if you already 'want'ed it */
882 if (gensec_security->want_features & feature) {
883 return gensec_security->ops->have_feature(gensec_security, feature);
889 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
893 NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
895 gensec_security->credentials = talloc_reference(gensec_security, credentials);
900 * Return the credentials structure associated with a GENSEC context
904 struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
906 if (!gensec_security) {
909 return gensec_security->credentials;
913 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
917 NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
919 gensec_security->target.service = talloc_strdup(gensec_security, service);
920 if (!gensec_security->target.service) {
921 return NT_STATUS_NO_MEMORY;
926 const char *gensec_get_target_service(struct gensec_security *gensec_security)
928 if (gensec_security->target.service) {
929 return gensec_security->target.service;
936 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
940 NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
942 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
943 if (!gensec_security->target.hostname) {
944 return NT_STATUS_NO_MEMORY;
949 const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
951 if (gensec_security->target.hostname) {
952 return gensec_security->target.hostname;
955 /* We could add use the 'set sockaddr' call, and do a reverse
956 * lookup, but this would be both insecure (compromising the
957 * way kerberos works) and add DNS timeouts */
962 * Set (and talloc_reference) local and peer socket addresses onto a socket context on the GENSEC context
964 * This is so that kerberos can include these addresses in
965 * cryptographic tokens, to avoid certain attacks.
968 NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, struct socket_address *my_addr)
970 gensec_security->my_addr = my_addr;
971 if (my_addr && !talloc_reference(gensec_security, my_addr)) {
972 return NT_STATUS_NO_MEMORY;
977 NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, struct socket_address *peer_addr)
979 gensec_security->peer_addr = peer_addr;
980 if (peer_addr && !talloc_reference(gensec_security, peer_addr)) {
981 return NT_STATUS_NO_MEMORY;
986 struct socket_address *gensec_get_my_addr(struct gensec_security *gensec_security)
988 if (gensec_security->my_addr) {
989 return gensec_security->my_addr;
992 /* We could add a 'set sockaddr' call, and do a lookup. This
993 * would avoid needing to do system calls if nothing asks. */
997 struct socket_address *gensec_get_peer_addr(struct gensec_security *gensec_security)
999 if (gensec_security->peer_addr) {
1000 return gensec_security->peer_addr;
1003 /* We could add a 'set sockaddr' call, and do a lookup. This
1004 * would avoid needing to do system calls if nothing asks.
1005 * However, this is not appropriate for the peer addres on
1006 * datagram sockets */
1013 * Set the target principal (assuming it it known, say from the SPNEGO reply)
1014 * - ensures it is talloc()ed
1018 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
1020 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1021 if (!gensec_security->target.principal) {
1022 return NT_STATUS_NO_MEMORY;
1024 return NT_STATUS_OK;
1027 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
1029 if (gensec_security->target.principal) {
1030 return gensec_security->target.principal;
1037 register a GENSEC backend.
1039 The 'name' can be later used by other backends to find the operations
1040 structure for this backend.
1042 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
1044 if (!lp_parm_bool(-1, "gensec", ops->name, ops->enabled)) {
1045 DEBUG(2,("gensec subsystem %s is disabled\n", ops->name));
1046 return NT_STATUS_OK;
1049 if (gensec_security_by_name(NULL, ops->name) != NULL) {
1050 /* its already registered! */
1051 DEBUG(0,("GENSEC backend '%s' already registered\n",
1053 return NT_STATUS_OBJECT_NAME_COLLISION;
1056 generic_security_ops = talloc_realloc(talloc_autofree_context(),
1057 generic_security_ops,
1058 struct gensec_security_ops *,
1059 gensec_num_backends+2);
1060 if (!generic_security_ops) {
1061 smb_panic("out of memory (or failed to realloc referenced memory) in gensec_register");
1064 generic_security_ops[gensec_num_backends] = ops;
1065 gensec_num_backends++;
1066 generic_security_ops[gensec_num_backends] = NULL;
1068 DEBUG(3,("GENSEC backend '%s' registered\n",
1071 return NT_STATUS_OK;
1075 return the GENSEC interface version, and the size of some critical types
1076 This can be used by backends to either detect compilation errors, or provide
1077 multiple implementations for different smbd compilation options in one module
1079 const struct gensec_critical_sizes *gensec_interface_version(void)
1081 static const struct gensec_critical_sizes critical_sizes = {
1082 GENSEC_INTERFACE_VERSION,
1083 sizeof(struct gensec_security_ops),
1084 sizeof(struct gensec_security),
1087 return &critical_sizes;
1091 initialise the GENSEC subsystem
1093 NTSTATUS gensec_init(void)
1095 static BOOL initialized = False;
1097 init_module_fn static_init[] = STATIC_GENSEC_MODULES;
1098 init_module_fn *shared_init = load_samba_modules(NULL, "gensec");
1100 if (initialized) return NT_STATUS_OK;
1103 run_init_functions(static_init);
1104 run_init_functions(shared_init);
1106 talloc_free(shared_init);
1108 return NT_STATUS_OK;