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 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
108 enum credentials_use_kerberos use_kerberos
109 = cli_credentials_get_kerberos_state(creds);
110 return gensec_use_kerberos_mechs(mem_ctx, backends, use_kerberos);
115 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
119 struct gensec_security_ops **backends;
120 const struct gensec_security_ops *backend;
121 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
125 backends = gensec_security_mechs(gensec_security, mem_ctx);
126 for (i=0; backends && backends[i]; i++) {
127 if (backends[i]->auth_type == auth_type) {
128 backend = backends[i];
129 talloc_free(mem_ctx);
133 talloc_free(mem_ctx);
138 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
139 const char *oid_string)
142 struct gensec_security_ops **backends;
143 const struct gensec_security_ops *backend;
144 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
148 backends = gensec_security_mechs(gensec_security, mem_ctx);
149 for (i=0; backends && backends[i]; i++) {
150 if (backends[i]->oid) {
151 for (j=0; backends[i]->oid[j]; j++) {
152 if (backends[i]->oid[j] &&
153 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
154 backend = backends[i];
155 talloc_free(mem_ctx);
161 talloc_free(mem_ctx);
166 static const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
167 const char *sasl_name)
170 struct gensec_security_ops **backends;
171 const struct gensec_security_ops *backend;
172 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
176 backends = gensec_security_mechs(gensec_security, mem_ctx);
177 for (i=0; backends && backends[i]; i++) {
178 if (backends[i]->sasl_name
179 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
180 backend = backends[i];
181 talloc_free(mem_ctx);
185 talloc_free(mem_ctx);
190 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
194 struct gensec_security_ops **backends;
195 const struct gensec_security_ops *backend;
196 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
200 backends = gensec_security_mechs(gensec_security, mem_ctx);
201 for (i=0; backends && backends[i]; i++) {
202 if (backends[i]->name
203 && (strcmp(backends[i]->name, name) == 0)) {
204 backend = backends[i];
205 talloc_free(mem_ctx);
209 talloc_free(mem_ctx);
214 * Return a unique list of security subsystems from those specified in
215 * the list of SASL names.
217 * Use the list of enabled GENSEC mechanisms from the credentials
218 * attached to the gensec_security, and return in our preferred order.
221 const struct gensec_security_ops **gensec_security_by_sasl(struct gensec_security *gensec_security,
223 const char **sasl_names)
225 const struct gensec_security_ops **backends_out;
226 struct gensec_security_ops **backends;
228 int num_backends_out = 0;
234 backends = gensec_security_mechs(gensec_security, mem_ctx);
236 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
240 backends_out[0] = NULL;
242 /* Find backends in our preferred order, by walking our list,
243 * then looking in the supplied list */
244 for (i=0; backends && backends[i]; i++) {
245 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
246 if (!backends[i]->sasl_name ||
247 !(strcmp(backends[i]->sasl_name,
248 sasl_names[sasl_idx]) == 0)) {
252 for (k=0; backends_out[k]; k++) {
253 if (backends_out[k] == backends[i]) {
258 if (k < num_backends_out) {
259 /* already in there */
263 backends_out = talloc_realloc(mem_ctx, backends_out,
264 const struct gensec_security_ops *,
265 num_backends_out + 2);
270 backends_out[num_backends_out] = backends[i];
272 backends_out[num_backends_out] = NULL;
279 * Return a unique list of security subsystems from those specified in
280 * the OID list. That is, where two OIDs refer to the same module,
281 * return that module only once.
283 * Use the list of enabled GENSEC mechanisms from the credentials
284 * attached to the gensec_security, and return in our preferred order.
287 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
289 const char **oid_strings,
292 struct gensec_security_ops_wrapper *backends_out;
293 struct gensec_security_ops **backends;
294 int i, j, k, oid_idx;
295 int num_backends_out = 0;
301 backends = gensec_security_mechs(gensec_security, gensec_security);
303 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
307 backends_out[0].op = NULL;
308 backends_out[0].oid = NULL;
310 /* Find backends in our preferred order, by walking our list,
311 * then looking in the supplied list */
312 for (i=0; backends && backends[i]; i++) {
313 if (!backends[i]->oid) {
316 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
317 if (strcmp(oid_strings[oid_idx], skip) == 0) {
321 for (j=0; backends[i]->oid[j]; j++) {
322 if (!backends[i]->oid[j] ||
323 !(strcmp(backends[i]->oid[j],
324 oid_strings[oid_idx]) == 0)) {
328 for (k=0; backends_out[k].op; k++) {
329 if (backends_out[k].op == backends[i]) {
334 if (k < num_backends_out) {
335 /* already in there */
339 backends_out = talloc_realloc(mem_ctx, backends_out,
340 struct gensec_security_ops_wrapper,
341 num_backends_out + 2);
346 backends_out[num_backends_out].op = backends[i];
347 backends_out[num_backends_out].oid = backends[i]->oid[j];
349 backends_out[num_backends_out].op = NULL;
350 backends_out[num_backends_out].oid = NULL;
358 * Return OIDS from the security subsystems listed
361 const char **gensec_security_oids_from_ops(TALLOC_CTX *mem_ctx,
362 struct gensec_security_ops **ops,
368 const char **oid_list;
372 oid_list = talloc_array(mem_ctx, const char *, 1);
377 for (i=0; ops && ops[i]; i++) {
382 for (k = 0; ops[i]->oid[k]; k++) {
383 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
385 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
389 oid_list[j] = ops[i]->oid[k];
400 * Return OIDS from the security subsystems listed
403 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
404 const struct gensec_security_ops_wrapper *wops)
409 const char **oid_list;
413 oid_list = talloc_array(mem_ctx, const char *, 1);
418 for (i=0; wops[i].op; i++) {
419 if (!wops[i].op->oid) {
423 for (k = 0; wops[i].op->oid[k]; k++) {
424 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
428 oid_list[j] = wops[i].op->oid[k];
438 * Return all the security subsystems currently enabled on a GENSEC context.
440 * This is taken from a list attached to the cli_credentails, and
441 * skips the OID in 'skip'. (Typically the SPNEGO OID)
445 const char **gensec_security_oids(struct gensec_security *gensec_security,
449 struct gensec_security_ops **ops
450 = gensec_security_mechs(gensec_security, mem_ctx);
451 return gensec_security_oids_from_ops(mem_ctx, ops, skip);
457 Start the GENSEC system, returning a context pointer.
458 @param mem_ctx The parent TALLOC memory context.
459 @param gensec_security Returned GENSEC context pointer.
460 @note The mem_ctx is only a parent and may be NULL.
462 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
463 struct gensec_security **gensec_security,
464 struct event_context *ev)
466 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
467 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
469 (*gensec_security)->ops = NULL;
471 ZERO_STRUCT((*gensec_security)->target);
472 ZERO_STRUCT((*gensec_security)->peer_addr);
473 ZERO_STRUCT((*gensec_security)->my_addr);
475 (*gensec_security)->subcontext = False;
476 (*gensec_security)->want_features = 0;
479 ev = event_context_init(*gensec_security);
481 talloc_free(*gensec_security);
482 return NT_STATUS_NO_MEMORY;
486 (*gensec_security)->event_ctx = ev;
492 * Start a GENSEC subcontext, with a copy of the properties of the parent
493 * @param mem_ctx The parent TALLOC memory context.
494 * @param parent The parent GENSEC context
495 * @param gensec_security Returned GENSEC context pointer.
496 * @note Used by SPNEGO in particular, for the actual implementation mechanism
499 NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
500 struct gensec_security *parent,
501 struct gensec_security **gensec_security)
503 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
504 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
506 (**gensec_security) = *parent;
507 (*gensec_security)->ops = NULL;
508 (*gensec_security)->private_data = NULL;
510 (*gensec_security)->subcontext = True;
511 (*gensec_security)->event_ctx = parent->event_ctx;
517 Start the GENSEC system, in client mode, returning a context pointer.
518 @param mem_ctx The parent TALLOC memory context.
519 @param gensec_security Returned GENSEC context pointer.
520 @note The mem_ctx is only a parent and may be NULL.
522 NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
523 struct gensec_security **gensec_security,
524 struct event_context *ev)
527 status = gensec_start(mem_ctx, gensec_security, ev);
528 if (!NT_STATUS_IS_OK(status)) {
531 (*gensec_security)->gensec_role = GENSEC_CLIENT;
537 Start the GENSEC system, in server mode, returning a context pointer.
538 @param mem_ctx The parent TALLOC memory context.
539 @param gensec_security Returned GENSEC context pointer.
540 @note The mem_ctx is only a parent and may be NULL.
542 NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
543 struct gensec_security **gensec_security,
544 struct event_context *ev)
547 status = gensec_start(mem_ctx, gensec_security, ev);
548 if (!NT_STATUS_IS_OK(status)) {
551 (*gensec_security)->gensec_role = GENSEC_SERVER;
556 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
559 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
560 gensec_security->subcontext ? "sub" : "",
561 gensec_security->ops->name));
562 switch (gensec_security->gensec_role) {
564 if (gensec_security->ops->client_start) {
565 status = gensec_security->ops->client_start(gensec_security);
566 if (!NT_STATUS_IS_OK(status)) {
567 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
568 gensec_security->ops->name, nt_errstr(status)));
573 if (gensec_security->ops->server_start) {
574 status = gensec_security->ops->server_start(gensec_security);
575 if (!NT_STATUS_IS_OK(status)) {
576 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
577 gensec_security->ops->name, nt_errstr(status)));
582 return NT_STATUS_INVALID_PARAMETER;
586 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
587 * @param gensec_security GENSEC context pointer.
588 * @param auth_type DCERPC auth type
589 * @param auth_level DCERPC auth level
592 NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
593 uint8_t auth_type, uint8_t auth_level)
595 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
596 if (!gensec_security->ops) {
597 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
598 return NT_STATUS_INVALID_PARAMETER;
600 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
601 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
602 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
603 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
604 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
605 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
606 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
607 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
608 /* Default features */
610 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
612 return NT_STATUS_INVALID_PARAMETER;
615 return gensec_start_mech(gensec_security);
618 const char *gensec_get_name_by_authtype(uint8_t authtype)
620 const struct gensec_security_ops *ops;
621 ops = gensec_security_by_authtype(NULL, authtype);
629 const char *gensec_get_name_by_oid(const char *oid_string)
631 const struct gensec_security_ops *ops;
632 ops = gensec_security_by_oid(NULL, oid_string);
641 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
645 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
646 const struct gensec_security_ops *ops)
648 gensec_security->ops = ops;
649 return gensec_start_mech(gensec_security);
653 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
655 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
656 * well-known #define to hook it in.
659 NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
660 const char *mech_oid)
662 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
663 if (!gensec_security->ops) {
664 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
665 return NT_STATUS_INVALID_PARAMETER;
667 return gensec_start_mech(gensec_security);
671 * Start a GENSEC sub-mechanism by a well know SASL name
675 NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
676 const char *sasl_name)
678 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
679 if (!gensec_security->ops) {
680 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
681 return NT_STATUS_INVALID_PARAMETER;
683 return gensec_start_mech(gensec_security);
687 * Start a GENSEC sub-mechanism by an internal name
691 NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
694 gensec_security->ops = gensec_security_by_name(gensec_security, name);
695 if (!gensec_security->ops) {
696 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
697 return NT_STATUS_INVALID_PARAMETER;
699 return gensec_start_mech(gensec_security);
703 wrappers for the gensec function pointers
705 NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
707 uint8_t *data, size_t length,
708 const uint8_t *whole_pdu, size_t pdu_length,
709 const DATA_BLOB *sig)
711 if (!gensec_security->ops->unseal_packet) {
712 return NT_STATUS_NOT_IMPLEMENTED;
714 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
715 return NT_STATUS_INVALID_PARAMETER;
718 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
720 whole_pdu, pdu_length,
724 NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
726 const uint8_t *data, size_t length,
727 const uint8_t *whole_pdu, size_t pdu_length,
728 const DATA_BLOB *sig)
730 if (!gensec_security->ops->check_packet) {
731 return NT_STATUS_NOT_IMPLEMENTED;
733 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
734 return NT_STATUS_INVALID_PARAMETER;
737 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
740 NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
742 uint8_t *data, size_t length,
743 const uint8_t *whole_pdu, size_t pdu_length,
746 if (!gensec_security->ops->seal_packet) {
747 return NT_STATUS_NOT_IMPLEMENTED;
749 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
750 return NT_STATUS_INVALID_PARAMETER;
753 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
756 NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
758 const uint8_t *data, size_t length,
759 const uint8_t *whole_pdu, size_t pdu_length,
762 if (!gensec_security->ops->sign_packet) {
763 return NT_STATUS_NOT_IMPLEMENTED;
765 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
766 return NT_STATUS_INVALID_PARAMETER;
769 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
772 size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
774 if (!gensec_security->ops->sig_size) {
777 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
781 return gensec_security->ops->sig_size(gensec_security, data_size);
784 NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
789 if (!gensec_security->ops->wrap) {
790 return NT_STATUS_NOT_IMPLEMENTED;
792 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
795 NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
800 if (!gensec_security->ops->unwrap) {
801 return NT_STATUS_NOT_IMPLEMENTED;
803 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
806 NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
807 DATA_BLOB *session_key)
809 if (!gensec_security->ops->session_key) {
810 return NT_STATUS_NOT_IMPLEMENTED;
812 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
813 return NT_STATUS_NO_USER_SESSION_KEY;
816 return gensec_security->ops->session_key(gensec_security, session_key);
820 * Return the credentials of a logged on user, including session keys
823 * Only valid after a successful authentication
825 * May only be called once per authentication.
829 NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
830 struct auth_session_info **session_info)
832 if (!gensec_security->ops->session_info) {
833 return NT_STATUS_NOT_IMPLEMENTED;
835 return gensec_security->ops->session_info(gensec_security, session_info);
839 * Next state function for the GENSEC state machine
841 * @param gensec_security GENSEC State
842 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
843 * @param in The request, as a DATA_BLOB
844 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
845 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
846 * or NT_STATUS_OK if the user is authenticated.
849 NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
850 const DATA_BLOB in, DATA_BLOB *out)
852 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
856 * Set the requirement for a certain feature on the connection
860 void gensec_want_feature(struct gensec_security *gensec_security,
863 gensec_security->want_features |= feature;
867 * Check the requirement for a certain feature on the connection
871 BOOL gensec_have_feature(struct gensec_security *gensec_security,
874 if (!gensec_security->ops->have_feature) {
878 /* Can only 'have' a feature if you already 'want'ed it */
879 if (gensec_security->want_features & feature) {
880 return gensec_security->ops->have_feature(gensec_security, feature);
886 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
890 NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
892 gensec_security->credentials = talloc_reference(gensec_security, credentials);
897 * Return the credentials structure associated with a GENSEC context
901 struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
903 if (!gensec_security) {
906 return gensec_security->credentials;
910 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
914 NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
916 gensec_security->target.service = talloc_strdup(gensec_security, service);
917 if (!gensec_security->target.service) {
918 return NT_STATUS_NO_MEMORY;
923 const char *gensec_get_target_service(struct gensec_security *gensec_security)
925 if (gensec_security->target.service) {
926 return gensec_security->target.service;
933 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
937 NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
939 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
940 if (!gensec_security->target.hostname) {
941 return NT_STATUS_NO_MEMORY;
946 const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
948 if (gensec_security->target.hostname) {
949 return gensec_security->target.hostname;
952 /* We could add use the 'set sockaddr' call, and do a reverse
953 * lookup, but this would be both insecure (compromising the
954 * way kerberos works) and add DNS timeouts */
959 * Set (and talloc_reference) local and peer socket addresses onto a socket context on the GENSEC context
961 * This is so that kerberos can include these addresses in
962 * cryptographic tokens, to avoid certain attacks.
965 NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, struct socket_address *my_addr)
967 gensec_security->my_addr = my_addr;
968 if (my_addr && !talloc_reference(gensec_security, my_addr)) {
969 return NT_STATUS_NO_MEMORY;
974 NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, struct socket_address *peer_addr)
976 gensec_security->peer_addr = peer_addr;
977 if (peer_addr && !talloc_reference(gensec_security, peer_addr)) {
978 return NT_STATUS_NO_MEMORY;
983 struct socket_address *gensec_get_my_addr(struct gensec_security *gensec_security)
985 if (gensec_security->my_addr) {
986 return gensec_security->my_addr;
989 /* We could add a 'set sockaddr' call, and do a lookup. This
990 * would avoid needing to do system calls if nothing asks. */
994 struct socket_address *gensec_get_peer_addr(struct gensec_security *gensec_security)
996 if (gensec_security->peer_addr) {
997 return gensec_security->peer_addr;
1000 /* We could add a 'set sockaddr' call, and do a lookup. This
1001 * would avoid needing to do system calls if nothing asks.
1002 * However, this is not appropriate for the peer addres on
1003 * datagram sockets */
1010 * Set the target principal (assuming it it known, say from the SPNEGO reply)
1011 * - ensures it is talloc()ed
1015 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
1017 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1018 if (!gensec_security->target.principal) {
1019 return NT_STATUS_NO_MEMORY;
1021 return NT_STATUS_OK;
1024 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
1026 if (gensec_security->target.principal) {
1027 return gensec_security->target.principal;
1034 register a GENSEC backend.
1036 The 'name' can be later used by other backends to find the operations
1037 structure for this backend.
1039 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
1041 if (!lp_parm_bool(-1, "gensec", ops->name, ops->enabled)) {
1042 DEBUG(2,("gensec subsystem %s is disabled\n", ops->name));
1043 return NT_STATUS_OK;
1046 if (gensec_security_by_name(NULL, ops->name) != NULL) {
1047 /* its already registered! */
1048 DEBUG(0,("GENSEC backend '%s' already registered\n",
1050 return NT_STATUS_OBJECT_NAME_COLLISION;
1053 generic_security_ops = talloc_realloc(talloc_autofree_context(),
1054 generic_security_ops,
1055 struct gensec_security_ops *,
1056 gensec_num_backends+2);
1057 if (!generic_security_ops) {
1058 smb_panic("out of memory (or failed to realloc referenced memory) in gensec_register");
1061 generic_security_ops[gensec_num_backends] = ops;
1062 gensec_num_backends++;
1063 generic_security_ops[gensec_num_backends] = NULL;
1065 DEBUG(3,("GENSEC backend '%s' registered\n",
1068 return NT_STATUS_OK;
1072 return the GENSEC interface version, and the size of some critical types
1073 This can be used by backends to either detect compilation errors, or provide
1074 multiple implementations for different smbd compilation options in one module
1076 const struct gensec_critical_sizes *gensec_interface_version(void)
1078 static const struct gensec_critical_sizes critical_sizes = {
1079 GENSEC_INTERFACE_VERSION,
1080 sizeof(struct gensec_security_ops),
1081 sizeof(struct gensec_security),
1084 return &critical_sizes;
1088 initialise the GENSEC subsystem
1090 NTSTATUS gensec_init(void)
1092 static BOOL initialized = False;
1094 init_module_fn static_init[] = STATIC_GENSEC_MODULES;
1095 init_module_fn *shared_init = load_samba_modules(NULL, "gensec");
1097 if (initialized) return NT_STATUS_OK;
1100 run_init_functions(static_init);
1101 run_init_functions(shared_init);
1103 talloc_free(shared_init);
1105 return NT_STATUS_OK;