LCOV - code coverage report
Current view: top level - source3/libads - sasl.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 213 331 64.4 %
Date: 2024-05-31 13:13:24 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    ads sasl code
       4             :    Copyright (C) Andrew Tridgell 2001
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "auth/credentials/credentials.h"
      22             : #include "auth/gensec/gensec.h"
      23             : #include "auth_generic.h"
      24             : #include "ads.h"
      25             : #include "smb_krb5.h"
      26             : #include "system/gssapi.h"
      27             : #include "lib/param/param.h"
      28             : #include "lib/util/asn1.h"
      29             : 
      30          54 : NTSTATUS ads_simple_creds(TALLOC_CTX *mem_ctx,
      31             :                           const char *account_domain,
      32             :                           const char *account_name,
      33             :                           const char *password,
      34             :                           struct cli_credentials **_creds)
      35             : {
      36          54 :         TALLOC_CTX *frame = talloc_stackframe();
      37          54 :         struct cli_credentials *creds = NULL;
      38          54 :         struct loadparm_context *lp_ctx = NULL;
      39           0 :         bool ok;
      40             : 
      41          54 :         lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
      42          54 :         if (lp_ctx == NULL) {
      43           0 :                 DBG_ERR("loadparm_init_s3 failed\n");
      44           0 :                 TALLOC_FREE(frame);
      45           0 :                 return NT_STATUS_INVALID_SERVER_STATE;
      46             :         }
      47             : 
      48          54 :         creds = cli_credentials_init(mem_ctx);
      49          54 :         if (creds == NULL) {
      50           0 :                 TALLOC_FREE(frame);
      51           0 :                 return NT_STATUS_NO_MEMORY;
      52             :         }
      53          54 :         talloc_steal(frame, creds);
      54             : 
      55          54 :         ok = cli_credentials_guess(creds, lp_ctx);
      56          54 :         if (!ok) {
      57           0 :                 TALLOC_FREE(frame);
      58           0 :                 return NT_STATUS_INTERNAL_ERROR;
      59             :         }
      60             : 
      61          54 :         if (account_domain != NULL && account_domain[0] != '\0') {
      62          54 :                 ok = cli_credentials_set_domain(creds,
      63             :                                                 account_domain,
      64             :                                                 CRED_SPECIFIED);
      65          54 :                 if (!ok) {
      66           0 :                         TALLOC_FREE(frame);
      67           0 :                         return NT_STATUS_NO_MEMORY;
      68             :                 }
      69             :         }
      70          54 :         if (password != NULL) {
      71          54 :                 ok = cli_credentials_set_password(creds,
      72             :                                                   password,
      73             :                                                   CRED_SPECIFIED);
      74          54 :                 if (!ok) {
      75           0 :                         TALLOC_FREE(frame);
      76           0 :                         return NT_STATUS_NO_MEMORY;
      77             :                 }
      78             :         }
      79             : 
      80          54 :         cli_credentials_parse_string(creds,
      81             :                                      account_name,
      82             :                                      CRED_SPECIFIED);
      83             : 
      84          54 :         *_creds = talloc_move(mem_ctx, &creds);
      85          54 :         TALLOC_FREE(frame);
      86          54 :         return NT_STATUS_OK;
      87             : }
      88             : 
      89             : #ifdef HAVE_LDAP
      90             : 
      91        1602 : static ADS_STATUS ads_sasl_gensec_wrap(struct ads_saslwrap *wrap,
      92             :                                        uint8_t *buf, uint32_t len)
      93             : {
      94           0 :         struct gensec_security *gensec_security =
      95        1602 :                 talloc_get_type_abort(wrap->wrap_private_data,
      96             :                 struct gensec_security);
      97           0 :         NTSTATUS nt_status;
      98           0 :         DATA_BLOB unwrapped, wrapped;
      99        1602 :         TALLOC_CTX *frame = talloc_stackframe();
     100             : 
     101        1602 :         unwrapped = data_blob_const(buf, len);
     102             : 
     103        1602 :         nt_status = gensec_wrap(gensec_security, frame, &unwrapped, &wrapped);
     104        1602 :         if (!NT_STATUS_IS_OK(nt_status)) {
     105           0 :                 TALLOC_FREE(frame);
     106           0 :                 return ADS_ERROR_NT(nt_status);
     107             :         }
     108             : 
     109        1602 :         if ((wrap->out.size - 4) < wrapped.length) {
     110           0 :                 TALLOC_FREE(frame);
     111           0 :                 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
     112             :         }
     113             : 
     114             :         /* copy the wrapped blob to the right location */
     115        1602 :         memcpy(wrap->out.buf + 4, wrapped.data, wrapped.length);
     116             : 
     117             :         /* set how many bytes must be written to the underlying socket */
     118        1602 :         wrap->out.left = 4 + wrapped.length;
     119             : 
     120        1602 :         TALLOC_FREE(frame);
     121             : 
     122        1602 :         return ADS_SUCCESS;
     123             : }
     124             : 
     125        1297 : static ADS_STATUS ads_sasl_gensec_unwrap(struct ads_saslwrap *wrap)
     126             : {
     127           0 :         struct gensec_security *gensec_security =
     128        1297 :                 talloc_get_type_abort(wrap->wrap_private_data,
     129             :                 struct gensec_security);
     130           0 :         NTSTATUS nt_status;
     131           0 :         DATA_BLOB unwrapped, wrapped;
     132        1297 :         TALLOC_CTX *frame = talloc_stackframe();
     133             : 
     134        1297 :         wrapped = data_blob_const(wrap->in.buf + 4, wrap->in.ofs - 4);
     135             : 
     136        1297 :         nt_status = gensec_unwrap(gensec_security, frame, &wrapped, &unwrapped);
     137        1297 :         if (!NT_STATUS_IS_OK(nt_status)) {
     138           0 :                 TALLOC_FREE(frame);
     139           0 :                 return ADS_ERROR_NT(nt_status);
     140             :         }
     141             : 
     142        1297 :         if (wrapped.length < unwrapped.length) {
     143           0 :                 TALLOC_FREE(frame);
     144           0 :                 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
     145             :         }
     146             : 
     147             :         /* copy the wrapped blob to the right location */
     148        1297 :         memcpy(wrap->in.buf + 4, unwrapped.data, unwrapped.length);
     149             : 
     150             :         /* set how many bytes must be written to the underlying socket */
     151        1297 :         wrap->in.left        = unwrapped.length;
     152        1297 :         wrap->in.ofs = 4;
     153             : 
     154        1297 :         TALLOC_FREE(frame);
     155             : 
     156        1297 :         return ADS_SUCCESS;
     157             : }
     158             : 
     159         305 : static void ads_sasl_gensec_disconnect(struct ads_saslwrap *wrap)
     160             : {
     161           0 :         struct gensec_security *gensec_security =
     162         305 :                 talloc_get_type_abort(wrap->wrap_private_data,
     163             :                 struct gensec_security);
     164             : 
     165         305 :         TALLOC_FREE(gensec_security);
     166             : 
     167         305 :         wrap->wrap_ops = NULL;
     168         305 :         wrap->wrap_private_data = NULL;
     169         305 : }
     170             : 
     171             : static const struct ads_saslwrap_ops ads_sasl_gensec_ops = {
     172             :         .name           = "gensec",
     173             :         .wrap           = ads_sasl_gensec_wrap,
     174             :         .unwrap         = ads_sasl_gensec_unwrap,
     175             :         .disconnect     = ads_sasl_gensec_disconnect
     176             : };
     177             : 
     178             : /*
     179             :    perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
     180             :    we fit on one socket??)
     181             : */
     182         330 : static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
     183             :                                 struct cli_credentials *creds,
     184             :                                 const char *target_service,
     185             :                                 const char *target_hostname)
     186             : {
     187         330 :         DATA_BLOB blob_in = data_blob_null;
     188         330 :         DATA_BLOB blob_out = data_blob_null;
     189           0 :         int rc;
     190           0 :         NTSTATUS nt_status;
     191           0 :         ADS_STATUS status;
     192           0 :         struct auth_generic_state *auth_generic_state;
     193         330 :         const char *sasl = "GSS-SPNEGO";
     194         330 :         const char *sasl_list[] = { sasl, NULL };
     195         330 :         struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
     196         330 :         const DATA_BLOB *tls_cb = NULL;
     197             : 
     198         330 :         nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
     199         330 :         if (!NT_STATUS_IS_OK(nt_status)) {
     200           0 :                 return ADS_ERROR_NT(nt_status);
     201             :         }
     202             : 
     203         330 :         if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_creds(auth_generic_state, creds))) {
     204           0 :                 return ADS_ERROR_NT(nt_status);
     205             :         }
     206             : 
     207         330 :         if (target_service != NULL) {
     208         330 :                 nt_status = gensec_set_target_service(
     209         330 :                                         auth_generic_state->gensec_security,
     210             :                                         target_service);
     211         330 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     212           0 :                         return ADS_ERROR_NT(nt_status);
     213             :                 }
     214             :         }
     215             : 
     216         330 :         if (target_hostname != NULL) {
     217         330 :                 nt_status = gensec_set_target_hostname(
     218         330 :                                         auth_generic_state->gensec_security,
     219             :                                         target_hostname);
     220         330 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     221           0 :                         return ADS_ERROR_NT(nt_status);
     222             :                 }
     223             :         }
     224             : 
     225         330 :         tls_cb = ads_tls_channel_bindings(&ads->ldap_tls_data);
     226         330 :         if (tls_cb != NULL) {
     227          24 :                 uint32_t initiator_addrtype = 0;
     228          24 :                 const DATA_BLOB *initiator_address = NULL;
     229          24 :                 uint32_t acceptor_addrtype = 0;
     230          24 :                 const DATA_BLOB *acceptor_address = NULL;
     231          24 :                 const DATA_BLOB *application_data = tls_cb;
     232             : 
     233          24 :                 nt_status = gensec_set_channel_bindings(auth_generic_state->gensec_security,
     234             :                                                         initiator_addrtype,
     235             :                                                         initiator_address,
     236             :                                                         acceptor_addrtype,
     237             :                                                         acceptor_address,
     238             :                                                         application_data);
     239          24 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     240           0 :                         DBG_WARNING("Failed to set GENSEC channel bindings: %s\n",
     241             :                                     nt_errstr(nt_status));
     242           0 :                         return ADS_ERROR_NT(nt_status);
     243             :                 }
     244             :         }
     245             : 
     246         330 :         switch (wrap->wrap_type) {
     247         306 :         case ADS_SASLWRAP_TYPE_SEAL:
     248         306 :                 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
     249         306 :                 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
     250         306 :                 break;
     251           0 :         case ADS_SASLWRAP_TYPE_SIGN:
     252           0 :                 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
     253           0 :                         gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
     254             :                 } else {
     255             :                         /*
     256             :                          * windows servers are broken with sign only,
     257             :                          * so we let the NTLMSSP backend to seal here,
     258             :                          * via GENSEC_FEATURE_LDAP_STYLE.
     259             :                          */
     260           0 :                         gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
     261           0 :                         gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
     262             :                 }
     263           0 :                 break;
     264          24 :         case ADS_SASLWRAP_TYPE_PLAIN:
     265          24 :                 break;
     266             :         }
     267             : 
     268         330 :         nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
     269             :                                                       sasl_list);
     270         330 :         if (!NT_STATUS_IS_OK(nt_status)) {
     271           0 :                 return ADS_ERROR_NT(nt_status);
     272             :         }
     273             : 
     274         330 :         rc = LDAP_SASL_BIND_IN_PROGRESS;
     275         330 :         blob_in = data_blob_null;
     276         330 :         blob_out = data_blob_null;
     277             : 
     278         334 :         while (true) {
     279         664 :                 struct berval cred, *scred = NULL;
     280             : 
     281         664 :                 nt_status = gensec_update(auth_generic_state->gensec_security,
     282             :                                           talloc_tos(), blob_in, &blob_out);
     283         664 :                 data_blob_free(&blob_in);
     284         664 :                 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
     285         330 :                     && !NT_STATUS_IS_OK(nt_status))
     286             :                 {
     287           1 :                         TALLOC_FREE(auth_generic_state);
     288           1 :                         data_blob_free(&blob_out);
     289           1 :                         return ADS_ERROR_NT(nt_status);
     290             :                 }
     291             : 
     292         663 :                 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
     293         329 :                         break;
     294             :                 }
     295             : 
     296         334 :                 cred.bv_val = (char *)blob_out.data;
     297         334 :                 cred.bv_len = blob_out.length;
     298         334 :                 scred = NULL;
     299         334 :                 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
     300         334 :                 data_blob_free(&blob_out);
     301         334 :                 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
     302           0 :                         if (scred) {
     303           0 :                                 ber_bvfree(scred);
     304             :                         }
     305             : 
     306           0 :                         TALLOC_FREE(auth_generic_state);
     307           0 :                         return ADS_ERROR(rc);
     308             :                 }
     309         334 :                 if (scred) {
     310         334 :                         blob_in = data_blob_talloc(talloc_tos(),
     311             :                                                    scred->bv_val,
     312             :                                                    scred->bv_len);
     313         334 :                         if (blob_in.length != scred->bv_len) {
     314           0 :                                 ber_bvfree(scred);
     315           0 :                                 TALLOC_FREE(auth_generic_state);
     316           0 :                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     317             :                         }
     318         334 :                         ber_bvfree(scred);
     319             :                 } else {
     320           0 :                         blob_in = data_blob_null;
     321             :                 }
     322         334 :                 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
     323           0 :                         break;
     324             :                 }
     325             :         }
     326             : 
     327         329 :         data_blob_free(&blob_in);
     328         329 :         data_blob_free(&blob_out);
     329             : 
     330         329 :         if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
     331           0 :                 bool ok;
     332             : 
     333         305 :                 ok = gensec_have_feature(auth_generic_state->gensec_security,
     334             :                                          GENSEC_FEATURE_SEAL);
     335         305 :                 if (!ok) {
     336           0 :                         DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
     337           0 :                         TALLOC_FREE(auth_generic_state);
     338           0 :                         return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
     339             :                 }
     340             : 
     341         305 :                 ok = gensec_have_feature(auth_generic_state->gensec_security,
     342             :                                          GENSEC_FEATURE_SIGN);
     343         305 :                 if (!ok) {
     344           0 :                         DEBUG(0,("The gensec feature signing request, but unavailable\n"));
     345           0 :                         TALLOC_FREE(auth_generic_state);
     346           0 :                         return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
     347             :                 }
     348             : 
     349          24 :         } else if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SIGN) {
     350           0 :                 bool ok;
     351             : 
     352           0 :                 ok = gensec_have_feature(auth_generic_state->gensec_security,
     353             :                                          GENSEC_FEATURE_SIGN);
     354           0 :                 if (!ok) {
     355           0 :                         DEBUG(0,("The gensec feature signing request, but unavailable\n"));
     356           0 :                         TALLOC_FREE(auth_generic_state);
     357           0 :                         return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
     358             :                 }
     359             :         }
     360             : 
     361         329 :         ads->auth.expire_time = gensec_expire_time(auth_generic_state->gensec_security);
     362             : 
     363         329 :         if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
     364           0 :                 size_t max_wrapped =
     365         305 :                         gensec_max_wrapped_size(auth_generic_state->gensec_security);
     366         305 :                 wrap->out.max_unwrapped =
     367         305 :                         gensec_max_input_size(auth_generic_state->gensec_security);
     368             : 
     369         305 :                 wrap->out.sig_size = max_wrapped - wrap->out.max_unwrapped;
     370             :                 /*
     371             :                  * Note that we have to truncate this to 0x2C
     372             :                  * (taken from a capture with LDAP unbind), as the
     373             :                  * signature size is not constant for Kerberos with
     374             :                  * arcfour-hmac-md5.
     375             :                  */
     376         305 :                 wrap->in.min_wrapped = MIN(wrap->out.sig_size, 0x2C);
     377         305 :                 wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
     378         305 :                 status = ads_setup_sasl_wrapping(wrap, ads->ldap.ld,
     379             :                                                  &ads_sasl_gensec_ops,
     380         305 :                                                  auth_generic_state->gensec_security);
     381         305 :                 if (!ADS_ERR_OK(status)) {
     382           0 :                         DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
     383             :                                 ads_errstr(status)));
     384           0 :                         TALLOC_FREE(auth_generic_state);
     385           0 :                         return status;
     386             :                 }
     387             :                 /* Only keep the gensec_security element around long-term */
     388         305 :                 talloc_steal(NULL, auth_generic_state->gensec_security);
     389             :         }
     390         329 :         TALLOC_FREE(auth_generic_state);
     391             : 
     392         329 :         return ADS_ERROR(rc);
     393             : }
     394             : 
     395             : #ifdef HAVE_KRB5
     396             : struct ads_service_principal {
     397             :         char *service;
     398             :         char *hostname;
     399             :         char *string;
     400             : };
     401             : 
     402         330 : static void ads_free_service_principal(struct ads_service_principal *p)
     403             : {
     404         330 :         SAFE_FREE(p->service);
     405         330 :         SAFE_FREE(p->hostname);
     406         330 :         SAFE_FREE(p->string);
     407         330 :         ZERO_STRUCTP(p);
     408         330 : }
     409             : 
     410         330 : static ADS_STATUS ads_guess_target(ADS_STRUCT *ads,
     411             :                                    char **service,
     412             :                                    char **hostname,
     413             :                                    char **principal)
     414             : {
     415         330 :         ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
     416         330 :         char *princ = NULL;
     417           0 :         TALLOC_CTX *frame;
     418         330 :         char *server = NULL;
     419         330 :         char *realm = NULL;
     420           0 :         int rc;
     421             : 
     422         330 :         frame = talloc_stackframe();
     423         330 :         if (frame == NULL) {
     424           0 :                 return ADS_ERROR(LDAP_NO_MEMORY);
     425             :         }
     426             : 
     427         330 :         if (ads->server.realm && ads->server.ldap_server) {
     428         148 :                 server = strlower_talloc(frame, ads->server.ldap_server);
     429         148 :                 if (server == NULL) {
     430           0 :                         goto out;
     431             :                 }
     432             : 
     433         148 :                 realm = strupper_talloc(frame, ads->server.realm);
     434         148 :                 if (realm == NULL) {
     435           0 :                         goto out;
     436             :                 }
     437             : 
     438             :                 /*
     439             :                  * If we got a name which is bigger than a NetBIOS name,
     440             :                  * but isn't a FQDN, create one.
     441             :                  */
     442         148 :                 if (strlen(server) > 15 && strstr(server, ".") == NULL) {
     443           0 :                         char *dnsdomain;
     444             : 
     445           0 :                         dnsdomain = strlower_talloc(frame, ads->server.realm);
     446           0 :                         if (dnsdomain == NULL) {
     447           0 :                                 goto out;
     448             :                         }
     449             : 
     450           0 :                         server = talloc_asprintf(frame,
     451             :                                                  "%s.%s",
     452             :                                                  server, dnsdomain);
     453           0 :                         if (server == NULL) {
     454           0 :                                 goto out;
     455             :                         }
     456             :                 }
     457         182 :         } else if (ads->config.realm && ads->config.ldap_server_name) {
     458         182 :                 server = strlower_talloc(frame, ads->config.ldap_server_name);
     459         182 :                 if (server == NULL) {
     460           0 :                         goto out;
     461             :                 }
     462             : 
     463         182 :                 realm = strupper_talloc(frame, ads->config.realm);
     464         182 :                 if (realm == NULL) {
     465           0 :                         goto out;
     466             :                 }
     467             : 
     468             :                 /*
     469             :                  * If we got a name which is bigger than a NetBIOS name,
     470             :                  * but isn't a FQDN, create one.
     471             :                  */
     472         182 :                 if (strlen(server) > 15 && strstr(server, ".") == NULL) {
     473           0 :                         char *dnsdomain;
     474             : 
     475           0 :                         dnsdomain = strlower_talloc(frame, ads->server.realm);
     476           0 :                         if (dnsdomain == NULL) {
     477           0 :                                 goto out;
     478             :                         }
     479             : 
     480           0 :                         server = talloc_asprintf(frame,
     481             :                                                  "%s.%s",
     482             :                                                  server, dnsdomain);
     483           0 :                         if (server == NULL) {
     484           0 :                                 goto out;
     485             :                         }
     486             :                 }
     487             :         }
     488             : 
     489         330 :         if (server == NULL || realm == NULL) {
     490           0 :                 goto out;
     491             :         }
     492             : 
     493         330 :         *service = SMB_STRDUP("ldap");
     494         330 :         if (*service == NULL) {
     495           0 :                 status = ADS_ERROR(LDAP_PARAM_ERROR);
     496           0 :                 goto out;
     497             :         }
     498         330 :         *hostname = SMB_STRDUP(server);
     499         330 :         if (*hostname == NULL) {
     500           0 :                 SAFE_FREE(*service);
     501           0 :                 status = ADS_ERROR(LDAP_PARAM_ERROR);
     502           0 :                 goto out;
     503             :         }
     504         330 :         rc = asprintf(&princ, "ldap/%s@%s", server, realm);
     505         330 :         if (rc == -1 || princ == NULL) {
     506           0 :                 SAFE_FREE(*service);
     507           0 :                 SAFE_FREE(*hostname);
     508           0 :                 status = ADS_ERROR(LDAP_PARAM_ERROR);
     509           0 :                 goto out;
     510             :         }
     511             : 
     512         330 :         *principal = princ;
     513             : 
     514         330 :         status = ADS_SUCCESS;
     515         330 : out:
     516         330 :         TALLOC_FREE(frame);
     517         330 :         return status;
     518             : }
     519             : 
     520         330 : static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
     521             :                                                  struct ads_service_principal *p)
     522             : {
     523           0 :         ADS_STATUS status;
     524             : 
     525         330 :         ZERO_STRUCTP(p);
     526             : 
     527         330 :         status = ads_guess_target(ads,
     528             :                                   &p->service,
     529             :                                   &p->hostname,
     530             :                                   &p->string);
     531         330 :         if (!ADS_ERR_OK(status)) {
     532           0 :                 return status;
     533             :         }
     534             : 
     535         330 :         return ADS_SUCCESS;
     536             : }
     537             : 
     538             : #endif /* HAVE_KRB5 */
     539             : 
     540             : /*
     541             :    this performs a SASL/SPNEGO bind
     542             : */
     543         330 : static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads,
     544             :                                        struct cli_credentials *creds)
     545             : {
     546         330 :         TALLOC_CTX *frame = talloc_stackframe();
     547         330 :         struct ads_service_principal p = {0};
     548           0 :         ADS_STATUS status;
     549         330 :         const char *debug_username = NULL;
     550             : 
     551         330 :         status = ads_generate_service_principal(ads, &p);
     552         330 :         if (!ADS_ERR_OK(status)) {
     553           0 :                 goto done;
     554             :         }
     555             : 
     556         330 :         debug_username = cli_credentials_get_unparsed_name(creds, frame);
     557         330 :         if (debug_username == NULL) {
     558           0 :                 status = ADS_ERROR_SYSTEM(errno);
     559           0 :                 goto done;
     560             :         }
     561             : 
     562         330 :         status = ads_sasl_spnego_gensec_bind(ads,
     563             :                                              creds,
     564         330 :                                              p.service,
     565         330 :                                              p.hostname);
     566         330 :         if (!ADS_ERR_OK(status)) {
     567           1 :                 DBG_WARNING("ads_sasl_spnego_gensec_bind() failed "
     568             :                             "for %s/%s with user[%s]: %s\n",
     569             :                             p.service, p.hostname,
     570             :                             debug_username,
     571             :                             ads_errstr(status));
     572           1 :                 goto done;
     573             :         }
     574             : 
     575         329 : done:
     576         330 :         ads_free_service_principal(&p);
     577         330 :         TALLOC_FREE(frame);
     578         330 :         return status;
     579             : }
     580             : 
     581         330 : ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads, struct cli_credentials *creds)
     582             : {
     583           0 :         ADS_STATUS status;
     584         330 :         struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
     585         330 :         bool tls = false;
     586             : 
     587         330 :         if (ads->auth.flags & ADS_AUTH_SASL_LDAPS) {
     588          12 :                 tls = true;
     589          12 :                 wrap->wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
     590         318 :         } else if (ads->auth.flags & ADS_AUTH_SASL_STARTTLS) {
     591          12 :                 tls = true;
     592          12 :                 wrap->wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
     593         306 :         } else if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
     594         306 :                 wrap->wrap_type = ADS_SASLWRAP_TYPE_SEAL;
     595           0 :         } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
     596           0 :                 wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN;
     597             :         } else {
     598           0 :                 wrap->wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
     599             :         }
     600             : 
     601         330 :         if (tls) {
     602          24 :                 const DATA_BLOB *tls_cb = NULL;
     603             : 
     604          24 :                 tls_cb = ads_tls_channel_bindings(&ads->ldap_tls_data);
     605          24 :                 if (tls_cb == NULL) {
     606           0 :                         DBG_ERR("No TLS channel bindings available\n");
     607           0 :                         return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
     608             :                 }
     609             :         }
     610             : 
     611         330 : retry:
     612         330 :         status = ads_sasl_spnego_bind(ads, creds);
     613         330 :         if (status.error_type == ENUM_ADS_ERROR_LDAP &&
     614         329 :             status.err.rc == LDAP_STRONG_AUTH_REQUIRED &&
     615           0 :             !tls &&
     616           0 :             wrap->wrap_type == ADS_SASLWRAP_TYPE_PLAIN)
     617             :         {
     618           0 :                 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
     619             :                          "retrying with signing enabled\n"));
     620           0 :                 wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN;
     621           0 :                 goto retry;
     622             :         }
     623         330 :         return status;
     624             : }
     625             : 
     626             : #endif /* HAVE_LDAP */
     627             : 

Generated by: LCOV version 1.14