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"
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_list(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 _PUBLIC_ 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 _PUBLIC_ 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)));
577 if (gensec_security->ops->server_start) {
578 status = gensec_security->ops->server_start(gensec_security);
579 if (!NT_STATUS_IS_OK(status)) {
580 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
581 gensec_security->ops->name, nt_errstr(status)));
587 return NT_STATUS_INVALID_PARAMETER;
591 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
592 * @param gensec_security GENSEC context pointer.
593 * @param auth_type DCERPC auth type
594 * @param auth_level DCERPC auth level
597 NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
598 uint8_t auth_type, uint8_t auth_level)
600 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
601 if (!gensec_security->ops) {
602 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
603 return NT_STATUS_INVALID_PARAMETER;
605 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
606 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
607 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
608 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
609 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
610 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
611 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
612 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
613 /* Default features */
615 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
617 return NT_STATUS_INVALID_PARAMETER;
620 return gensec_start_mech(gensec_security);
623 const char *gensec_get_name_by_authtype(uint8_t authtype)
625 const struct gensec_security_ops *ops;
626 ops = gensec_security_by_authtype(NULL, authtype);
634 const char *gensec_get_name_by_oid(const char *oid_string)
636 const struct gensec_security_ops *ops;
637 ops = gensec_security_by_oid(NULL, oid_string);
646 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
650 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
651 const struct gensec_security_ops *ops)
653 gensec_security->ops = ops;
654 return gensec_start_mech(gensec_security);
658 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
660 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
661 * well-known #define to hook it in.
664 NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
665 const char *mech_oid)
667 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
668 if (!gensec_security->ops) {
669 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
670 return NT_STATUS_INVALID_PARAMETER;
672 return gensec_start_mech(gensec_security);
676 * Start a GENSEC sub-mechanism by a well know SASL name
680 NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
681 const char *sasl_name)
683 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
684 if (!gensec_security->ops) {
685 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
686 return NT_STATUS_INVALID_PARAMETER;
688 return gensec_start_mech(gensec_security);
692 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
696 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
697 const char **sasl_names)
700 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
701 const struct gensec_security_ops **ops;
703 return NT_STATUS_NO_MEMORY;
705 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
707 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
708 str_list_join(mem_ctx,
710 talloc_free(mem_ctx);
711 return NT_STATUS_INVALID_PARAMETER;
713 nt_status = gensec_start_mech_by_ops(gensec_security, ops[0]);
714 talloc_free(mem_ctx);
719 * Start a GENSEC sub-mechanism by an internal name
723 NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
726 gensec_security->ops = gensec_security_by_name(gensec_security, name);
727 if (!gensec_security->ops) {
728 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
729 return NT_STATUS_INVALID_PARAMETER;
731 return gensec_start_mech(gensec_security);
735 wrappers for the gensec function pointers
737 NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
739 uint8_t *data, size_t length,
740 const uint8_t *whole_pdu, size_t pdu_length,
741 const DATA_BLOB *sig)
743 if (!gensec_security->ops->unseal_packet) {
744 return NT_STATUS_NOT_IMPLEMENTED;
746 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
747 return NT_STATUS_INVALID_PARAMETER;
750 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
752 whole_pdu, pdu_length,
756 NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
758 const uint8_t *data, size_t length,
759 const uint8_t *whole_pdu, size_t pdu_length,
760 const DATA_BLOB *sig)
762 if (!gensec_security->ops->check_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->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
772 NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
774 uint8_t *data, size_t length,
775 const uint8_t *whole_pdu, size_t pdu_length,
778 if (!gensec_security->ops->seal_packet) {
779 return NT_STATUS_NOT_IMPLEMENTED;
781 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
782 return NT_STATUS_INVALID_PARAMETER;
785 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
788 NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
790 const uint8_t *data, size_t length,
791 const uint8_t *whole_pdu, size_t pdu_length,
794 if (!gensec_security->ops->sign_packet) {
795 return NT_STATUS_NOT_IMPLEMENTED;
797 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
798 return NT_STATUS_INVALID_PARAMETER;
801 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
804 size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
806 if (!gensec_security->ops->sig_size) {
809 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
813 return gensec_security->ops->sig_size(gensec_security, data_size);
816 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
821 if (!gensec_security->ops->wrap) {
822 return NT_STATUS_NOT_IMPLEMENTED;
824 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
827 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
832 if (!gensec_security->ops->unwrap) {
833 return NT_STATUS_NOT_IMPLEMENTED;
835 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
838 NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
839 DATA_BLOB *session_key)
841 if (!gensec_security->ops->session_key) {
842 return NT_STATUS_NOT_IMPLEMENTED;
844 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
845 return NT_STATUS_NO_USER_SESSION_KEY;
848 return gensec_security->ops->session_key(gensec_security, session_key);
852 * Return the credentials of a logged on user, including session keys
855 * Only valid after a successful authentication
857 * May only be called once per authentication.
861 NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
862 struct auth_session_info **session_info)
864 if (!gensec_security->ops->session_info) {
865 return NT_STATUS_NOT_IMPLEMENTED;
867 return gensec_security->ops->session_info(gensec_security, session_info);
871 * Next state function for the GENSEC state machine
873 * @param gensec_security GENSEC State
874 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
875 * @param in The request, as a DATA_BLOB
876 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
877 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
878 * or NT_STATUS_OK if the user is authenticated.
881 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
882 const DATA_BLOB in, DATA_BLOB *out)
884 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
888 * Set the requirement for a certain feature on the connection
892 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
895 gensec_security->want_features |= feature;
899 * Check the requirement for a certain feature on the connection
903 _PUBLIC_ BOOL gensec_have_feature(struct gensec_security *gensec_security,
906 if (!gensec_security->ops->have_feature) {
910 /* Can only 'have' a feature if you already 'want'ed it */
911 if (gensec_security->want_features & feature) {
912 return gensec_security->ops->have_feature(gensec_security, feature);
918 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
922 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
924 gensec_security->credentials = talloc_reference(gensec_security, credentials);
929 * Return the credentials structure associated with a GENSEC context
933 struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
935 if (!gensec_security) {
938 return gensec_security->credentials;
942 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
946 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
948 gensec_security->target.service = talloc_strdup(gensec_security, service);
949 if (!gensec_security->target.service) {
950 return NT_STATUS_NO_MEMORY;
955 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security)
957 if (gensec_security->target.service) {
958 return gensec_security->target.service;
965 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
969 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
971 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
972 if (!gensec_security->target.hostname) {
973 return NT_STATUS_NO_MEMORY;
978 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
980 if (gensec_security->target.hostname) {
981 return gensec_security->target.hostname;
984 /* We could add use the 'set sockaddr' call, and do a reverse
985 * lookup, but this would be both insecure (compromising the
986 * way kerberos works) and add DNS timeouts */
991 * Set (and talloc_reference) local and peer socket addresses onto a socket context on the GENSEC context
993 * This is so that kerberos can include these addresses in
994 * cryptographic tokens, to avoid certain attacks.
997 NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, struct socket_address *my_addr)
999 gensec_security->my_addr = my_addr;
1000 if (my_addr && !talloc_reference(gensec_security, my_addr)) {
1001 return NT_STATUS_NO_MEMORY;
1003 return NT_STATUS_OK;
1006 NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, struct socket_address *peer_addr)
1008 gensec_security->peer_addr = peer_addr;
1009 if (peer_addr && !talloc_reference(gensec_security, peer_addr)) {
1010 return NT_STATUS_NO_MEMORY;
1012 return NT_STATUS_OK;
1015 struct socket_address *gensec_get_my_addr(struct gensec_security *gensec_security)
1017 if (gensec_security->my_addr) {
1018 return gensec_security->my_addr;
1021 /* We could add a 'set sockaddr' call, and do a lookup. This
1022 * would avoid needing to do system calls if nothing asks. */
1026 struct socket_address *gensec_get_peer_addr(struct gensec_security *gensec_security)
1028 if (gensec_security->peer_addr) {
1029 return gensec_security->peer_addr;
1032 /* We could add a 'set sockaddr' call, and do a lookup. This
1033 * would avoid needing to do system calls if nothing asks.
1034 * However, this is not appropriate for the peer addres on
1035 * datagram sockets */
1042 * Set the target principal (assuming it it known, say from the SPNEGO reply)
1043 * - ensures it is talloc()ed
1047 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
1049 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1050 if (!gensec_security->target.principal) {
1051 return NT_STATUS_NO_MEMORY;
1053 return NT_STATUS_OK;
1056 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
1058 if (gensec_security->target.principal) {
1059 return gensec_security->target.principal;
1066 register a GENSEC backend.
1068 The 'name' can be later used by other backends to find the operations
1069 structure for this backend.
1071 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
1073 if (!lp_parm_bool(-1, "gensec", ops->name, ops->enabled)) {
1074 DEBUG(2,("gensec subsystem %s is disabled\n", ops->name));
1075 return NT_STATUS_OK;
1078 if (gensec_security_by_name(NULL, ops->name) != NULL) {
1079 /* its already registered! */
1080 DEBUG(0,("GENSEC backend '%s' already registered\n",
1082 return NT_STATUS_OBJECT_NAME_COLLISION;
1085 generic_security_ops = talloc_realloc(talloc_autofree_context(),
1086 generic_security_ops,
1087 struct gensec_security_ops *,
1088 gensec_num_backends+2);
1089 if (!generic_security_ops) {
1090 smb_panic("out of memory (or failed to realloc referenced memory) in gensec_register");
1093 generic_security_ops[gensec_num_backends] = discard_const(ops);
1094 gensec_num_backends++;
1095 generic_security_ops[gensec_num_backends] = NULL;
1097 DEBUG(3,("GENSEC backend '%s' registered\n",
1100 return NT_STATUS_OK;
1104 return the GENSEC interface version, and the size of some critical types
1105 This can be used by backends to either detect compilation errors, or provide
1106 multiple implementations for different smbd compilation options in one module
1108 const struct gensec_critical_sizes *gensec_interface_version(void)
1110 static const struct gensec_critical_sizes critical_sizes = {
1111 GENSEC_INTERFACE_VERSION,
1112 sizeof(struct gensec_security_ops),
1113 sizeof(struct gensec_security),
1116 return &critical_sizes;
1120 initialise the GENSEC subsystem
1122 NTSTATUS gensec_init(void)
1124 static BOOL initialized = False;
1126 init_module_fn static_init[] = STATIC_gensec_MODULES;
1127 init_module_fn *shared_init = load_samba_modules(NULL, "gensec");
1129 if (initialized) return NT_STATUS_OK;
1132 run_init_functions(static_init);
1133 run_init_functions(shared_init);
1135 talloc_free(shared_init);
1137 return NT_STATUS_OK;