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 const static struct gensec_security_ops **generic_security_ops;
31 static int gensec_num_backends;
33 const struct gensec_security_ops **gensec_security_all(void)
35 return generic_security_ops;
38 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
42 const struct gensec_security_ops **backends;
43 if (!gensec_security) {
44 backends = gensec_security_all();
46 backends = cli_credentials_gensec_list(gensec_get_credentials(gensec_security));
48 for (i=0; backends && backends[i]; i++) {
49 if (backends[i]->auth_type == auth_type) {
57 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
58 const char *oid_string)
61 const struct gensec_security_ops **backends;
62 if (!gensec_security) {
63 backends = gensec_security_all();
65 backends = cli_credentials_gensec_list(gensec_get_credentials(gensec_security));
67 for (i=0; backends && backends[i]; i++) {
68 if (backends[i]->oid) {
69 for (j=0; backends[i]->oid[j]; j++) {
70 if (backends[i]->oid[j] &&
71 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
81 static const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
82 const char *sasl_name)
85 const struct gensec_security_ops **backends;
86 if (!gensec_security) {
87 backends = gensec_security_all();
89 backends = cli_credentials_gensec_list(gensec_get_credentials(gensec_security));
91 for (i=0; backends && backends[i]; i++) {
92 if (backends[i]->sasl_name
93 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
101 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
105 const struct gensec_security_ops **backends;
106 if (!gensec_security) {
107 backends = gensec_security_all();
109 backends = cli_credentials_gensec_list(gensec_get_credentials(gensec_security));
111 for (i=0; backends && backends[i]; i++) {
112 if (backends[i]->name
113 && (strcmp(backends[i]->name, name) == 0)) {
122 * Return a unique list of security subsystems from those specified in
123 * the list of SASL names.
125 * Use the list of enabled GENSEC mechanisms from the credentials
126 * attached to the gensec_security, and return in our preferred order.
129 const struct gensec_security_ops **gensec_security_by_sasl(struct gensec_security *gensec_security,
131 const char **sasl_names)
133 const struct gensec_security_ops **backends_out;
134 const struct gensec_security_ops **backends;
136 int num_backends_out = 0;
142 backends = cli_credentials_gensec_list(gensec_get_credentials(gensec_security));
144 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
148 backends_out[0] = NULL;
150 /* Find backends in our preferred order, by walking our list,
151 * then looking in the supplied list */
152 for (i=0; backends && backends[i]; i++) {
153 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
154 if (!backends[i]->sasl_name ||
155 !(strcmp(backends[i]->sasl_name,
156 sasl_names[sasl_idx]) == 0)) {
160 for (k=0; backends_out[k]; k++) {
161 if (backends_out[k] == backends[i]) {
166 if (k < num_backends_out) {
167 /* already in there */
171 backends_out = talloc_realloc(mem_ctx, backends_out,
172 const struct gensec_security_ops *,
173 num_backends_out + 2);
178 backends_out[num_backends_out] = backends[i];
180 backends_out[num_backends_out] = NULL;
187 * Return a unique list of security subsystems from those specified in
188 * the OID list. That is, where two OIDs refer to the same module,
189 * return that module only once.
191 * Use the list of enabled GENSEC mechanisms from the credentials
192 * attached to the gensec_security, and return in our preferred order.
195 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
197 const char **oid_strings,
200 struct gensec_security_ops_wrapper *backends_out;
201 const struct gensec_security_ops **backends;
202 int i, j, k, oid_idx;
203 int num_backends_out = 0;
209 backends = cli_credentials_gensec_list(gensec_get_credentials(gensec_security));
211 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
215 backends_out[0].op = NULL;
216 backends_out[0].oid = NULL;
218 /* Find backends in our preferred order, by walking our list,
219 * then looking in the supplied list */
220 for (i=0; backends && backends[i]; i++) {
221 if (!backends[i]->oid) {
224 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
225 if (strcmp(oid_strings[oid_idx], skip) == 0) {
229 for (j=0; backends[i]->oid[j]; j++) {
230 if (!backends[i]->oid[j] ||
231 !(strcmp(backends[i]->oid[j],
232 oid_strings[oid_idx]) == 0)) {
236 for (k=0; backends_out[k].op; k++) {
237 if (backends_out[k].op == backends[i]) {
242 if (k < num_backends_out) {
243 /* already in there */
247 backends_out = talloc_realloc(mem_ctx, backends_out,
248 struct gensec_security_ops_wrapper,
249 num_backends_out + 2);
254 backends_out[num_backends_out].op = backends[i];
255 backends_out[num_backends_out].oid = backends[i]->oid[j];
257 backends_out[num_backends_out].op = NULL;
258 backends_out[num_backends_out].oid = NULL;
266 * Return OIDS from the security subsystems listed
269 const char **gensec_security_oids_from_ops(TALLOC_CTX *mem_ctx,
270 const struct gensec_security_ops **ops,
276 const char **oid_list;
280 oid_list = talloc_array(mem_ctx, const char *, 1);
285 for (i=0; ops && ops[i]; i++) {
290 for (k = 0; ops[i]->oid[k]; k++) {
291 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
293 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
297 oid_list[j] = ops[i]->oid[k];
308 * Return OIDS from the security subsystems listed
311 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
312 const struct gensec_security_ops_wrapper *wops)
317 const char **oid_list;
321 oid_list = talloc_array(mem_ctx, const char *, 1);
326 for (i=0; wops[i].op; i++) {
327 if (!wops[i].op->oid) {
331 for (k = 0; wops[i].op->oid[k]; k++) {
332 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
336 oid_list[j] = wops[i].op->oid[k];
346 * Return all the security subsystems currently enabled on a GENSEC context.
348 * This is taken from a list attached to the cli_credentails, and
349 * skips the OID in 'skip'. (Typically the SPNEGO OID)
353 const char **gensec_security_oids(struct gensec_security *gensec_security,
357 const struct gensec_security_ops **ops
358 = cli_credentials_gensec_list(gensec_get_credentials(gensec_security));
359 return gensec_security_oids_from_ops(mem_ctx, ops, skip);
365 Start the GENSEC system, returning a context pointer.
366 @param mem_ctx The parent TALLOC memory context.
367 @param gensec_security Returned GENSEC context pointer.
368 @note The mem_ctx is only a parent and may be NULL.
370 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
371 struct gensec_security **gensec_security,
372 struct event_context *ev)
374 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
375 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
377 (*gensec_security)->ops = NULL;
379 ZERO_STRUCT((*gensec_security)->target);
380 ZERO_STRUCT((*gensec_security)->peer_addr);
381 ZERO_STRUCT((*gensec_security)->my_addr);
383 (*gensec_security)->subcontext = False;
384 (*gensec_security)->want_features = 0;
387 ev = event_context_init(*gensec_security);
389 talloc_free(*gensec_security);
390 return NT_STATUS_NO_MEMORY;
394 (*gensec_security)->event_ctx = ev;
400 * Start a GENSEC subcontext, with a copy of the properties of the parent
401 * @param mem_ctx The parent TALLOC memory context.
402 * @param parent The parent GENSEC context
403 * @param gensec_security Returned GENSEC context pointer.
404 * @note Used by SPNEGO in particular, for the actual implementation mechanism
407 NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
408 struct gensec_security *parent,
409 struct gensec_security **gensec_security)
411 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
412 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
414 (**gensec_security) = *parent;
415 (*gensec_security)->ops = NULL;
416 (*gensec_security)->private_data = NULL;
418 (*gensec_security)->subcontext = True;
419 (*gensec_security)->event_ctx = parent->event_ctx;
425 Start the GENSEC system, in client mode, returning a context pointer.
426 @param mem_ctx The parent TALLOC memory context.
427 @param gensec_security Returned GENSEC context pointer.
428 @note The mem_ctx is only a parent and may be NULL.
430 NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
431 struct gensec_security **gensec_security,
432 struct event_context *ev)
435 status = gensec_start(mem_ctx, gensec_security, ev);
436 if (!NT_STATUS_IS_OK(status)) {
439 (*gensec_security)->gensec_role = GENSEC_CLIENT;
445 Start the GENSEC system, in server mode, returning a context pointer.
446 @param mem_ctx The parent TALLOC memory context.
447 @param gensec_security Returned GENSEC context pointer.
448 @note The mem_ctx is only a parent and may be NULL.
450 NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
451 struct gensec_security **gensec_security,
452 struct event_context *ev)
455 status = gensec_start(mem_ctx, gensec_security, ev);
456 if (!NT_STATUS_IS_OK(status)) {
459 (*gensec_security)->gensec_role = GENSEC_SERVER;
464 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
467 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
468 gensec_security->subcontext ? "sub" : "",
469 gensec_security->ops->name));
470 switch (gensec_security->gensec_role) {
472 if (gensec_security->ops->client_start) {
473 status = gensec_security->ops->client_start(gensec_security);
474 if (!NT_STATUS_IS_OK(status)) {
475 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
476 gensec_security->ops->name, nt_errstr(status)));
481 if (gensec_security->ops->server_start) {
482 status = gensec_security->ops->server_start(gensec_security);
483 if (!NT_STATUS_IS_OK(status)) {
484 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
485 gensec_security->ops->name, nt_errstr(status)));
490 return NT_STATUS_INVALID_PARAMETER;
494 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
495 * @param gensec_security GENSEC context pointer.
496 * @param auth_type DCERPC auth type
497 * @param auth_level DCERPC auth level
500 NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
501 uint8_t auth_type, uint8_t auth_level)
503 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
504 if (!gensec_security->ops) {
505 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
506 return NT_STATUS_INVALID_PARAMETER;
508 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
509 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
510 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
511 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
512 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
513 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
514 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
515 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
516 /* Default features */
518 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
520 return NT_STATUS_INVALID_PARAMETER;
523 return gensec_start_mech(gensec_security);
526 const char *gensec_get_name_by_authtype(uint8_t authtype)
528 const struct gensec_security_ops *ops;
529 ops = gensec_security_by_authtype(NULL, authtype);
537 const char *gensec_get_name_by_oid(const char *oid_string)
539 const struct gensec_security_ops *ops;
540 ops = gensec_security_by_oid(NULL, oid_string);
549 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
553 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
554 const struct gensec_security_ops *ops)
556 gensec_security->ops = ops;
557 return gensec_start_mech(gensec_security);
561 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
563 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
564 * well-known #define to hook it in.
567 NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
568 const char *mech_oid)
570 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
571 if (!gensec_security->ops) {
572 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
573 return NT_STATUS_INVALID_PARAMETER;
575 return gensec_start_mech(gensec_security);
579 * Start a GENSEC sub-mechanism by a well know SASL name
583 NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
584 const char *sasl_name)
586 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
587 if (!gensec_security->ops) {
588 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
589 return NT_STATUS_INVALID_PARAMETER;
591 return gensec_start_mech(gensec_security);
595 * Start a GENSEC sub-mechanism by an internal name
599 NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
602 gensec_security->ops = gensec_security_by_name(gensec_security, name);
603 if (!gensec_security->ops) {
604 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
605 return NT_STATUS_INVALID_PARAMETER;
607 return gensec_start_mech(gensec_security);
611 wrappers for the gensec function pointers
613 NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
615 uint8_t *data, size_t length,
616 const uint8_t *whole_pdu, size_t pdu_length,
617 const DATA_BLOB *sig)
619 if (!gensec_security->ops->unseal_packet) {
620 return NT_STATUS_NOT_IMPLEMENTED;
622 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
623 return NT_STATUS_INVALID_PARAMETER;
626 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
628 whole_pdu, pdu_length,
632 NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
634 const uint8_t *data, size_t length,
635 const uint8_t *whole_pdu, size_t pdu_length,
636 const DATA_BLOB *sig)
638 if (!gensec_security->ops->check_packet) {
639 return NT_STATUS_NOT_IMPLEMENTED;
641 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
642 return NT_STATUS_INVALID_PARAMETER;
645 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
648 NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
650 uint8_t *data, size_t length,
651 const uint8_t *whole_pdu, size_t pdu_length,
654 if (!gensec_security->ops->seal_packet) {
655 return NT_STATUS_NOT_IMPLEMENTED;
657 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
658 return NT_STATUS_INVALID_PARAMETER;
661 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
664 NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
666 const uint8_t *data, size_t length,
667 const uint8_t *whole_pdu, size_t pdu_length,
670 if (!gensec_security->ops->sign_packet) {
671 return NT_STATUS_NOT_IMPLEMENTED;
673 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
674 return NT_STATUS_INVALID_PARAMETER;
677 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
680 size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
682 if (!gensec_security->ops->sig_size) {
685 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
689 return gensec_security->ops->sig_size(gensec_security, data_size);
692 NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
697 if (!gensec_security->ops->wrap) {
698 return NT_STATUS_NOT_IMPLEMENTED;
700 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
703 NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
708 if (!gensec_security->ops->unwrap) {
709 return NT_STATUS_NOT_IMPLEMENTED;
711 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
714 NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
715 DATA_BLOB *session_key)
717 if (!gensec_security->ops->session_key) {
718 return NT_STATUS_NOT_IMPLEMENTED;
720 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
721 return NT_STATUS_NO_USER_SESSION_KEY;
724 return gensec_security->ops->session_key(gensec_security, session_key);
728 * Return the credentials of a logged on user, including session keys
731 * Only valid after a successful authentication
733 * May only be called once per authentication.
737 NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
738 struct auth_session_info **session_info)
740 if (!gensec_security->ops->session_info) {
741 return NT_STATUS_NOT_IMPLEMENTED;
743 return gensec_security->ops->session_info(gensec_security, session_info);
747 * Next state function for the GENSEC state machine
749 * @param gensec_security GENSEC State
750 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
751 * @param in The request, as a DATA_BLOB
752 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
753 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
754 * or NT_STATUS_OK if the user is authenticated.
757 NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
758 const DATA_BLOB in, DATA_BLOB *out)
760 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
764 * Set the requirement for a certain feature on the connection
768 void gensec_want_feature(struct gensec_security *gensec_security,
771 gensec_security->want_features |= feature;
775 * Check the requirement for a certain feature on the connection
779 BOOL gensec_have_feature(struct gensec_security *gensec_security,
782 if (!gensec_security->ops->have_feature) {
786 /* Can only 'have' a feature if you already 'want'ed it */
787 if (gensec_security->want_features & feature) {
788 return gensec_security->ops->have_feature(gensec_security, feature);
794 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
798 NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
800 gensec_security->credentials = talloc_reference(gensec_security, credentials);
805 * Return the credentials structure associated with a GENSEC context
809 struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
811 if (!gensec_security) {
814 return gensec_security->credentials;
818 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
822 NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
824 gensec_security->target.service = talloc_strdup(gensec_security, service);
825 if (!gensec_security->target.service) {
826 return NT_STATUS_NO_MEMORY;
831 const char *gensec_get_target_service(struct gensec_security *gensec_security)
833 if (gensec_security->target.service) {
834 return gensec_security->target.service;
841 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
845 NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
847 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
848 if (!gensec_security->target.hostname) {
849 return NT_STATUS_NO_MEMORY;
854 const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
856 if (gensec_security->target.hostname) {
857 return gensec_security->target.hostname;
860 /* We could add use the 'set sockaddr' call, and do a reverse
861 * lookup, but this would be both insecure (compromising the
862 * way kerberos works) and add DNS timeouts */
867 * Set local and peer socket addresses onto a socket context on the GENSEC context
869 * This is so that kerberos can include these addresses in
870 * cryptographic tokens, to avoid certain attacks.
873 NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, const char *my_addr, int port)
875 gensec_security->my_addr.addr = talloc_strdup(gensec_security, my_addr);
876 if (my_addr && !gensec_security->my_addr.addr) {
877 return NT_STATUS_NO_MEMORY;
879 gensec_security->my_addr.port = port;
883 NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, const char *peer_addr, int port)
885 gensec_security->peer_addr.addr = talloc_strdup(gensec_security, peer_addr);
886 if (peer_addr && !gensec_security->peer_addr.addr) {
887 return NT_STATUS_NO_MEMORY;
889 gensec_security->peer_addr.port = port;
893 const char *gensec_get_my_addr(struct gensec_security *gensec_security, int *port)
895 if (gensec_security->my_addr.addr) {
897 *port = gensec_security->my_addr.port;
899 return gensec_security->my_addr.addr;
902 /* We could add a 'set sockaddr' call, and do a lookup. This
903 * would avoid needing to do system calls if nothing asks. */
907 const char *gensec_get_peer_addr(struct gensec_security *gensec_security, int *port)
909 if (gensec_security->peer_addr.addr) {
911 *port = gensec_security->peer_addr.port;
913 return gensec_security->peer_addr.addr;
916 /* We could add a 'set sockaddr' call, and do a lookup. This
917 * would avoid needing to do system calls if nothing asks.
918 * However, this is not appropriate for the peer addres on
919 * datagram sockets */
926 * Set the target principal (assuming it it known, say from the SPNEGO reply)
927 * - ensures it is talloc()ed
931 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
933 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
934 if (!gensec_security->target.principal) {
935 return NT_STATUS_NO_MEMORY;
940 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
942 if (gensec_security->target.principal) {
943 return gensec_security->target.principal;
950 register a GENSEC backend.
952 The 'name' can be later used by other backends to find the operations
953 structure for this backend.
955 NTSTATUS gensec_register(const void *_ops)
957 const struct gensec_security_ops *ops = _ops;
959 if (!lp_parm_bool(-1, "gensec", ops->name, ops->enabled)) {
960 DEBUG(2,("gensec subsystem %s is disabled\n", ops->name));
964 if (gensec_security_by_name(NULL, ops->name) != NULL) {
965 /* its already registered! */
966 DEBUG(0,("GENSEC backend '%s' already registered\n",
968 return NT_STATUS_OBJECT_NAME_COLLISION;
971 generic_security_ops = realloc_p(generic_security_ops,
972 const struct gensec_security_ops *,
973 gensec_num_backends+2);
974 if (!generic_security_ops) {
975 smb_panic("out of memory in gensec_register");
978 generic_security_ops[gensec_num_backends] = ops;
979 gensec_num_backends++;
980 generic_security_ops[gensec_num_backends] = NULL;
982 DEBUG(3,("GENSEC backend '%s' registered\n",
989 return the GENSEC interface version, and the size of some critical types
990 This can be used by backends to either detect compilation errors, or provide
991 multiple implementations for different smbd compilation options in one module
993 const struct gensec_critical_sizes *gensec_interface_version(void)
995 static const struct gensec_critical_sizes critical_sizes = {
996 GENSEC_INTERFACE_VERSION,
997 sizeof(struct gensec_security_ops),
998 sizeof(struct gensec_security),
1001 return &critical_sizes;
1005 initialise the GENSEC subsystem
1007 NTSTATUS gensec_init(void)
1009 static BOOL initialized = False;
1011 init_module_fn static_init[] = STATIC_GENSEC_MODULES;
1012 init_module_fn *shared_init = load_samba_modules(NULL, "gensec");
1014 if (initialized) return NT_STATUS_OK;
1017 run_init_functions(static_init);
1018 run_init_functions(shared_init);
1020 talloc_free(shared_init);
1022 return NT_STATUS_OK;