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);
381 (*gensec_security)->subcontext = False;
382 (*gensec_security)->want_features = 0;
385 ev = event_context_init(*gensec_security);
387 talloc_free(*gensec_security);
388 return NT_STATUS_NO_MEMORY;
392 (*gensec_security)->event_ctx = ev;
398 * Start a GENSEC subcontext, with a copy of the properties of the parent
399 * @param mem_ctx The parent TALLOC memory context.
400 * @param parent The parent GENSEC context
401 * @param gensec_security Returned GENSEC context pointer.
402 * @note Used by SPNEGO in particular, for the actual implementation mechanism
405 NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
406 struct gensec_security *parent,
407 struct gensec_security **gensec_security)
409 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
410 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
412 (**gensec_security) = *parent;
413 (*gensec_security)->ops = NULL;
414 (*gensec_security)->private_data = NULL;
416 (*gensec_security)->subcontext = True;
417 (*gensec_security)->event_ctx = parent->event_ctx;
423 Start the GENSEC system, in client mode, returning a context pointer.
424 @param mem_ctx The parent TALLOC memory context.
425 @param gensec_security Returned GENSEC context pointer.
426 @note The mem_ctx is only a parent and may be NULL.
428 NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
429 struct gensec_security **gensec_security,
430 struct event_context *ev)
433 status = gensec_start(mem_ctx, gensec_security, ev);
434 if (!NT_STATUS_IS_OK(status)) {
437 (*gensec_security)->gensec_role = GENSEC_CLIENT;
443 Start the GENSEC system, in server mode, returning a context pointer.
444 @param mem_ctx The parent TALLOC memory context.
445 @param gensec_security Returned GENSEC context pointer.
446 @note The mem_ctx is only a parent and may be NULL.
448 NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
449 struct gensec_security **gensec_security,
450 struct event_context *ev)
453 status = gensec_start(mem_ctx, gensec_security, ev);
454 if (!NT_STATUS_IS_OK(status)) {
457 (*gensec_security)->gensec_role = GENSEC_SERVER;
462 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
465 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
466 gensec_security->subcontext ? "sub" : "",
467 gensec_security->ops->name));
468 switch (gensec_security->gensec_role) {
470 if (gensec_security->ops->client_start) {
471 status = gensec_security->ops->client_start(gensec_security);
472 if (!NT_STATUS_IS_OK(status)) {
473 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
474 gensec_security->ops->name, nt_errstr(status)));
479 if (gensec_security->ops->server_start) {
480 status = gensec_security->ops->server_start(gensec_security);
481 if (!NT_STATUS_IS_OK(status)) {
482 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
483 gensec_security->ops->name, nt_errstr(status)));
488 return NT_STATUS_INVALID_PARAMETER;
492 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
493 * @param gensec_security GENSEC context pointer.
494 * @param auth_type DCERPC auth type
495 * @param auth_level DCERPC auth level
498 NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
499 uint8_t auth_type, uint8_t auth_level)
501 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
502 if (!gensec_security->ops) {
503 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
504 return NT_STATUS_INVALID_PARAMETER;
506 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
507 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
508 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
509 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
510 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
511 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
512 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
513 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
514 /* Default features */
516 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
518 return NT_STATUS_INVALID_PARAMETER;
521 return gensec_start_mech(gensec_security);
524 const char *gensec_get_name_by_authtype(uint8_t authtype)
526 const struct gensec_security_ops *ops;
527 ops = gensec_security_by_authtype(NULL, authtype);
535 const char *gensec_get_name_by_oid(const char *oid_string)
537 const struct gensec_security_ops *ops;
538 ops = gensec_security_by_oid(NULL, oid_string);
547 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
551 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
552 const struct gensec_security_ops *ops)
554 gensec_security->ops = ops;
555 return gensec_start_mech(gensec_security);
559 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
561 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
562 * well-known #define to hook it in.
565 NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
566 const char *mech_oid)
568 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
569 if (!gensec_security->ops) {
570 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
571 return NT_STATUS_INVALID_PARAMETER;
573 return gensec_start_mech(gensec_security);
577 * Start a GENSEC sub-mechanism by a well know SASL name
581 NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
582 const char *sasl_name)
584 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
585 if (!gensec_security->ops) {
586 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
587 return NT_STATUS_INVALID_PARAMETER;
589 return gensec_start_mech(gensec_security);
593 * Start a GENSEC sub-mechanism by an internal name
597 NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
600 gensec_security->ops = gensec_security_by_name(gensec_security, name);
601 if (!gensec_security->ops) {
602 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
603 return NT_STATUS_INVALID_PARAMETER;
605 return gensec_start_mech(gensec_security);
609 wrappers for the gensec function pointers
611 NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
613 uint8_t *data, size_t length,
614 const uint8_t *whole_pdu, size_t pdu_length,
615 const DATA_BLOB *sig)
617 if (!gensec_security->ops->unseal_packet) {
618 return NT_STATUS_NOT_IMPLEMENTED;
620 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
621 return NT_STATUS_INVALID_PARAMETER;
624 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
626 whole_pdu, pdu_length,
630 NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
632 const uint8_t *data, size_t length,
633 const uint8_t *whole_pdu, size_t pdu_length,
634 const DATA_BLOB *sig)
636 if (!gensec_security->ops->check_packet) {
637 return NT_STATUS_NOT_IMPLEMENTED;
639 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
640 return NT_STATUS_INVALID_PARAMETER;
643 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
646 NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
648 uint8_t *data, size_t length,
649 const uint8_t *whole_pdu, size_t pdu_length,
652 if (!gensec_security->ops->seal_packet) {
653 return NT_STATUS_NOT_IMPLEMENTED;
655 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
656 return NT_STATUS_INVALID_PARAMETER;
659 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
662 NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
664 const uint8_t *data, size_t length,
665 const uint8_t *whole_pdu, size_t pdu_length,
668 if (!gensec_security->ops->sign_packet) {
669 return NT_STATUS_NOT_IMPLEMENTED;
671 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
672 return NT_STATUS_INVALID_PARAMETER;
675 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
678 size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
680 if (!gensec_security->ops->sig_size) {
683 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
687 return gensec_security->ops->sig_size(gensec_security, data_size);
690 NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
695 if (!gensec_security->ops->wrap) {
696 return NT_STATUS_NOT_IMPLEMENTED;
698 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
701 NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
706 if (!gensec_security->ops->unwrap) {
707 return NT_STATUS_NOT_IMPLEMENTED;
709 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
712 NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
713 DATA_BLOB *session_key)
715 if (!gensec_security->ops->session_key) {
716 return NT_STATUS_NOT_IMPLEMENTED;
718 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
719 return NT_STATUS_NO_USER_SESSION_KEY;
722 return gensec_security->ops->session_key(gensec_security, session_key);
726 * Return the credentials of a logged on user, including session keys
729 * Only valid after a successful authentication
731 * May only be called once per authentication.
735 NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
736 struct auth_session_info **session_info)
738 if (!gensec_security->ops->session_info) {
739 return NT_STATUS_NOT_IMPLEMENTED;
741 return gensec_security->ops->session_info(gensec_security, session_info);
745 * Next state function for the GENSEC state machine
747 * @param gensec_security GENSEC State
748 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
749 * @param in The request, as a DATA_BLOB
750 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
751 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
752 * or NT_STATUS_OK if the user is authenticated.
755 NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
756 const DATA_BLOB in, DATA_BLOB *out)
758 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
762 * Set the requirement for a certain feature on the connection
766 void gensec_want_feature(struct gensec_security *gensec_security,
769 gensec_security->want_features |= feature;
773 * Check the requirement for a certain feature on the connection
777 BOOL gensec_have_feature(struct gensec_security *gensec_security,
780 if (!gensec_security->ops->have_feature) {
784 /* Can only 'have' a feature if you already 'want'ed it */
785 if (gensec_security->want_features & feature) {
786 return gensec_security->ops->have_feature(gensec_security, feature);
792 * Associate a credentails structure with a GENSEC context - talloc_reference()s it to the context
796 NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
798 gensec_security->credentials = talloc_reference(gensec_security, credentials);
803 * Return the credentails structure associated with a GENSEC context
807 struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
809 if (!gensec_security) {
812 return gensec_security->credentials;
816 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
820 NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
822 gensec_security->target.service = talloc_strdup(gensec_security, service);
823 if (!gensec_security->target.service) {
824 return NT_STATUS_NO_MEMORY;
829 const char *gensec_get_target_service(struct gensec_security *gensec_security)
831 if (gensec_security->target.service) {
832 return gensec_security->target.service;
839 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
843 NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
845 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
846 if (!gensec_security->target.hostname) {
847 return NT_STATUS_NO_MEMORY;
852 const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
854 if (gensec_security->target.hostname) {
855 return gensec_security->target.hostname;
858 /* TODO: Add a 'set sockaddr' call, and do a reverse lookup */
863 * Set the target principal (assuming it it known, say from the SPNEGO reply)
864 * - ensures it is talloc()ed
868 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
870 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
871 if (!gensec_security->target.principal) {
872 return NT_STATUS_NO_MEMORY;
877 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
879 if (gensec_security->target.principal) {
880 return gensec_security->target.principal;
887 register a GENSEC backend.
889 The 'name' can be later used by other backends to find the operations
890 structure for this backend.
892 NTSTATUS gensec_register(const void *_ops)
894 const struct gensec_security_ops *ops = _ops;
896 if (!lp_parm_bool(-1, "gensec", ops->name, ops->enabled)) {
897 DEBUG(2,("gensec subsystem %s is disabled\n", ops->name));
901 if (gensec_security_by_name(NULL, ops->name) != NULL) {
902 /* its already registered! */
903 DEBUG(0,("GENSEC backend '%s' already registered\n",
905 return NT_STATUS_OBJECT_NAME_COLLISION;
908 generic_security_ops = realloc_p(generic_security_ops,
909 const struct gensec_security_ops *,
910 gensec_num_backends+2);
911 if (!generic_security_ops) {
912 smb_panic("out of memory in gensec_register");
915 generic_security_ops[gensec_num_backends] = ops;
916 gensec_num_backends++;
917 generic_security_ops[gensec_num_backends] = NULL;
919 DEBUG(3,("GENSEC backend '%s' registered\n",
926 return the GENSEC interface version, and the size of some critical types
927 This can be used by backends to either detect compilation errors, or provide
928 multiple implementations for different smbd compilation options in one module
930 const struct gensec_critical_sizes *gensec_interface_version(void)
932 static const struct gensec_critical_sizes critical_sizes = {
933 GENSEC_INTERFACE_VERSION,
934 sizeof(struct gensec_security_ops),
935 sizeof(struct gensec_security),
938 return &critical_sizes;
942 initialise the GENSEC subsystem
944 NTSTATUS gensec_init(void)
946 static BOOL initialized = False;
948 init_module_fn static_init[] = STATIC_GENSEC_MODULES;
949 init_module_fn *shared_init = load_samba_modules(NULL, "gensec");
951 if (initialized) return NT_STATUS_OK;
954 run_init_functions(static_init);
955 run_init_functions(shared_init);
957 talloc_free(shared_init);