LCOV - code coverage report
Current view: top level - auth/gensec - gensec_start.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 405 470 86.2 %
Date: 2024-06-10 12:05:21 Functions: 40 41 97.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Generic Authentication Interface
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
       8             : 
       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 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      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.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "system/network.h"
      25             : #include "tevent.h"
      26             : #include "../lib/util/tevent_ntstatus.h"
      27             : #include "librpc/gen_ndr/dcerpc.h"
      28             : #include "auth/credentials/credentials.h"
      29             : #include "auth/gensec/gensec.h"
      30             : #include "auth/gensec/gensec_internal.h"
      31             : #include "lib/param/param.h"
      32             : #include "lib/param/loadparm.h"
      33             : #include "lib/util/tsort.h"
      34             : #include "lib/util/samba_modules.h"
      35             : #include "lib/util/base64.h"
      36             : 
      37             : #undef DBGC_CLASS
      38             : #define DBGC_CLASS DBGC_AUTH
      39             : 
      40             : #undef strcasecmp
      41             : 
      42             : /* the list of currently registered GENSEC backends */
      43             : static const struct gensec_security_ops **generic_security_ops;
      44             : static int gensec_num_backends;
      45             : 
      46     5765907 : static bool gensec_security_ops_enabled(const struct gensec_security_ops *ops,
      47             :                                         struct gensec_security *security)
      48             : {
      49     5908500 :         bool ok = lpcfg_parm_bool(security->settings->lp_ctx,
      50             :                                   NULL,
      51             :                                   "gensec",
      52     5765907 :                                   ops->name,
      53     5765907 :                                   ops->enabled);
      54             : 
      55     6755392 :         if (ops->weak_crypto &&
      56      989485 :             lpcfg_weak_crypto(security->settings->lp_ctx) != SAMBA_WEAK_CRYPTO_ALLOWED) {
      57           6 :                 ok = false;
      58             :         }
      59             : 
      60     5765907 :         return ok;
      61             : }
      62             : 
      63             : /* Sometimes we want to force only kerberos, sometimes we want to
      64             :  * force it's avoidance.  The old list could be either
      65             :  * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
      66             :  * an existing list we have trimmed down)
      67             :  *
      68             :  * The intended logic is:
      69             :  *
      70             :  * if we are in the default AUTO have kerberos:
      71             :  * - take a reference to the master list
      72             :  * otherwise
      73             :  * - always add spnego then:
      74             :  * - if we 'MUST' have kerberos:
      75             :  *   only add kerberos mechs
      76             :  * - if we 'DONT' want kerberos':
      77             :  *   only add non-kerberos mechs
      78             :  *
      79             :  * Once we get things like NegoEx or moonshot, this will of course get
      80             :  * more complex.
      81             :  */
      82             : 
      83    18590414 : static bool gensec_offer_mech(struct gensec_security *gensec_security,
      84             :                               const struct gensec_security_ops *mech)
      85             : {
      86    18590414 :         struct cli_credentials *creds = NULL;
      87      265202 :         enum credentials_use_kerberos use_kerberos;
      88      265202 :         bool offer;
      89             : 
      90             :         /*
      91             :          * We want to always offer SPNEGO and other backends
      92             :          */
      93    18590414 :         offer = mech->glue;
      94             : 
      95    18590414 :         if (gensec_security != NULL) {
      96     6282659 :                 creds = gensec_get_credentials(gensec_security);
      97             :         }
      98             : 
      99    18590414 :         if ((mech->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) && (creds != NULL))
     100             :         {
     101      611582 :                 if (cli_credentials_get_netlogon_creds(creds) != NULL) {
     102        5683 :                         offer = true;
     103             :                 }
     104             :                 /*
     105             :                  * Even if Kerberos is set to REQUIRED, offer the
     106             :                  * schannel auth mechanism so that machine accounts are
     107             :                  * able to authenticate via netlogon.
     108             :                  */
     109      611582 :                 if (gensec_security->gensec_role == GENSEC_SERVER) {
     110      383563 :                         offer = true;
     111             :                 }
     112             :         }
     113             : 
     114    18590414 :         use_kerberos = CRED_USE_KERBEROS_DESIRED;
     115    18590414 :         if (creds != NULL) {
     116     6282603 :                 use_kerberos = cli_credentials_get_kerberos_state(creds);
     117             :         }
     118             : 
     119    18478666 :         switch (use_kerberos) {
     120    16625216 :         case CRED_USE_KERBEROS_DESIRED:
     121    16625216 :                 offer = true;
     122    16625216 :                 break;
     123     1399916 :         case CRED_USE_KERBEROS_DISABLED:
     124     1399916 :                 if (!mech->kerberos) {
     125     1045793 :                         offer = true;
     126             :                 }
     127     1386910 :                 break;
     128      325518 :         case CRED_USE_KERBEROS_REQUIRED:
     129      325518 :                 if (mech->kerberos) {
     130      114789 :                         offer = true;
     131             :                 }
     132      313086 :                 break;
     133           0 :         default:
     134             :                 /* Can't happen or invalid parameter */
     135           0 :                 offer = false;
     136             :         }
     137             : 
     138    18590414 :         if (offer && (gensec_security != NULL)) {
     139     5765907 :                 offer = gensec_security_ops_enabled(mech, gensec_security);
     140             :         }
     141             : 
     142    18590414 :         return offer;
     143             : }
     144             : 
     145     2013539 : _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs(
     146             :                                 struct gensec_security *gensec_security,
     147             :                                 TALLOC_CTX *mem_ctx)
     148             : {
     149     2013539 :         const struct gensec_security_ops * const *backends =
     150             :                 generic_security_ops;
     151     2013539 :         const struct gensec_security_ops **result = NULL;
     152       28153 :         size_t i, j, num_backends;
     153             : 
     154     2013539 :         if ((gensec_security != NULL) &&
     155      612316 :             (gensec_security->settings->backends != NULL)) {
     156      256340 :                 backends = gensec_security->settings->backends;
     157             :         }
     158             : 
     159     2013539 :         if (backends == NULL) {
     160             :                 /* Just return the NULL terminator */
     161       61098 :                 return talloc_zero(mem_ctx,
     162             :                                    const struct gensec_security_ops *);
     163             :         }
     164             : 
     165    20542855 :         for (num_backends = 0; backends[num_backends]; num_backends++) {
     166             :                 /* noop */
     167      265202 :         }
     168             : 
     169     1952441 :         result = talloc_array(
     170             :                 mem_ctx, const struct gensec_security_ops *, num_backends + 1);
     171     1952441 :         if (result == NULL) {
     172           0 :                 return NULL;
     173             :         }
     174             : 
     175     1925516 :         j = 0;
     176    20542855 :         for (i = 0; backends[i]; i++) {
     177    18590414 :                 bool offer = gensec_offer_mech(gensec_security, backends[i]);
     178    18590414 :                 if (offer) {
     179    17455893 :                         result[j++] = backends[i];
     180             :                 }
     181             :         }
     182             : 
     183     1952441 :         result[j] = NULL;
     184     1952441 :         return result;
     185             : }
     186             : 
     187     1617519 : static const struct gensec_security_ops *gensec_security_by_fn(
     188             :         struct gensec_security *gensec_security,
     189             :         bool (*fn)(const struct gensec_security_ops *backend,
     190             :                    const void *private_data),
     191             :         const void *private_data)
     192             : {
     193       21554 :         size_t i;
     194     1617519 :         const struct gensec_security_ops **backends = NULL;
     195             : 
     196     1617519 :         backends = gensec_security_mechs(gensec_security, gensec_security);
     197     1617519 :         if (backends == NULL) {
     198           0 :                 return NULL;
     199             :         }
     200             : 
     201     9140689 :         for (i = 0; backends[i] != NULL; i++) {
     202     8370027 :                 const struct gensec_security_ops *backend = backends[i];
     203      118768 :                 bool ok;
     204             : 
     205     8370027 :                 ok = fn(backend, private_data);
     206     8370027 :                 if (ok) {
     207      846857 :                         TALLOC_FREE(backends);
     208      846857 :                         return backend;
     209             :                 }
     210             :         }
     211             : 
     212      770662 :         TALLOC_FREE(backends);
     213      770662 :         return NULL;
     214             : }
     215             : 
     216     1318853 : static bool by_oid_fn(const struct gensec_security_ops *backend,
     217             :                       const void *private_data)
     218             : {
     219     1318853 :         const char *oid = private_data;
     220        3274 :         int i;
     221             : 
     222     1318853 :         if (backend->oid == NULL) {
     223      329311 :                 return false;
     224             :         }
     225             : 
     226     1746724 :         for (i = 0; backend->oid[i] != NULL; i++) {
     227     1180814 :                 if (strcmp(backend->oid[i], oid) == 0) {
     228      420362 :                         return true;
     229             :                 }
     230             :         }
     231      565906 :         return false;
     232             : }
     233             : 
     234      423770 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
     235             :         struct gensec_security *gensec_security,
     236             :         const char *oid_string)
     237             : {
     238      423770 :         return gensec_security_by_fn(gensec_security, by_oid_fn, oid_string);
     239             : }
     240             : 
     241       54020 : static bool by_sasl_name_fn(const struct gensec_security_ops *backend,
     242             :                             const void *private_data)
     243             : {
     244       54020 :         const char *sasl_name = private_data;
     245       54020 :         if (backend->sasl_name == NULL) {
     246         272 :                 return false;
     247             :         }
     248       53748 :         return (strcmp(backend->sasl_name, sasl_name) == 0);
     249             : }
     250             : 
     251       53484 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
     252             :         struct gensec_security *gensec_security,
     253             :         const char *sasl_name)
     254             : {
     255       53484 :         return gensec_security_by_fn(
     256             :                 gensec_security, by_sasl_name_fn, sasl_name);
     257             : }
     258             : 
     259     1972600 : static bool by_auth_type_fn(const struct gensec_security_ops *backend,
     260             :                             const void *private_data)
     261             : {
     262     1972600 :         uint32_t auth_type = *((const uint32_t *)private_data);
     263     1972600 :         return (backend->auth_type == auth_type);
     264             : }
     265             : 
     266      299809 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
     267             :         struct gensec_security *gensec_security,
     268             :         uint32_t auth_type)
     269             : {
     270      299809 :         if (auth_type == DCERPC_AUTH_TYPE_NONE) {
     271           0 :                 return NULL;
     272             :         }
     273      299809 :         return gensec_security_by_fn(
     274             :                 gensec_security, by_auth_type_fn, &auth_type);
     275             : }
     276             : 
     277     5024554 : static bool by_name_fn(const struct gensec_security_ops *backend,
     278             :                        const void *private_data)
     279             : {
     280     5024554 :         const char *name = private_data;
     281     5024554 :         if (backend->name == NULL) {
     282           0 :                 return false;
     283             :         }
     284     5024554 :         return (strcmp(backend->name, name) == 0);
     285             : }
     286             : 
     287      840456 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_name(
     288             :         struct gensec_security *gensec_security,
     289             :         const char *name)
     290             : {
     291      840456 :         return gensec_security_by_fn(gensec_security, by_name_fn, name);
     292             : }
     293             : 
     294       53985 : static const char **gensec_security_sasl_names_from_ops(
     295             :         struct gensec_security *gensec_security,
     296             :         TALLOC_CTX *mem_ctx,
     297             :         const struct gensec_security_ops * const *ops)
     298             : {
     299       53985 :         const char **sasl_names = NULL;
     300       53985 :         size_t i, sasl_names_count = 0;
     301             : 
     302       53985 :         if (ops == NULL) {
     303           0 :                 return NULL;
     304             :         }
     305             : 
     306       53985 :         sasl_names = talloc_array(mem_ctx, const char *, 1);
     307       53985 :         if (sasl_names == NULL) {
     308           0 :                 return NULL;
     309             :         }
     310             : 
     311      701805 :         for (i = 0; ops[i] != NULL; i++) {
     312      647820 :                 enum gensec_role role = GENSEC_SERVER;
     313      647820 :                 const char **tmp = NULL;
     314             : 
     315      647820 :                 if (ops[i]->sasl_name == NULL) {
     316      431880 :                         continue;
     317             :                 }
     318             : 
     319      215940 :                 if (gensec_security != NULL) {
     320      215940 :                         role = gensec_security->gensec_role;
     321             :                 }
     322             : 
     323      215940 :                 switch (role) {
     324           0 :                 case GENSEC_CLIENT:
     325           0 :                         if (ops[i]->client_start == NULL) {
     326           0 :                                 continue;
     327             :                         }
     328           0 :                         break;
     329      215940 :                 case GENSEC_SERVER:
     330      215940 :                         if (ops[i]->server_start == NULL) {
     331       53985 :                                 continue;
     332             :                         }
     333      161223 :                         break;
     334             :                 }
     335             : 
     336      161955 :                 tmp = talloc_realloc(mem_ctx,
     337             :                                      sasl_names,
     338             :                                      const char *,
     339             :                                      sasl_names_count + 2);
     340      161955 :                 if (tmp == NULL) {
     341           0 :                         TALLOC_FREE(sasl_names);
     342           0 :                         return NULL;
     343             :                 }
     344      161955 :                 sasl_names = tmp;
     345             : 
     346      161955 :                 sasl_names[sasl_names_count] = ops[i]->sasl_name;
     347      161955 :                 sasl_names_count++;
     348             :         }
     349       53985 :         sasl_names[sasl_names_count] = NULL;
     350             : 
     351       53985 :         return sasl_names;
     352             : }
     353             : 
     354             : /**
     355             :  * @brief Get the sasl names from the gensec security context.
     356             :  *
     357             :  * @param[in]  gensec_security The gensec security context.
     358             :  *
     359             :  * @param[in]  mem_ctx The memory context to allocate memory on.
     360             :  *
     361             :  * @return An allocated array with sasl names, NULL on error.
     362             :  */
     363             : _PUBLIC_
     364       53985 : const char **gensec_security_sasl_names(struct gensec_security *gensec_security,
     365             :                                         TALLOC_CTX *mem_ctx)
     366             : {
     367       53985 :         const struct gensec_security_ops **ops = NULL;
     368             : 
     369       53985 :         ops = gensec_security_mechs(gensec_security, mem_ctx);
     370             : 
     371       53985 :         return gensec_security_sasl_names_from_ops(gensec_security,
     372             :                                                    mem_ctx,
     373             :                                                    ops);
     374             : }
     375             : 
     376             : /**
     377             :  * Return a unique list of security subsystems from those specified in
     378             :  * the list of SASL names.
     379             :  *
     380             :  * Use the list of enabled GENSEC mechanisms from the credentials
     381             :  * attached to the gensec_security, and return in our preferred order.
     382             :  */
     383             : 
     384         330 : static const struct gensec_security_ops **gensec_security_by_sasl_list(
     385             :         struct gensec_security *gensec_security,
     386             :         TALLOC_CTX *mem_ctx,
     387             :         const char **sasl_names)
     388             : {
     389           0 :         const struct gensec_security_ops **backends_out;
     390           0 :         const struct gensec_security_ops **backends;
     391           0 :         int i, k, sasl_idx;
     392         330 :         int num_backends_out = 0;
     393             : 
     394         330 :         if (!sasl_names) {
     395           0 :                 return NULL;
     396             :         }
     397             : 
     398         330 :         backends = gensec_security_mechs(gensec_security, mem_ctx);
     399             : 
     400         330 :         backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
     401         330 :         if (!backends_out) {
     402           0 :                 return NULL;
     403             :         }
     404         330 :         backends_out[0] = NULL;
     405             : 
     406             :         /* Find backends in our preferred order, by walking our list,
     407             :          * then looking in the supplied list */
     408        2230 :         for (i=0; backends && backends[i]; i++) {
     409        3800 :                 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
     410        1900 :                         if (!backends[i]->sasl_name ||
     411         641 :                             !(strcmp(backends[i]->sasl_name,
     412         641 :                                      sasl_names[sasl_idx]) == 0)) {
     413        1570 :                                 continue;
     414             :                         }
     415             : 
     416         330 :                         for (k=0; backends_out[k]; k++) {
     417           0 :                                 if (backends_out[k] == backends[i]) {
     418           0 :                                         break;
     419             :                                 }
     420             :                         }
     421             : 
     422         330 :                         if (k < num_backends_out) {
     423             :                                 /* already in there */
     424           0 :                                 continue;
     425             :                         }
     426             : 
     427         330 :                         backends_out = talloc_realloc(mem_ctx, backends_out,
     428             :                                                       const struct gensec_security_ops *,
     429             :                                                       num_backends_out + 2);
     430         330 :                         if (!backends_out) {
     431           0 :                                 return NULL;
     432             :                         }
     433             : 
     434         330 :                         backends_out[num_backends_out] = backends[i];
     435         330 :                         num_backends_out++;
     436         330 :                         backends_out[num_backends_out] = NULL;
     437             :                 }
     438             :         }
     439         330 :         return backends_out;
     440             : }
     441             : 
     442             : /**
     443             :  * Return a unique list of security subsystems from those specified in
     444             :  * the OID list.  That is, where two OIDs refer to the same module,
     445             :  * return that module only once.
     446             :  *
     447             :  * Use the list of enabled GENSEC mechanisms from the credentials
     448             :  * attached to the gensec_security, and return in our preferred order.
     449             :  */
     450             : 
     451      207109 : _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
     452             :                                         struct gensec_security *gensec_security,
     453             :                                         TALLOC_CTX *mem_ctx,
     454             :                                         const char * const *oid_strings,
     455             :                                         const char *skip)
     456             : {
     457        3704 :         struct gensec_security_ops_wrapper *backends_out;
     458        3704 :         const struct gensec_security_ops **backends;
     459        3704 :         int i, j, k, oid_idx;
     460      207109 :         int num_backends_out = 0;
     461             : 
     462      207109 :         if (!oid_strings) {
     463           0 :                 return NULL;
     464             :         }
     465             : 
     466      207109 :         backends = gensec_security_mechs(gensec_security, gensec_security);
     467             : 
     468      207109 :         backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
     469      207109 :         if (!backends_out) {
     470           0 :                 return NULL;
     471             :         }
     472      207109 :         backends_out[0].op = NULL;
     473      207109 :         backends_out[0].oid = NULL;
     474             : 
     475             :         /* Find backends in our preferred order, by walking our list,
     476             :          * then looking in the supplied list */
     477     1891509 :         for (i=0; backends && backends[i]; i++) {
     478     1684400 :                 if (!backends[i]->oid) {
     479     1150794 :                         continue;
     480             :                 }
     481     1694103 :                 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
     482     1160497 :                         if (strcmp(oid_strings[oid_idx], skip) == 0) {
     483           0 :                                 continue;
     484             :                         }
     485             : 
     486     2659386 :                         for (j=0; backends[i]->oid[j]; j++) {
     487     1526855 :                                 if (!backends[i]->oid[j] ||
     488     1498889 :                                     !(strcmp(backends[i]->oid[j],
     489     1461199 :                                             oid_strings[oid_idx]) == 0)) {
     490     1080320 :                                         continue;
     491             :                                 }
     492             : 
     493      517279 :                                 for (k=0; backends_out[k].op; k++) {
     494      211464 :                                         if (backends_out[k].op == backends[i]) {
     495      109522 :                                                 break;
     496             :                                         }
     497             :                                 }
     498             : 
     499      418569 :                                 if (k < num_backends_out) {
     500             :                                         /* already in there */
     501      112754 :                                         continue;
     502             :                                 }
     503             : 
     504      305815 :                                 backends_out = talloc_realloc(mem_ctx, backends_out,
     505             :                                                               struct gensec_security_ops_wrapper,
     506             :                                                               num_backends_out + 2);
     507      305815 :                                 if (!backends_out) {
     508           0 :                                         return NULL;
     509             :                                 }
     510             : 
     511      305815 :                                 backends_out[num_backends_out].op = backends[i];
     512      305815 :                                 backends_out[num_backends_out].oid = backends[i]->oid[j];
     513      305815 :                                 num_backends_out++;
     514      305815 :                                 backends_out[num_backends_out].op = NULL;
     515      305815 :                                 backends_out[num_backends_out].oid = NULL;
     516             :                         }
     517             :                 }
     518             :         }
     519      203405 :         return backends_out;
     520             : }
     521             : 
     522             : /**
     523             :  * Return OIDS from the security subsystems listed
     524             :  */
     525             : 
     526      134422 : static const char **gensec_security_oids_from_ops(
     527             :         struct gensec_security *gensec_security,
     528             :         TALLOC_CTX *mem_ctx,
     529             :         const struct gensec_security_ops * const *ops,
     530             :         const char *skip)
     531             : {
     532        2651 :         int i;
     533      134422 :         int j = 0;
     534        2651 :         int k;
     535        2651 :         const char **oid_list;
     536      134422 :         if (!ops) {
     537           0 :                 return NULL;
     538             :         }
     539      134422 :         oid_list = talloc_array(mem_ctx, const char *, 1);
     540      134422 :         if (!oid_list) {
     541           0 :                 return NULL;
     542             :         }
     543             : 
     544     1171533 :         for (i=0; ops && ops[i]; i++) {
     545     1037111 :                 if (!ops[i]->oid) {
     546      694947 :                         continue;
     547             :                 }
     548             : 
     549      765137 :                 for (k = 0; ops[i]->oid[k]; k++) {
     550      422973 :                         if (skip && strcmp(skip, ops[i]->oid[k])==0) {
     551             :                         } else {
     552      288551 :                                 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
     553      288551 :                                 if (!oid_list) {
     554           0 :                                         return NULL;
     555             :                                 }
     556      288551 :                                 oid_list[j] = ops[i]->oid[k];
     557      288551 :                                 j++;
     558             :                         }
     559             :                 }
     560             :         }
     561      134422 :         oid_list[j] = NULL;
     562      134422 :         return oid_list;
     563             : }
     564             : 
     565             : 
     566             : /**
     567             :  * Return OIDS from the security subsystems listed
     568             :  */
     569             : 
     570       92460 : _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
     571             :                                 const struct gensec_security_ops_wrapper *wops)
     572             : {
     573        1520 :         int i;
     574       92460 :         int j = 0;
     575        1520 :         int k;
     576        1520 :         const char **oid_list;
     577       92460 :         if (!wops) {
     578           0 :                 return NULL;
     579             :         }
     580       92460 :         oid_list = talloc_array(mem_ctx, const char *, 1);
     581       92460 :         if (!oid_list) {
     582           0 :                 return NULL;
     583             :         }
     584             : 
     585      222044 :         for (i=0; wops[i].op; i++) {
     586      129584 :                 if (!wops[i].op->oid) {
     587           0 :                         continue;
     588             :                 }
     589             : 
     590      300061 :                 for (k = 0; wops[i].op->oid[k]; k++) {
     591      170477 :                         oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
     592      170477 :                         if (!oid_list) {
     593           0 :                                 return NULL;
     594             :                         }
     595      170477 :                         oid_list[j] = wops[i].op->oid[k];
     596      170477 :                         j++;
     597             :                 }
     598             :         }
     599       92460 :         oid_list[j] = NULL;
     600       92460 :         return oid_list;
     601             : }
     602             : 
     603             : 
     604             : /**
     605             :  * Return all the security subsystems currently enabled on a GENSEC context.
     606             :  *
     607             :  * This is taken from a list attached to the cli_credentials, and
     608             :  * skips the OID in 'skip'.  (Typically the SPNEGO OID)
     609             :  *
     610             :  */
     611             : 
     612      134422 : _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
     613             :                                            TALLOC_CTX *mem_ctx,
     614             :                                            const char *skip)
     615             : {
     616        2651 :         const struct gensec_security_ops **ops;
     617             : 
     618      134422 :         ops = gensec_security_mechs(gensec_security, mem_ctx);
     619             : 
     620      134422 :         return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
     621             : }
     622             : 
     623      551237 : static int gensec_security_destructor(struct gensec_security *gctx)
     624             : {
     625      551237 :         if (gctx->parent_security != NULL) {
     626         169 :                 if (gctx->parent_security->child_security == gctx) {
     627         169 :                         gctx->parent_security->child_security = NULL;
     628             :                 }
     629         169 :                 gctx->parent_security = NULL;
     630             :         }
     631             : 
     632      551237 :         if (gctx->child_security != NULL) {
     633      138636 :                 if (gctx->child_security->parent_security == gctx) {
     634      138636 :                         gctx->child_security->parent_security = NULL;
     635             :                 }
     636      138636 :                 gctx->child_security = NULL;
     637             :         }
     638             : 
     639      551237 :         return 0;
     640             : }
     641             : 
     642             : /**
     643             :   Start the GENSEC system, returning a context pointer.
     644             :   @param mem_ctx The parent TALLOC memory context.
     645             :   @param gensec_security Returned GENSEC context pointer.
     646             :   @note  The mem_ctx is only a parent and may be NULL.
     647             :   @note, the auth context is moved to be a referenced pointer of the
     648             :   @ gensec_security return
     649             : */
     650      316766 : static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
     651             :                              struct gensec_settings *settings,
     652             :                              struct auth4_context *auth_context,
     653             :                              struct gensec_security **gensec_security)
     654             : {
     655      316766 :         (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
     656      316766 :         NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
     657             : 
     658      316766 :         (*gensec_security)->max_update_size = 0;
     659             : 
     660      316766 :         SMB_ASSERT(settings->lp_ctx != NULL);
     661      316766 :         (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
     662             : 
     663             :         /* We need to reference this, not steal, as the caller may be
     664             :          * python, which won't like it if we steal it's object away
     665             :          * from it */
     666      316766 :         (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
     667             : 
     668      316766 :         talloc_set_destructor((*gensec_security), gensec_security_destructor);
     669      316766 :         return NT_STATUS_OK;
     670             : }
     671             : 
     672             : /**
     673             :  * Start a GENSEC subcontext, with a copy of the properties of the parent
     674             :  * @param mem_ctx The parent TALLOC memory context.
     675             :  * @param parent The parent GENSEC context
     676             :  * @param gensec_security Returned GENSEC context pointer.
     677             :  * @note Used by SPNEGO in particular, for the actual implementation mechanism
     678             :  */
     679             : 
     680      235997 : _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
     681             :                                  struct gensec_security *parent,
     682             :                                  struct gensec_security **gensec_security)
     683             : {
     684      235997 :         if (parent->child_security != NULL) {
     685           0 :                 return NT_STATUS_INTERNAL_ERROR;
     686             :         }
     687             : 
     688      235997 :         (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
     689      235997 :         NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
     690             : 
     691      235997 :         (**gensec_security) = *parent;
     692      235997 :         (*gensec_security)->ops = NULL;
     693      235997 :         (*gensec_security)->private_data = NULL;
     694      235997 :         (*gensec_security)->update_busy_ptr = NULL;
     695             : 
     696      235997 :         (*gensec_security)->subcontext = true;
     697      235997 :         (*gensec_security)->want_features = parent->want_features;
     698      235997 :         (*gensec_security)->max_update_size = parent->max_update_size;
     699      235997 :         (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
     700      235997 :         (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
     701      235997 :         (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
     702      235997 :         (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
     703      235997 :         (*gensec_security)->channel_bindings = talloc_reference(*gensec_security, parent->channel_bindings);
     704             : 
     705      235997 :         talloc_set_destructor((*gensec_security), gensec_security_destructor);
     706      235997 :         return NT_STATUS_OK;
     707             : }
     708             : 
     709      139454 : _PUBLIC_ NTSTATUS gensec_child_ready(struct gensec_security *parent,
     710             :                                      struct gensec_security *child)
     711             : {
     712      139454 :         if (parent->child_security != NULL) {
     713           0 :                 return NT_STATUS_INTERNAL_ERROR;
     714             :         }
     715             : 
     716      139454 :         if (child->parent_security != NULL) {
     717           0 :                 return NT_STATUS_INTERNAL_ERROR;
     718             :         }
     719             : 
     720      139454 :         parent->child_security = child;
     721      139454 :         child->parent_security = parent;
     722      139454 :         return NT_STATUS_OK;
     723             : }
     724             : 
     725             : /**
     726             :   Start the GENSEC system, in client mode, returning a context pointer.
     727             :   @param mem_ctx The parent TALLOC memory context.
     728             :   @param gensec_security Returned GENSEC context pointer.
     729             :   @note  The mem_ctx is only a parent and may be NULL.
     730             : */
     731      125156 : _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
     732             :                              struct gensec_security **gensec_security,
     733             :                              struct gensec_settings *settings)
     734             : {
     735        1742 :         NTSTATUS status;
     736             : 
     737      125156 :         if (settings == NULL) {
     738           0 :                 DEBUG(0,("gensec_client_start: no settings given!\n"));
     739           0 :                 return NT_STATUS_INTERNAL_ERROR;
     740             :         }
     741             : 
     742      125156 :         status = gensec_start(mem_ctx, settings, NULL, gensec_security);
     743      125156 :         if (!NT_STATUS_IS_OK(status)) {
     744           0 :                 return status;
     745             :         }
     746      125156 :         (*gensec_security)->gensec_role = GENSEC_CLIENT;
     747             : 
     748      125156 :         return status;
     749             : }
     750             : 
     751             : 
     752             : 
     753             : /**
     754             :   Start the GENSEC system, in server mode, returning a context pointer.
     755             :   @param mem_ctx The parent TALLOC memory context.
     756             :   @param gensec_security Returned GENSEC context pointer.
     757             :   @note  The mem_ctx is only a parent and may be NULL.
     758             : */
     759      191610 : _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
     760             :                                       struct gensec_settings *settings,
     761             :                                       struct auth4_context *auth_context,
     762             :                                       struct gensec_security **gensec_security)
     763             : {
     764        2921 :         NTSTATUS status;
     765             : 
     766      191610 :         if (!settings) {
     767           0 :                 DEBUG(0,("gensec_server_start: no settings given!\n"));
     768           0 :                 return NT_STATUS_INTERNAL_ERROR;
     769             :         }
     770             : 
     771      191610 :         status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
     772      191610 :         if (!NT_STATUS_IS_OK(status)) {
     773           0 :                 return status;
     774             :         }
     775      191610 :         (*gensec_security)->gensec_role = GENSEC_SERVER;
     776             : 
     777      191610 :         return status;
     778             : }
     779             : 
     780      452383 : static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
     781             : {
     782        8072 :         NTSTATUS status;
     783             : 
     784             :         /*
     785             :          * Callers sometimes just reuse a context, we should
     786             :          * clear the internal state before starting it again.
     787             :          */
     788      452383 :         talloc_unlink(gensec_security, gensec_security->private_data);
     789      452383 :         gensec_security->private_data = NULL;
     790             : 
     791      452383 :         if (gensec_security->child_security != NULL) {
     792             :                 /*
     793             :                  * The talloc_unlink(.., gensec_security->private_data)
     794             :                  * should have cleared this via
     795             :                  * gensec_security_destructor().
     796             :                  */
     797           0 :                 return NT_STATUS_INTERNAL_ERROR;
     798             :         }
     799             : 
     800      452383 :         if (gensec_security->credentials) {
     801      452381 :                 const char *forced_mech = cli_credentials_get_forced_sasl_mech(gensec_security->credentials);
     802      452381 :                 if (forced_mech &&
     803           0 :                     (gensec_security->ops->sasl_name == NULL ||
     804           0 :                      strcasecmp(forced_mech, gensec_security->ops->sasl_name) != 0)) {
     805           0 :                         DEBUG(5, ("GENSEC mechanism %s (%s) skipped, as it "
     806             :                                   "did not match forced mechanism %s\n",
     807             :                                   gensec_security->ops->name,
     808             :                                   gensec_security->ops->sasl_name,
     809             :                                   forced_mech));
     810           0 :                         return NT_STATUS_INVALID_PARAMETER;
     811             :                 }
     812             :         }
     813      452383 :         DEBUG(5, ("Starting GENSEC %smechanism %s\n",
     814             :                   gensec_security->subcontext ? "sub" : "",
     815             :                   gensec_security->ops->name));
     816      452383 :         switch (gensec_security->gensec_role) {
     817      182109 :         case GENSEC_CLIENT:
     818      182109 :                 if (gensec_security->ops->client_start) {
     819      182109 :                         status = gensec_security->ops->client_start(gensec_security);
     820      182109 :                         if (!NT_STATUS_IS_OK(status)) {
     821       28146 :                                 DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
     822             :                                           gensec_security->ops->name, nt_errstr(status)));
     823             :                         }
     824      182109 :                         return status;
     825             :                 }
     826           0 :                 break;
     827      270274 :         case GENSEC_SERVER:
     828      270274 :                 if (gensec_security->ops->server_start) {
     829      270274 :                         status = gensec_security->ops->server_start(gensec_security);
     830      270274 :                         if (!NT_STATUS_IS_OK(status)) {
     831          10 :                                 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
     832             :                                           gensec_security->ops->name, nt_errstr(status)));
     833             :                         }
     834      270274 :                         return status;
     835             :                 }
     836           0 :                 break;
     837             :         }
     838           0 :         return NT_STATUS_INVALID_PARAMETER;
     839             : }
     840             : 
     841             : /**
     842             :  * Start a GENSEC sub-mechanism with a specified mechanism structure, used in SPNEGO
     843             :  *
     844             :  */
     845             : 
     846      236325 : NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
     847             :                                   const struct gensec_security_ops *ops)
     848             : {
     849      236325 :         gensec_security->ops = ops;
     850      236325 :         return gensec_start_mech(gensec_security);
     851             : }
     852             : 
     853             : 
     854             : /**
     855             :  * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
     856             :  * @param gensec_security GENSEC context pointer.
     857             :  * @param auth_type DCERPC auth type
     858             :  * @param auth_level DCERPC auth level
     859             :  */
     860             : 
     861       18943 : _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
     862             :                                        uint8_t auth_type, uint8_t auth_level)
     863             : {
     864       18943 :         gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type);
     865       18943 :         if (!gensec_security->ops) {
     866          39 :                 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
     867          39 :                 return NT_STATUS_INVALID_PARAMETER;
     868             :         }
     869       18904 :         gensec_security->dcerpc_auth_level = auth_level;
     870             :         /*
     871             :          * We need to reset sign/seal in order to reset it.
     872             :          * We may got some default features inherited by the credentials
     873             :          */
     874       18904 :         gensec_security->want_features &= ~GENSEC_FEATURE_SIGN;
     875       18904 :         gensec_security->want_features &= ~GENSEC_FEATURE_SEAL;
     876       18904 :         gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
     877       18904 :         gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
     878       18904 :         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
     879        6474 :                 if (gensec_security->gensec_role == GENSEC_CLIENT) {
     880        3313 :                         gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
     881             :                 }
     882       12430 :         } else if (auth_level == DCERPC_AUTH_LEVEL_PACKET) {
     883             :                 /*
     884             :                  * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
     885             :                  * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
     886             :                  */
     887         408 :                 if (gensec_security->gensec_role == GENSEC_CLIENT) {
     888         255 :                         gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
     889             :                 }
     890       12022 :         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
     891       10576 :                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
     892       10576 :                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
     893        1446 :         } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
     894             :                 /* Default features */
     895             :         } else {
     896           3 :                 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
     897             :                          auth_level));
     898           3 :                 return NT_STATUS_INVALID_PARAMETER;
     899             :         }
     900             : 
     901       18901 :         return gensec_start_mech(gensec_security);
     902             : }
     903             : 
     904         160 : _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
     905             : {
     906           0 :         const struct gensec_security_ops *ops;
     907         160 :         ops = gensec_security_by_auth_type(gensec_security, authtype);
     908         160 :         if (ops) {
     909         121 :                 return ops->name;
     910             :         }
     911          39 :         return NULL;
     912             : }
     913             : 
     914             : 
     915          76 : _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
     916             :                                                                                         const char *oid_string)
     917             : {
     918           0 :         const struct gensec_security_ops *ops;
     919          76 :         ops = gensec_security_by_oid(gensec_security, oid_string);
     920          76 :         if (ops) {
     921           4 :                 return ops->name;
     922             :         }
     923          72 :         return oid_string;
     924             : }
     925             : 
     926             : /**
     927             :  * Start a GENSEC sub-mechanism by OID, used in SPNEGO
     928             :  *
     929             :  * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
     930             :  *       well-known #define to hook it in.
     931             :  */
     932             : 
     933      142282 : _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
     934             :                                   const char *mech_oid)
     935             : {
     936      142282 :         SMB_ASSERT(gensec_security != NULL);
     937             : 
     938      142282 :         gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
     939      142282 :         if (!gensec_security->ops) {
     940          72 :                 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
     941          72 :                 return NT_STATUS_INVALID_PARAMETER;
     942             :         }
     943      142210 :         return gensec_start_mech(gensec_security);
     944             : }
     945             : 
     946             : /**
     947             :  * Start a GENSEC sub-mechanism by a well known SASL name
     948             :  *
     949             :  */
     950             : 
     951       53484 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
     952             :                                         const char *sasl_name)
     953             : {
     954       53484 :         gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
     955       53484 :         if (!gensec_security->ops) {
     956           2 :                 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
     957           2 :                 return NT_STATUS_INVALID_PARAMETER;
     958             :         }
     959       53482 :         return gensec_start_mech(gensec_security);
     960             : }
     961             : 
     962             : /**
     963             :  * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
     964             :  *
     965             :  */
     966             : 
     967         330 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
     968             :                                                  const char **sasl_names)
     969             : {
     970         330 :         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
     971         330 :         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
     972           0 :         const struct gensec_security_ops **ops;
     973           0 :         int i;
     974         330 :         if (!mem_ctx) {
     975           0 :                 return NT_STATUS_NO_MEMORY;
     976             :         }
     977         330 :         ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
     978         330 :         if (!ops || !*ops) {
     979           0 :                 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
     980             :                           str_list_join(mem_ctx,
     981             :                                         sasl_names, ' ')));
     982           0 :                 talloc_free(mem_ctx);
     983           0 :                 return NT_STATUS_INVALID_PARAMETER;
     984             :         }
     985         330 :         for (i=0; ops[i]; i++) {
     986         330 :                 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
     987         330 :                 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
     988         330 :                         break;
     989             :                 }
     990             :         }
     991         330 :         talloc_free(mem_ctx);
     992         330 :         return nt_status;
     993             : }
     994             : 
     995             : /**
     996             :  * Start a GENSEC sub-mechanism by an internal name
     997             :  *
     998             :  */
     999             : 
    1000        1469 : _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
    1001             :                                         const char *name)
    1002             : {
    1003        1469 :         gensec_security->ops = gensec_security_by_name(gensec_security, name);
    1004        1469 :         if (!gensec_security->ops) {
    1005           4 :                 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
    1006           4 :                 return NT_STATUS_INVALID_PARAMETER;
    1007             :         }
    1008        1465 :         return gensec_start_mech(gensec_security);
    1009             : }
    1010             : 
    1011             : /**
    1012             :  * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
    1013             :  *
    1014             :  */
    1015             : 
    1016      317104 : _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
    1017             : {
    1018      317104 :         gensec_security->credentials = talloc_reference(gensec_security, credentials);
    1019      317104 :         NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
    1020      317104 :         gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
    1021      317104 :         return NT_STATUS_OK;
    1022             : }
    1023             : 
    1024             : /*
    1025             :   register a GENSEC backend.
    1026             : 
    1027             :   The 'name' can be later used by other backends to find the operations
    1028             :   structure for this backend.
    1029             : */
    1030      770434 : _PUBLIC_ NTSTATUS gensec_register(TALLOC_CTX *ctx,
    1031             :                         const struct gensec_security_ops *ops)
    1032             : {
    1033      770434 :         if (gensec_security_by_name(NULL, ops->name) != NULL) {
    1034             :                 /* its already registered! */
    1035           0 :                 DEBUG(0,("GENSEC backend '%s' already registered\n",
    1036             :                          ops->name));
    1037           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
    1038             :         }
    1039             : 
    1040      770434 :         generic_security_ops = talloc_realloc(ctx,
    1041             :                                               generic_security_ops,
    1042             :                                               const struct gensec_security_ops *,
    1043             :                                               gensec_num_backends+2);
    1044      770434 :         if (!generic_security_ops) {
    1045           0 :                 return NT_STATUS_NO_MEMORY;
    1046             :         }
    1047             : 
    1048      770434 :         generic_security_ops[gensec_num_backends] = ops;
    1049      770434 :         gensec_num_backends++;
    1050      770434 :         generic_security_ops[gensec_num_backends] = NULL;
    1051             : 
    1052      770434 :         DEBUG(3,("GENSEC backend '%s' registered\n",
    1053             :                  ops->name));
    1054             : 
    1055      770434 :         return NT_STATUS_OK;
    1056             : }
    1057             : 
    1058             : /*
    1059             :   return the GENSEC interface version, and the size of some critical types
    1060             :   This can be used by backends to either detect compilation errors, or provide
    1061             :   multiple implementations for different smbd compilation options in one module
    1062             : */
    1063           0 : _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
    1064             : {
    1065           0 :         static const struct gensec_critical_sizes critical_sizes = {
    1066             :                 GENSEC_INTERFACE_VERSION,
    1067             :                 sizeof(struct gensec_security_ops),
    1068             :                 sizeof(struct gensec_security),
    1069             :         };
    1070             : 
    1071           0 :         return &critical_sizes;
    1072             : }
    1073             : 
    1074     1676482 : static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
    1075     1676482 :         return NUMERIC_CMP((*gs2)->priority, (*gs1)->priority);
    1076             : }
    1077             : 
    1078      179976 : int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
    1079             : {
    1080      179976 :         return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
    1081             : }
    1082             : 
    1083     1702296 : bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
    1084             : {
    1085     1702296 :         return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
    1086             : }
    1087             : 
    1088             : /*
    1089             :   initialise the GENSEC subsystem
    1090             : */
    1091      222365 : _PUBLIC_ NTSTATUS gensec_init(void)
    1092             : {
    1093        2737 :         static bool initialized = false;
    1094             : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
    1095             : #ifdef STATIC_gensec_MODULES
    1096        2737 :         STATIC_gensec_MODULES_PROTO;
    1097      222365 :         init_module_fn static_init[] = { STATIC_gensec_MODULES };
    1098             : #else
    1099             :         init_module_fn *static_init = NULL;
    1100             : #endif
    1101        2737 :         init_module_fn *shared_init;
    1102             : 
    1103      222365 :         if (initialized) return NT_STATUS_OK;
    1104       61098 :         initialized = true;
    1105             : 
    1106       61098 :         shared_init = load_samba_modules(NULL, "gensec");
    1107             : 
    1108       61098 :         run_init_functions(NULL, static_init);
    1109       61098 :         run_init_functions(NULL, shared_init);
    1110             : 
    1111       61098 :         talloc_free(shared_init);
    1112             : 
    1113       61098 :         TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
    1114             : 
    1115       61098 :         return NT_STATUS_OK;
    1116             : }

Generated by: LCOV version 1.14