LCOV - code coverage report
Current view: top level - auth/credentials - credentials.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 616 848 72.6 %
Date: 2024-05-31 13:13:24 Functions: 62 75 82.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    User credentials handling
       5             : 
       6             :    Copyright (C) Jelmer Vernooij 2005
       7             :    Copyright (C) Tim Potter 2001
       8             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "lib/util/util_file.h"
      26             : #include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
      27             : #include "auth/credentials/credentials.h"
      28             : #include "auth/credentials/credentials_internal.h"
      29             : #include "auth/gensec/gensec.h"
      30             : #include "libcli/auth/libcli_auth.h"
      31             : #include "tevent.h"
      32             : #include "param/param.h"
      33             : #include "system/filesys.h"
      34             : #include "system/passwd.h"
      35             : 
      36             : /**
      37             :  * Create a new credentials structure
      38             :  * @param mem_ctx TALLOC_CTX parent for credentials structure
      39             :  */
      40      364957 : _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
      41             : {
      42      364957 :         struct cli_credentials *cred = talloc_zero(mem_ctx, struct cli_credentials);
      43      364957 :         if (cred == NULL) {
      44           0 :                 return cred;
      45             :         }
      46             : 
      47      364957 :         cred->winbind_separator = '\\';
      48             : 
      49      364957 :         cred->kerberos_state = CRED_USE_KERBEROS_DESIRED;
      50             : 
      51      364957 :         cred->signing_state = SMB_SIGNING_DEFAULT;
      52             : 
      53             :         /*
      54             :          * The default value of lpcfg_client_ipc_signing() is REQUIRED, so use
      55             :          * the same value here.
      56             :          */
      57      364957 :         cred->ipc_signing_state = SMB_SIGNING_REQUIRED;
      58      364957 :         cred->encryption_state = SMB_ENCRYPTION_DEFAULT;
      59             : 
      60      364957 :         return cred;
      61             : }
      62             : 
      63             : _PUBLIC_
      64       62376 : struct cli_credentials *cli_credentials_init_server(TALLOC_CTX *mem_ctx,
      65             :                                                     struct loadparm_context *lp_ctx)
      66             : {
      67       62376 :         struct cli_credentials *server_creds = NULL;
      68        2677 :         NTSTATUS status;
      69        2677 :         bool ok;
      70             : 
      71       62376 :         server_creds = cli_credentials_init(mem_ctx);
      72       62376 :         if (server_creds == NULL) {
      73           0 :                 return NULL;
      74             :         }
      75             : 
      76       62376 :         ok = cli_credentials_set_conf(server_creds, lp_ctx);
      77       62376 :         if (!ok) {
      78           0 :                 TALLOC_FREE(server_creds);
      79           0 :                 return NULL;
      80             :         }
      81             : 
      82       62376 :         status = cli_credentials_set_machine_account(server_creds, lp_ctx);
      83       62376 :         if (!NT_STATUS_IS_OK(status)) {
      84           2 :                 DEBUG(1, ("Failed to obtain server credentials: %s\n",
      85             :                           nt_errstr(status)));
      86           2 :                 TALLOC_FREE(server_creds);
      87           2 :                 return NULL;
      88             :         }
      89             : 
      90       59697 :         return server_creds;
      91             : }
      92             : 
      93           0 : _PUBLIC_ void cli_credentials_set_callback_data(struct cli_credentials *cred,
      94             :                                                 void *callback_data)
      95             : {
      96           0 :         cred->priv_data = callback_data;
      97           0 : }
      98             : 
      99           0 : _PUBLIC_ void *_cli_credentials_callback_data(struct cli_credentials *cred)
     100             : {
     101           0 :         return cred->priv_data;
     102             : }
     103             : 
     104             : /**
     105             :  * Create a new anonymous credential
     106             :  * @param mem_ctx TALLOC_CTX parent for credentials structure
     107             :  */
     108      121871 : _PUBLIC_ struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx)
     109             : {
     110        1909 :         struct cli_credentials *anon_credentials;
     111             : 
     112      121871 :         anon_credentials = cli_credentials_init(mem_ctx);
     113      121871 :         cli_credentials_set_anonymous(anon_credentials);
     114             : 
     115      121871 :         return anon_credentials;
     116             : }
     117             : 
     118      286147 : _PUBLIC_ bool cli_credentials_set_kerberos_state(struct cli_credentials *creds,
     119             :                                                  enum credentials_use_kerberos kerberos_state,
     120             :                                                  enum credentials_obtained obtained)
     121             : {
     122      286147 :         if (obtained >= creds->kerberos_state_obtained) {
     123      286146 :                 creds->kerberos_state = kerberos_state;
     124      286146 :                 creds->kerberos_state_obtained = obtained;
     125             : 
     126      286146 :                 return true;
     127             :         }
     128             : 
     129           0 :         return false;
     130             : }
     131             : 
     132           0 : _PUBLIC_ void cli_credentials_set_forced_sasl_mech(struct cli_credentials *creds,
     133             :                                                    const char *sasl_mech)
     134             : {
     135           0 :         TALLOC_FREE(creds->forced_sasl_mech);
     136           0 :         creds->forced_sasl_mech = talloc_strdup(creds, sasl_mech);
     137           0 : }
     138             : 
     139          80 : _PUBLIC_ void cli_credentials_set_krb_forwardable(struct cli_credentials *creds,
     140             :                                                   enum credentials_krb_forwardable krb_forwardable)
     141             : {
     142          80 :         creds->krb_forwardable = krb_forwardable;
     143          80 : }
     144             : 
     145      788485 : _PUBLIC_ enum credentials_use_kerberos cli_credentials_get_kerberos_state(struct cli_credentials *creds)
     146             : {
     147      788485 :         return creds->kerberos_state;
     148             : }
     149             : 
     150      420660 : _PUBLIC_ const char *cli_credentials_get_forced_sasl_mech(struct cli_credentials *creds)
     151             : {
     152      420660 :         return creds->forced_sasl_mech;
     153             : }
     154             : 
     155       15486 : _PUBLIC_ enum credentials_krb_forwardable cli_credentials_get_krb_forwardable(struct cli_credentials *creds)
     156             : {
     157       15486 :         return creds->krb_forwardable;
     158             : }
     159             : 
     160       44186 : _PUBLIC_ bool cli_credentials_set_gensec_features(struct cli_credentials *creds,
     161             :                                                   uint32_t gensec_features,
     162             :                                                   enum credentials_obtained obtained)
     163             : {
     164       44186 :         if (obtained >= creds->gensec_features_obtained) {
     165       44185 :                 creds->gensec_features_obtained = obtained;
     166       44185 :                 creds->gensec_features = gensec_features;
     167             : 
     168       44185 :                 return true;
     169             :         }
     170             : 
     171           0 :         return false;
     172             : }
     173             : 
     174      350398 : _PUBLIC_ uint32_t cli_credentials_get_gensec_features(struct cli_credentials *creds)
     175             : {
     176      350398 :         return creds->gensec_features;
     177             : }
     178             : 
     179             : /**
     180             :  * @brief Find out how the username was obtained.
     181             :  *
     182             :  * @param cred A credentials context.
     183             :  *
     184             :  * @return The obtained information for the username.
     185             :  */
     186             : _PUBLIC_ enum credentials_obtained
     187           1 : cli_credentials_get_username_obtained(struct cli_credentials *cred)
     188             : {
     189           1 :         return cred->username_obtained;
     190             : }
     191             : 
     192             : /**
     193             :  * Obtain the username for this credentials context.
     194             :  * @param cred credentials context
     195             :  * @retval The username set on this context.
     196             :  * @note Return value will never be NULL except by programmer error.
     197             :  */
     198     1594386 : _PUBLIC_ const char *cli_credentials_get_username(struct cli_credentials *cred)
     199             : {
     200     1594386 :         if (cred->machine_account_pending) {
     201           0 :                 cli_credentials_set_machine_account(cred,
     202             :                                         cred->machine_account_pending_lp_ctx);
     203             :         }
     204             : 
     205     1594386 :         if (cred->username_obtained == CRED_CALLBACK &&
     206           0 :             !cred->callback_running) {
     207           0 :                 cred->callback_running = true;
     208           0 :                 cred->username = cred->username_cb(cred);
     209           0 :                 cred->callback_running = false;
     210           0 :                 if (cred->username_obtained == CRED_CALLBACK) {
     211           0 :                         cred->username_obtained = CRED_CALLBACK_RESULT;
     212           0 :                         cli_credentials_invalidate_ccache(cred, cred->username_obtained);
     213             :                 }
     214             :         }
     215             : 
     216     1594386 :         return cred->username;
     217             : }
     218             : 
     219             : /**
     220             :  * @brief Obtain the username for this credentials context.
     221             :  *
     222             :  * @param[in]  cred  The credential context.
     223             :  *
     224             :  * @param[in]  obtained  A pointer to store the obtained information.
     225             :  *
     226             :  * return The user name or NULL if an error occurred.
     227             :  */
     228             : _PUBLIC_ const char *
     229       21915 : cli_credentials_get_username_and_obtained(struct cli_credentials *cred,
     230             :                                           enum credentials_obtained *obtained)
     231             : {
     232       21915 :         if (obtained != NULL) {
     233       21915 :                 *obtained = cred->username_obtained;
     234             :         }
     235             : 
     236       21915 :         return cli_credentials_get_username(cred);
     237             : }
     238             : 
     239      828610 : _PUBLIC_ bool cli_credentials_set_username(struct cli_credentials *cred,
     240             :                                   const char *val, enum credentials_obtained obtained)
     241             : {
     242      828610 :         if (obtained >= cred->username_obtained) {
     243      692549 :                 cred->username = talloc_strdup(cred, val);
     244      692549 :                 cred->username_obtained = obtained;
     245      692549 :                 cli_credentials_invalidate_ccache(cred, cred->username_obtained);
     246      692549 :                 return true;
     247             :         }
     248             : 
     249      135885 :         return false;
     250             : }
     251             : 
     252           0 : _PUBLIC_ bool cli_credentials_set_username_callback(struct cli_credentials *cred,
     253             :                                   const char *(*username_cb) (struct cli_credentials *))
     254             : {
     255           0 :         if (cred->username_obtained < CRED_CALLBACK) {
     256           0 :                 cred->username_cb = username_cb;
     257           0 :                 cred->username_obtained = CRED_CALLBACK;
     258           0 :                 return true;
     259             :         }
     260             : 
     261           0 :         return false;
     262             : }
     263             : 
     264         609 : _PUBLIC_ bool cli_credentials_set_bind_dn(struct cli_credentials *cred,
     265             :                                  const char *bind_dn)
     266             : {
     267         609 :         cred->bind_dn = talloc_strdup(cred, bind_dn);
     268         609 :         return true;
     269             : }
     270             : 
     271             : /**
     272             :  * Obtain the BIND DN for this credentials context.
     273             :  * @param cred credentials context
     274             :  * @retval The username set on this context.
     275             :  * @note Return value will be NULL if not specified explicitly
     276             :  */
     277       55445 : _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred)
     278             : {
     279       55445 :         return cred->bind_dn;
     280             : }
     281             : 
     282             : 
     283             : /**
     284             :  * @brief Find out how the principal was obtained.
     285             :  *
     286             :  * @param cred A credentials context.
     287             :  *
     288             :  * @return The obtained information for the principal.
     289             :  */
     290             : _PUBLIC_ enum credentials_obtained
     291        4441 : cli_credentials_get_principal_obtained(struct cli_credentials *cred)
     292             : {
     293        4441 :         if (cred->machine_account_pending) {
     294           0 :                 cli_credentials_set_machine_account(cred,
     295             :                                         cred->machine_account_pending_lp_ctx);
     296             :         }
     297             : 
     298        4441 :         if (cred->principal_obtained < cred->username_obtained
     299         355 :             || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
     300        4088 :                 const char *effective_username = NULL;
     301        4088 :                 const char *effective_realm = NULL;
     302           8 :                 enum credentials_obtained effective_obtained;
     303             : 
     304             :                 /*
     305             :                  * We don't want to trigger a callbacks in
     306             :                  * cli_credentials_get_username()
     307             :                  * cli_credentials_get_domain()
     308             :                  * nor
     309             :                  * cli_credentials_get_realm()
     310             :                  */
     311             : 
     312        4088 :                 effective_username = cred->username;
     313        4088 :                 if (effective_username == NULL || strlen(effective_username) == 0) {
     314           4 :                         return cred->username_obtained;
     315             :                 }
     316             : 
     317        4084 :                 if (cred->domain_obtained > cred->realm_obtained) {
     318        2589 :                         effective_realm = cred->domain;
     319        2589 :                         effective_obtained = MIN(cred->domain_obtained,
     320             :                                                  cred->username_obtained);
     321             :                 } else {
     322        1495 :                         effective_realm = cred->realm;
     323        1495 :                         effective_obtained = MIN(cred->realm_obtained,
     324             :                                                  cred->username_obtained);
     325             :                 }
     326             : 
     327        4084 :                 if (effective_realm == NULL || strlen(effective_realm) == 0) {
     328           0 :                         effective_realm = cred->domain;
     329           0 :                         effective_obtained = MIN(cred->domain_obtained,
     330             :                                                  cred->username_obtained);
     331             :                 }
     332             : 
     333        4084 :                 if (effective_realm != NULL && strlen(effective_realm) != 0) {
     334        4084 :                         return effective_obtained;
     335             :                 }
     336             :         }
     337             : 
     338         352 :         return cred->principal_obtained;
     339             : }
     340             : 
     341             : /**
     342             :  * Obtain the client principal for this credentials context.
     343             :  * @param cred credentials context
     344             :  * @retval The username set on this context.
     345             :  * @note Return value will never be NULL except by programmer error.
     346             :  */
     347      133106 : _PUBLIC_ char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
     348             : {
     349      133106 :         if (cred->machine_account_pending) {
     350           0 :                 cli_credentials_set_machine_account(cred,
     351             :                                         cred->machine_account_pending_lp_ctx);
     352             :         }
     353             : 
     354      133106 :         if (cred->principal_obtained == CRED_CALLBACK &&
     355           0 :             !cred->callback_running) {
     356           0 :                 cred->callback_running = true;
     357           0 :                 cred->principal = cred->principal_cb(cred);
     358           0 :                 cred->callback_running = false;
     359           0 :                 if (cred->principal_obtained == CRED_CALLBACK) {
     360           0 :                         cred->principal_obtained = CRED_CALLBACK_RESULT;
     361           0 :                         cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
     362             :                 }
     363             :         }
     364             : 
     365      133106 :         if (cred->principal_obtained < cred->username_obtained
     366       23376 :             || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
     367      109740 :                 const char *effective_username = NULL;
     368      109740 :                 const char *effective_realm = NULL;
     369        3380 :                 enum credentials_obtained effective_obtained;
     370             : 
     371      109740 :                 effective_username = cli_credentials_get_username(cred);
     372      109740 :                 if (effective_username == NULL || strlen(effective_username) == 0) {
     373           7 :                         *obtained = cred->username_obtained;
     374           7 :                         return NULL;
     375             :                 }
     376             : 
     377      109733 :                 if (cred->domain_obtained > cred->realm_obtained) {
     378       29957 :                         effective_realm = cli_credentials_get_domain(cred);
     379       29957 :                         effective_obtained = MIN(cred->domain_obtained,
     380             :                                                  cred->username_obtained);
     381             :                 } else {
     382       79776 :                         effective_realm = cli_credentials_get_realm(cred);
     383       79776 :                         effective_obtained = MIN(cred->realm_obtained,
     384             :                                                  cred->username_obtained);
     385             :                 }
     386             : 
     387      109733 :                 if (effective_realm == NULL || strlen(effective_realm) == 0) {
     388         249 :                         effective_realm = cli_credentials_get_domain(cred);
     389         249 :                         effective_obtained = MIN(cred->domain_obtained,
     390             :                                                  cred->username_obtained);
     391             :                 }
     392             : 
     393      109733 :                 if (effective_realm != NULL && strlen(effective_realm) != 0) {
     394      109574 :                         *obtained = effective_obtained;
     395      109574 :                         return talloc_asprintf(mem_ctx, "%s@%s",
     396             :                                                effective_username,
     397             :                                                effective_realm);
     398             :                 }
     399             :         }
     400       23525 :         *obtained = cred->principal_obtained;
     401       23525 :         return talloc_strdup(mem_ctx, cred->principal);
     402             : }
     403             : 
     404             : /**
     405             :  * Obtain the client principal for this credentials context.
     406             :  * @param cred credentials context
     407             :  * @retval The username set on this context.
     408             :  * @note Return value will never be NULL except by programmer error.
     409             :  */
     410       65463 : _PUBLIC_ char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
     411             : {
     412        1604 :         enum credentials_obtained obtained;
     413       65463 :         return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
     414             : }
     415             : 
     416      210744 : _PUBLIC_ bool cli_credentials_set_principal(struct cli_credentials *cred,
     417             :                                    const char *val,
     418             :                                    enum credentials_obtained obtained)
     419             : {
     420      210744 :         if (obtained >= cred->principal_obtained) {
     421      210719 :                 cred->principal = talloc_strdup(cred, val);
     422      210719 :                 if (cred->principal == NULL) {
     423      164058 :                         return false;
     424             :                 }
     425       44305 :                 cred->principal_obtained = obtained;
     426             : 
     427       44305 :                 cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
     428       44305 :                 return true;
     429             :         }
     430             : 
     431          25 :         return false;
     432             : }
     433             : 
     434             : /* Set a callback to get the principal.  This could be a popup dialog,
     435             :  * a terminal prompt or similar.  */
     436           0 : _PUBLIC_ bool cli_credentials_set_principal_callback(struct cli_credentials *cred,
     437             :                                   const char *(*principal_cb) (struct cli_credentials *))
     438             : {
     439           0 :         if (cred->principal_obtained < CRED_CALLBACK) {
     440           0 :                 cred->principal_cb = principal_cb;
     441           0 :                 cred->principal_obtained = CRED_CALLBACK;
     442           0 :                 return true;
     443             :         }
     444             : 
     445           0 :         return false;
     446             : }
     447             : 
     448             : /* Some of our tools are 'anonymous by default'.  This is a single
     449             :  * function to determine if authentication has been explicitly
     450             :  * requested */
     451             : 
     452       95433 : _PUBLIC_ bool cli_credentials_authentication_requested(struct cli_credentials *cred)
     453             : {
     454       95433 :         uint32_t gensec_features = 0;
     455             : 
     456       95433 :         if (cred->bind_dn) {
     457         446 :                 return true;
     458             :         }
     459             : 
     460             :         /*
     461             :          * If we forced the mech we clearly want authentication. E.g. to use
     462             :          * SASL/EXTERNAL which has no credentials.
     463             :          */
     464       94987 :         if (cred->forced_sasl_mech) {
     465           0 :                 return true;
     466             :         }
     467             : 
     468       94987 :         if (cli_credentials_is_anonymous(cred)){
     469         705 :                 return false;
     470             :         }
     471             : 
     472       94280 :         if (cred->principal_obtained >= CRED_SPECIFIED) {
     473       28760 :                 return true;
     474             :         }
     475       64969 :         if (cred->username_obtained >= CRED_SPECIFIED) {
     476       60019 :                 return true;
     477             :         }
     478             : 
     479        4316 :         if (cli_credentials_get_kerberos_state(cred) == CRED_USE_KERBEROS_REQUIRED) {
     480          24 :                 return true;
     481             :         }
     482             : 
     483        4292 :         gensec_features = cli_credentials_get_gensec_features(cred);
     484        4292 :         if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
     485           0 :                 return true;
     486             :         }
     487             : 
     488        4292 :         if (gensec_features & GENSEC_FEATURE_SIGN) {
     489           0 :                 return true;
     490             :         }
     491             : 
     492        4292 :         if (gensec_features & GENSEC_FEATURE_SEAL) {
     493           0 :                 return true;
     494             :         }
     495             : 
     496        4271 :         return false;
     497             : }
     498             : 
     499             : /**
     500             :  * Obtain the password for this credentials context.
     501             :  * @param cred credentials context
     502             :  * @retval If set, the cleartext password, otherwise NULL
     503             :  */
     504      158890 : _PUBLIC_ const char *cli_credentials_get_password(struct cli_credentials *cred)
     505             : {
     506      158890 :         if (cred->machine_account_pending) {
     507           1 :                 cli_credentials_set_machine_account(cred,
     508             :                                                     cred->machine_account_pending_lp_ctx);
     509             :         }
     510             : 
     511      158890 :         if (cred->password_obtained == CRED_CALLBACK &&
     512          39 :             !cred->callback_running &&
     513          39 :             !cred->password_will_be_nt_hash) {
     514          39 :                 cred->callback_running = true;
     515          39 :                 cred->password = cred->password_cb(cred);
     516          39 :                 cred->callback_running = false;
     517          39 :                 if (cred->password_obtained == CRED_CALLBACK) {
     518          39 :                         cred->password_obtained = CRED_CALLBACK_RESULT;
     519          39 :                         cli_credentials_invalidate_ccache(cred, cred->password_obtained);
     520             :                 }
     521             :         }
     522             : 
     523      158890 :         return cred->password;
     524             : }
     525             : 
     526             : /**
     527             :  * @brief Find out how the password was obtained.
     528             :  *
     529             :  * @param cred A credentials context.
     530             :  *
     531             :  * @return The obtained information for the password.
     532             :  */
     533             : _PUBLIC_ enum credentials_obtained
     534       35294 : cli_credentials_get_password_obtained(struct cli_credentials *cred)
     535             : {
     536       35294 :         return cred->password_obtained;
     537             : }
     538             : 
     539             : /**
     540             :  * @brief Obtain the password for this credentials context.
     541             :  *
     542             :  * @param[in]  cred  The credential context.
     543             :  *
     544             :  * @param[in]  obtained  A pointer to store the obtained information.
     545             :  *
     546             :  * return The user name or NULL if an error occurred.
     547             :  */
     548             : _PUBLIC_ const char *
     549       21308 : cli_credentials_get_password_and_obtained(struct cli_credentials *cred,
     550             :                                           enum credentials_obtained *obtained)
     551             : {
     552       21308 :         const char *password = cli_credentials_get_password(cred);
     553             : 
     554       21308 :         if (obtained != NULL) {
     555       21308 :                 *obtained = cred->password_obtained;
     556             :         }
     557             : 
     558       21308 :         return password;
     559             : }
     560             : 
     561             : /* Set a password on the credentials context, including an indication
     562             :  * of 'how' the password was obtained */
     563             : 
     564      285841 : _PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred,
     565             :                                   const char *val,
     566             :                                   enum credentials_obtained obtained)
     567             : {
     568      285841 :         if (obtained >= cred->password_obtained) {
     569             : 
     570      285798 :                 cred->lm_response = data_blob_null;
     571      285798 :                 cred->nt_response = data_blob_null;
     572      285798 :                 cred->nt_hash = NULL;
     573      285798 :                 cred->password = NULL;
     574             : 
     575      285798 :                 cli_credentials_invalidate_ccache(cred, obtained);
     576             : 
     577      285798 :                 cred->password_tries = 0;
     578             : 
     579      285798 :                 if (val == NULL) {
     580      166840 :                         cred->password_obtained = obtained;
     581      166840 :                         return true;
     582             :                 }
     583             : 
     584      118958 :                 if (cred->password_will_be_nt_hash) {
     585           3 :                         struct samr_Password *nt_hash = NULL;
     586           3 :                         size_t val_len = strlen(val);
     587           1 :                         size_t converted;
     588             : 
     589           3 :                         nt_hash = talloc(cred, struct samr_Password);
     590           3 :                         if (nt_hash == NULL) {
     591           0 :                                 return false;
     592             :                         }
     593             : 
     594           3 :                         converted = strhex_to_str((char *)nt_hash->hash,
     595             :                                                   sizeof(nt_hash->hash),
     596             :                                                   val, val_len);
     597           3 :                         if (converted != sizeof(nt_hash->hash)) {
     598           0 :                                 TALLOC_FREE(nt_hash);
     599           0 :                                 return false;
     600             :                         }
     601             : 
     602           3 :                         cred->nt_hash = nt_hash;
     603           3 :                         cred->password_obtained = obtained;
     604           3 :                         return true;
     605             :                 }
     606             : 
     607      118955 :                 cred->password = talloc_strdup(cred, val);
     608      118955 :                 if (cred->password == NULL) {
     609           0 :                         return false;
     610             :                 }
     611             : 
     612             :                 /* Don't print the actual password in talloc memory dumps */
     613      118955 :                 talloc_set_name_const(cred->password,
     614             :                         "password set via cli_credentials_set_password");
     615      118955 :                 cred->password_obtained = obtained;
     616             : 
     617      118955 :                 return true;
     618             :         }
     619             : 
     620          36 :         return false;
     621             : }
     622             : 
     623       15974 : _PUBLIC_ bool cli_credentials_set_password_callback(struct cli_credentials *cred,
     624             :                                            const char *(*password_cb) (struct cli_credentials *))
     625             : {
     626       15974 :         if (cred->password_obtained < CRED_CALLBACK) {
     627        9102 :                 cred->password_tries = 3;
     628        9102 :                 cred->password_cb = password_cb;
     629        9102 :                 cred->password_obtained = CRED_CALLBACK;
     630        9102 :                 cli_credentials_invalidate_ccache(cred, cred->password_obtained);
     631        9102 :                 return true;
     632             :         }
     633             : 
     634        6872 :         return false;
     635             : }
     636             : 
     637             : /**
     638             :  * Obtain the 'old' password for this credentials context (used for join accounts).
     639             :  * @param cred credentials context
     640             :  * @retval If set, the cleartext password, otherwise NULL
     641             :  */
     642         533 : _PUBLIC_ const char *cli_credentials_get_old_password(struct cli_credentials *cred)
     643             : {
     644         533 :         if (cred->machine_account_pending) {
     645           0 :                 cli_credentials_set_machine_account(cred,
     646             :                                                     cred->machine_account_pending_lp_ctx);
     647             :         }
     648             : 
     649         533 :         return cred->old_password;
     650             : }
     651             : 
     652         669 : _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
     653             :                                       const char *val,
     654             :                                       enum credentials_obtained obtained)
     655             : {
     656         669 :         cred->old_password = talloc_strdup(cred, val);
     657         669 :         if (cred->old_password) {
     658             :                 /* Don't print the actual password in talloc memory dumps */
     659         340 :                 talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password");
     660             :         }
     661         669 :         cred->old_nt_hash = NULL;
     662         669 :         return true;
     663             : }
     664             : 
     665             : /**
     666             :  * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
     667             :  *
     668             :  * Sometimes we only have this much of the password, while the rest of
     669             :  * the time this call avoids calling E_md4hash themselves.
     670             :  *
     671             :  * @param cred credentials context
     672             :  * @retval If set, the cleartext password, otherwise NULL
     673             :  */
     674       44280 : _PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
     675             :                                                            TALLOC_CTX *mem_ctx)
     676             : {
     677         722 :         enum credentials_obtained password_obtained;
     678         722 :         enum credentials_obtained ccache_threshold;
     679         722 :         enum credentials_obtained client_gss_creds_threshold;
     680         722 :         bool password_is_nt_hash;
     681       44280 :         const char *password = NULL;
     682       44280 :         struct samr_Password *nt_hash = NULL;
     683             : 
     684       44280 :         if (cred->nt_hash != NULL) {
     685             :                 /*
     686             :                  * If we already have a hash it's easy.
     687             :                  */
     688       14408 :                 goto return_hash;
     689             :         }
     690             : 
     691             :         /*
     692             :          * This is a bit tricky, with password_will_be_nt_hash
     693             :          * we still need to get the value via the password_callback
     694             :          * but if we did that we should not remember it's state
     695             :          * in the long run so we need to undo it.
     696             :          */
     697             : 
     698       29872 :         password_obtained = cred->password_obtained;
     699       29872 :         ccache_threshold = cred->ccache_threshold;
     700       29872 :         client_gss_creds_threshold = cred->client_gss_creds_threshold;
     701       29872 :         password_is_nt_hash = cred->password_will_be_nt_hash;
     702             : 
     703       29872 :         cred->password_will_be_nt_hash = false;
     704       29872 :         password = cli_credentials_get_password(cred);
     705             : 
     706       29872 :         cred->password_will_be_nt_hash = password_is_nt_hash;
     707       29872 :         if (password_is_nt_hash && password_obtained == CRED_CALLBACK) {
     708             :                 /*
     709             :                  * We got the nt_hash as string via the callback,
     710             :                  * so we need to undo the state change.
     711             :                  *
     712             :                  * And also don't remember it as plaintext password.
     713             :                  */
     714           0 :                 cred->client_gss_creds_threshold = client_gss_creds_threshold;
     715           0 :                 cred->ccache_threshold = ccache_threshold;
     716           0 :                 cred->password_obtained = password_obtained;
     717           0 :                 cred->password = NULL;
     718             :         }
     719             : 
     720       29872 :         if (password == NULL) {
     721        1172 :                 return NULL;
     722             :         }
     723             : 
     724       28680 :         nt_hash = talloc(cred, struct samr_Password);
     725       28680 :         if (nt_hash == NULL) {
     726           0 :                 return NULL;
     727             :         }
     728             : 
     729       28680 :         if (password_is_nt_hash) {
     730           0 :                 size_t password_len = strlen(password);
     731           0 :                 size_t converted;
     732             : 
     733           0 :                 converted = strhex_to_str((char *)nt_hash->hash,
     734             :                                           sizeof(nt_hash->hash),
     735             :                                           password, password_len);
     736           0 :                 if (converted != sizeof(nt_hash->hash)) {
     737           0 :                         TALLOC_FREE(nt_hash);
     738           0 :                         return NULL;
     739             :                 }
     740             :         } else {
     741       28680 :                 E_md4hash(password, nt_hash->hash);
     742             :         }
     743             : 
     744       28680 :         cred->nt_hash = nt_hash;
     745       28680 :         nt_hash = NULL;
     746             : 
     747       43088 : return_hash:
     748       43088 :         nt_hash = talloc(mem_ctx, struct samr_Password);
     749       43088 :         if (nt_hash == NULL) {
     750           0 :                 return NULL;
     751             :         }
     752             : 
     753       43088 :         *nt_hash = *cred->nt_hash;
     754             : 
     755       43088 :         return nt_hash;
     756             : }
     757             : 
     758             : /**
     759             :  * Obtain the old password, in the form MD4(unicode(password)) for this credentials context.
     760             :  *
     761             :  * Sometimes we only have this much of the password, while the rest of
     762             :  * the time this call avoids calling E_md4hash themselves.
     763             :  *
     764             :  * @param cred credentials context
     765             :  * @retval If set, the cleartext password, otherwise NULL
     766             :  */
     767         360 : _PUBLIC_ struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
     768             :                                                                TALLOC_CTX *mem_ctx)
     769             : {
     770         360 :         const char *old_password = NULL;
     771             : 
     772         360 :         if (cred->old_nt_hash != NULL) {
     773           0 :                 struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
     774           0 :                 if (!nt_hash) {
     775           0 :                         return NULL;
     776             :                 }
     777             : 
     778           0 :                 *nt_hash = *cred->old_nt_hash;
     779             : 
     780           0 :                 return nt_hash;
     781             :         }
     782             : 
     783         360 :         old_password = cli_credentials_get_old_password(cred);
     784         360 :         if (old_password) {
     785         219 :                 struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
     786         219 :                 if (!nt_hash) {
     787           0 :                         return NULL;
     788             :                 }
     789             : 
     790         219 :                 E_md4hash(old_password, nt_hash->hash);
     791             : 
     792         219 :                 return nt_hash;
     793             :         }
     794             : 
     795         141 :         return NULL;
     796             : }
     797             : 
     798             : /**
     799             :  * Obtain the 'short' or 'NetBIOS' domain for this credentials context.
     800             :  * @param cred credentials context
     801             :  * @retval The domain set on this context.
     802             :  * @note Return value will never be NULL except by programmer error.
     803             :  */
     804      774925 : _PUBLIC_ const char *cli_credentials_get_domain(struct cli_credentials *cred)
     805             : {
     806      774925 :         if (cred->machine_account_pending) {
     807           0 :                 cli_credentials_set_machine_account(cred,
     808             :                                                     cred->machine_account_pending_lp_ctx);
     809             :         }
     810             : 
     811      774925 :         if (cred->domain_obtained == CRED_CALLBACK &&
     812           0 :             !cred->callback_running) {
     813           0 :                 cred->callback_running = true;
     814           0 :                 cred->domain = cred->domain_cb(cred);
     815           0 :                 cred->callback_running = false;
     816           0 :                 if (cred->domain_obtained == CRED_CALLBACK) {
     817           0 :                         cred->domain_obtained = CRED_CALLBACK_RESULT;
     818           0 :                         cli_credentials_invalidate_ccache(cred, cred->domain_obtained);
     819             :                 }
     820             :         }
     821             : 
     822      774925 :         return cred->domain;
     823             : }
     824             : 
     825             : /**
     826             :  * @brief Obtain the domain for this credential context.
     827             :  *
     828             :  * @param[in] cred  The credential context.
     829             :  *
     830             :  * @param[out] obtained A pointer to store the obtained information.
     831             :  *
     832             :  * @return The domain name or NULL if an error occurred.
     833             :  */
     834          87 : _PUBLIC_ const char *cli_credentials_get_domain_and_obtained(
     835             :         struct cli_credentials *cred,
     836             :         enum credentials_obtained *obtained)
     837             : {
     838          87 :         const char *domain = cli_credentials_get_domain(cred);
     839             : 
     840          87 :         if (obtained != NULL) {
     841          87 :                 *obtained = cred->domain_obtained;
     842             :         }
     843             : 
     844          87 :         return domain;
     845             : }
     846             : 
     847             : 
     848      583416 : _PUBLIC_ bool cli_credentials_set_domain(struct cli_credentials *cred,
     849             :                                 const char *val,
     850             :                                 enum credentials_obtained obtained)
     851             : {
     852      583416 :         if (obtained >= cred->domain_obtained) {
     853             :                 /* it is important that the domain be in upper case,
     854             :                  * particularly for the sensitive NTLMv2
     855             :                  * calculations */
     856      520144 :                 cred->domain = strupper_talloc(cred, val);
     857      520144 :                 cred->domain_obtained = obtained;
     858             :                 /* setting domain does not mean we have to invalidate ccache
     859             :                  * because domain in not used for Kerberos operations.
     860             :                  * If ccache invalidation is required, one will anyway specify
     861             :                  * a password to kinit, and that will force invalidation of the ccache
     862             :                  */
     863      520144 :                 return true;
     864             :         }
     865             : 
     866       63272 :         return false;
     867             : }
     868             : 
     869           0 : bool cli_credentials_set_domain_callback(struct cli_credentials *cred,
     870             :                                          const char *(*domain_cb) (struct cli_credentials *))
     871             : {
     872           0 :         if (cred->domain_obtained < CRED_CALLBACK) {
     873           0 :                 cred->domain_cb = domain_cb;
     874           0 :                 cred->domain_obtained = CRED_CALLBACK;
     875           0 :                 return true;
     876             :         }
     877             : 
     878           0 :         return false;
     879             : }
     880             : 
     881             : /**
     882             :  * Obtain the Kerberos realm for this credentials context.
     883             :  * @param cred credentials context
     884             :  * @retval The realm set on this context.
     885             :  * @note Return value will never be NULL except by programmer error.
     886             :  */
     887      836796 : _PUBLIC_ const char *cli_credentials_get_realm(struct cli_credentials *cred)
     888             : {
     889      836796 :         if (cred->machine_account_pending) {
     890           0 :                 cli_credentials_set_machine_account(cred,
     891             :                                                     cred->machine_account_pending_lp_ctx);
     892             :         }
     893             : 
     894      836796 :         if (cred->realm_obtained == CRED_CALLBACK &&
     895           0 :             !cred->callback_running) {
     896           0 :                 cred->callback_running = true;
     897           0 :                 cred->realm = cred->realm_cb(cred);
     898           0 :                 cred->callback_running = false;
     899           0 :                 if (cred->realm_obtained == CRED_CALLBACK) {
     900           0 :                         cred->realm_obtained = CRED_CALLBACK_RESULT;
     901           0 :                         cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
     902             :                 }
     903             :         }
     904             : 
     905      836796 :         return cred->realm;
     906             : }
     907             : 
     908             : /**
     909             :  * Set the realm for this credentials context, and force it to
     910             :  * uppercase for the sanity of our local kerberos libraries
     911             :  */
     912      456103 : _PUBLIC_ bool cli_credentials_set_realm(struct cli_credentials *cred,
     913             :                                const char *val,
     914             :                                enum credentials_obtained obtained)
     915             : {
     916      456103 :         if (obtained >= cred->realm_obtained) {
     917      449075 :                 cred->realm = strupper_talloc(cred, val);
     918      449075 :                 cred->realm_obtained = obtained;
     919      449075 :                 cli_credentials_invalidate_ccache(cred, cred->realm_obtained);
     920      449075 :                 return true;
     921             :         }
     922             : 
     923        7028 :         return false;
     924             : }
     925             : 
     926           0 : bool cli_credentials_set_realm_callback(struct cli_credentials *cred,
     927             :                                         const char *(*realm_cb) (struct cli_credentials *))
     928             : {
     929           0 :         if (cred->realm_obtained < CRED_CALLBACK) {
     930           0 :                 cred->realm_cb = realm_cb;
     931           0 :                 cred->realm_obtained = CRED_CALLBACK;
     932           0 :                 return true;
     933             :         }
     934             : 
     935           0 :         return false;
     936             : }
     937             : 
     938             : /**
     939             :  * Obtain the 'short' or 'NetBIOS' workstation name for this credentials context.
     940             :  *
     941             :  * @param cred credentials context
     942             :  * @retval The workstation name set on this context.
     943             :  * @note Return value will never be NULL except by programmer error.
     944             :  */
     945      125562 : _PUBLIC_ const char *cli_credentials_get_workstation(struct cli_credentials *cred)
     946             : {
     947      125562 :         if (cred->workstation_obtained == CRED_CALLBACK &&
     948           0 :             !cred->callback_running) {
     949           0 :                 cred->callback_running = true;
     950           0 :                 cred->workstation = cred->workstation_cb(cred);
     951           0 :                 cred->callback_running = false;
     952           0 :                 if (cred->workstation_obtained == CRED_CALLBACK) {
     953           0 :                         cred->workstation_obtained = CRED_CALLBACK_RESULT;
     954             :                 }
     955             :         }
     956             : 
     957      125562 :         return cred->workstation;
     958             : }
     959             : 
     960      467633 : _PUBLIC_ bool cli_credentials_set_workstation(struct cli_credentials *cred,
     961             :                                      const char *val,
     962             :                                      enum credentials_obtained obtained)
     963             : {
     964      467633 :         if (obtained >= cred->workstation_obtained) {
     965      425551 :                 cred->workstation = talloc_strdup(cred, val);
     966      425551 :                 cred->workstation_obtained = obtained;
     967      425551 :                 return true;
     968             :         }
     969             : 
     970       41662 :         return false;
     971             : }
     972             : 
     973           0 : bool cli_credentials_set_workstation_callback(struct cli_credentials *cred,
     974             :                                               const char *(*workstation_cb) (struct cli_credentials *))
     975             : {
     976           0 :         if (cred->workstation_obtained < CRED_CALLBACK) {
     977           0 :                 cred->workstation_cb = workstation_cb;
     978           0 :                 cred->workstation_obtained = CRED_CALLBACK;
     979           0 :                 return true;
     980             :         }
     981             : 
     982           0 :         return false;
     983             : }
     984             : 
     985             : /**
     986             :  * Given a string, typically obtained from a -U argument, parse it into domain, username, realm and password fields
     987             :  *
     988             :  * The format accepted is [domain\\]user[%password] or user[@realm][%password]
     989             :  *
     990             :  * @param credentials Credentials structure on which to set the password
     991             :  * @param data the string containing the username, password etc
     992             :  * @param obtained This enum describes how 'specified' this password is
     993             :  */
     994             : 
     995      247422 : _PUBLIC_ void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained)
     996             : {
     997        1026 :         char *uname, *p;
     998      247422 :         char *uname_free = NULL;
     999             : 
    1000      247422 :         if (strcmp("%",data) == 0) {
    1001         452 :                 cli_credentials_set_anonymous(credentials);
    1002         452 :                 return;
    1003             :         }
    1004             : 
    1005      246970 :         uname = talloc_strdup(credentials, data);
    1006      246970 :         uname_free = uname;
    1007             : 
    1008      246970 :         if ((p = strchr_m(uname,'%'))) {
    1009       23746 :                 *p = 0;
    1010       23746 :                 cli_credentials_set_password(credentials, p+1, obtained);
    1011             :         }
    1012             : 
    1013      246970 :         if ((p = strchr_m(uname,'@'))) {
    1014             :                 /*
    1015             :                  * We also need to set username and domain
    1016             :                  * in order to undo the effect of
    1017             :                  * cli_credentials_guess().
    1018             :                  */
    1019         433 :                 cli_credentials_set_username(credentials, uname, obtained);
    1020         433 :                 cli_credentials_set_domain(credentials, "", obtained);
    1021             : 
    1022         433 :                 cli_credentials_set_principal(credentials, uname, obtained);
    1023         433 :                 *p = 0;
    1024         433 :                 cli_credentials_set_realm(credentials, p+1, obtained);
    1025         433 :                 TALLOC_FREE(uname_free);
    1026         433 :                 return;
    1027      246537 :         } else if ((p = strchr_m(uname,'\\'))
    1028      245922 :                    || (p = strchr_m(uname, '/'))
    1029      244585 :                    || (p = strchr_m(uname, credentials->winbind_separator)))
    1030             :         {
    1031        1980 :                 const char *domain = NULL;
    1032             : 
    1033        1980 :                 domain = uname;
    1034        1980 :                 *p = 0;
    1035        1980 :                 uname = p+1;
    1036             : 
    1037        1986 :                 if (obtained == credentials->realm_obtained &&
    1038           6 :                     !strequal_m(credentials->domain, domain))
    1039             :                 {
    1040             :                         /*
    1041             :                          * We need to undo a former set with the same level
    1042             :                          * in order to get the expected result from
    1043             :                          * cli_credentials_get_principal().
    1044             :                          *
    1045             :                          * But we only need to do that if the domain
    1046             :                          * actually changes.
    1047             :                          */
    1048           5 :                         cli_credentials_set_realm(credentials, domain, obtained);
    1049             :                 }
    1050        1980 :                 cli_credentials_set_domain(credentials, domain, obtained);
    1051             :         }
    1052      246539 :         if (obtained == credentials->principal_obtained &&
    1053           8 :             !strequal_m(credentials->username, uname))
    1054             :         {
    1055             :                 /*
    1056             :                  * We need to undo a former set with the same level
    1057             :                  * in order to get the expected result from
    1058             :                  * cli_credentials_get_principal().
    1059             :                  *
    1060             :                  * But we only need to do that if the username
    1061             :                  * actually changes.
    1062             :                  */
    1063           2 :                 credentials->principal_obtained = CRED_UNINITIALISED;
    1064           2 :                 credentials->principal = NULL;
    1065             :         }
    1066      246537 :         cli_credentials_set_username(credentials, uname, obtained);
    1067             : 
    1068      246537 :         TALLOC_FREE(uname_free);
    1069             : }
    1070             : 
    1071             : /**
    1072             :  * Given a a credentials structure, print it as a string
    1073             :  *
    1074             :  * The format output is [domain\\]user[%password] or user[@realm][%password]
    1075             :  *
    1076             :  * @param credentials Credentials structure on which to set the password
    1077             :  * @param mem_ctx The memory context to place the result on
    1078             :  */
    1079             : 
    1080       27667 : _PUBLIC_ char *cli_credentials_get_unparsed_name(struct cli_credentials *credentials, TALLOC_CTX *mem_ctx)
    1081             : {
    1082       27667 :         const char *bind_dn = cli_credentials_get_bind_dn(credentials);
    1083       27667 :         const char *domain = NULL;
    1084       27667 :         const char *username = NULL;
    1085       27667 :         char *name = NULL;
    1086             : 
    1087       27667 :         if (bind_dn) {
    1088           0 :                 name = talloc_strdup(mem_ctx, bind_dn);
    1089             :         } else {
    1090       27667 :                 cli_credentials_get_ntlm_username_domain(credentials, mem_ctx, &username, &domain);
    1091       27667 :                 if (domain && domain[0]) {
    1092       26283 :                         name = talloc_asprintf(mem_ctx, "%s\\%s",
    1093             :                                                domain, username);
    1094             :                 } else {
    1095        1384 :                         name = talloc_asprintf(mem_ctx, "%s",
    1096             :                                                username);
    1097             :                 }
    1098             :         }
    1099       27667 :         return name;
    1100             : }
    1101             : 
    1102             : 
    1103             : /**
    1104             :  * Specifies default values for domain, workstation and realm
    1105             :  * from the smb.conf configuration file
    1106             :  *
    1107             :  * @param cred Credentials structure to fill in
    1108             :  *
    1109             :  * @return true on success, false on error.
    1110             :  */
    1111      280281 : _PUBLIC_ bool cli_credentials_set_conf(struct cli_credentials *cred,
    1112             :                                        struct loadparm_context *lp_ctx)
    1113             : {
    1114      280281 :         const char *sep = NULL;
    1115      280281 :         const char *realm = lpcfg_realm(lp_ctx);
    1116        3939 :         enum credentials_client_protection protection =
    1117      280281 :                 lpcfg_client_protection(lp_ctx);
    1118      280281 :         const char *workgroup = lpcfg_workgroup(lp_ctx);
    1119      280281 :         const char *netbios_name = lpcfg_netbios_name(lp_ctx);
    1120        3939 :         bool ok;
    1121             : 
    1122      280281 :         (void)cli_credentials_set_username(cred, "", CRED_UNINITIALISED);
    1123             : 
    1124      280281 :         if (workgroup != NULL && strlen(workgroup) == 0) {
    1125           0 :                 workgroup = NULL;
    1126             :         }
    1127             : 
    1128      280281 :         if (workgroup != NULL) {
    1129      280281 :                 if (lpcfg_parm_is_cmdline(lp_ctx, "workgroup")) {
    1130        1484 :                         ok = cli_credentials_set_domain(cred,
    1131             :                                                         workgroup,
    1132             :                                                         CRED_SPECIFIED);
    1133        1484 :                         if (!ok) {
    1134           0 :                                 DBG_ERR("Failed to set domain!\n");
    1135           0 :                                 return false;
    1136             :                         }
    1137             :                 } else {
    1138      278797 :                         (void)cli_credentials_set_domain(cred,
    1139             :                                                          workgroup,
    1140             :                                                          CRED_SMB_CONF);
    1141             :                 }
    1142             :         }
    1143             : 
    1144      280281 :         if (netbios_name != NULL && strlen(netbios_name) == 0) {
    1145           0 :                 netbios_name = NULL;
    1146             :         }
    1147             : 
    1148      280281 :         if (netbios_name != NULL) {
    1149      280281 :                 if (lpcfg_parm_is_cmdline(lp_ctx, "netbios name")) {
    1150         275 :                         ok = cli_credentials_set_workstation(cred,
    1151             :                                                              netbios_name,
    1152             :                                                              CRED_SPECIFIED);
    1153         275 :                         if (!ok) {
    1154           0 :                                 DBG_ERR("Failed to set workstation!\n");
    1155           0 :                                 return false;
    1156             :                         }
    1157             :                 } else {
    1158      280006 :                         (void)cli_credentials_set_workstation(cred,
    1159             :                                                               netbios_name,
    1160             :                                                               CRED_SMB_CONF);
    1161             :                 }
    1162             :         }
    1163             : 
    1164      280281 :         if (realm != NULL && strlen(realm) == 0) {
    1165      118317 :                 realm = NULL;
    1166             :         }
    1167             : 
    1168      279717 :         if (realm != NULL) {
    1169      161400 :                 if (lpcfg_parm_is_cmdline(lp_ctx, "realm")) {
    1170         252 :                         ok = cli_credentials_set_realm(cred,
    1171             :                                                        realm,
    1172             :                                                        CRED_SPECIFIED);
    1173         252 :                         if (!ok) {
    1174           0 :                                 DBG_ERR("Failed to set realm!\n");
    1175           0 :                                 return false;
    1176             :                         }
    1177             :                 } else {
    1178      161148 :                         (void)cli_credentials_set_realm(cred,
    1179             :                                                         realm,
    1180             :                                                         CRED_SMB_CONF);
    1181             :                 }
    1182             :         }
    1183             : 
    1184      280281 :         sep = lpcfg_winbind_separator(lp_ctx);
    1185      280281 :         if (sep != NULL && sep[0] != '\0') {
    1186      280281 :                 cred->winbind_separator = *lpcfg_winbind_separator(lp_ctx);
    1187             :         }
    1188             : 
    1189      280281 :         if (cred->signing_state_obtained <= CRED_SMB_CONF) {
    1190             :                 /* Will be set to default for invalid smb.conf values */
    1191      279141 :                 cred->signing_state = lpcfg_client_signing(lp_ctx);
    1192      279141 :                 if (cred->signing_state == SMB_SIGNING_DEFAULT) {
    1193      279127 :                         switch (protection) {
    1194      275197 :                         case CRED_CLIENT_PROTECTION_DEFAULT:
    1195      275197 :                                 break;
    1196           0 :                         case CRED_CLIENT_PROTECTION_PLAIN:
    1197           0 :                                 cred->signing_state = SMB_SIGNING_OFF;
    1198           0 :                                 break;
    1199           0 :                         case CRED_CLIENT_PROTECTION_SIGN:
    1200             :                         case CRED_CLIENT_PROTECTION_ENCRYPT:
    1201           0 :                                 cred->signing_state = SMB_SIGNING_REQUIRED;
    1202           0 :                                 break;
    1203             :                         }
    1204             :                 }
    1205             : 
    1206      279141 :                 cred->signing_state_obtained = CRED_SMB_CONF;
    1207             :         }
    1208             : 
    1209      280281 :         if (cred->ipc_signing_state_obtained <= CRED_SMB_CONF) {
    1210             :                 /* Will be set to required for invalid smb.conf values */
    1211      280280 :                 cred->ipc_signing_state = lpcfg_client_ipc_signing(lp_ctx);
    1212      280280 :                 cred->ipc_signing_state_obtained = CRED_SMB_CONF;
    1213             :         }
    1214             : 
    1215      280281 :         if (cred->encryption_state_obtained <= CRED_SMB_CONF) {
    1216             :                 /* Will be set to default for invalid smb.conf values */
    1217      279141 :                 cred->encryption_state = lpcfg_client_smb_encrypt(lp_ctx);
    1218      279141 :                 if (cred->encryption_state == SMB_ENCRYPTION_DEFAULT) {
    1219      279045 :                         switch (protection) {
    1220      275115 :                         case CRED_CLIENT_PROTECTION_DEFAULT:
    1221      275115 :                                 break;
    1222           0 :                         case CRED_CLIENT_PROTECTION_PLAIN:
    1223             :                         case CRED_CLIENT_PROTECTION_SIGN:
    1224           0 :                                 cred->encryption_state = SMB_ENCRYPTION_OFF;
    1225           0 :                                 break;
    1226           0 :                         case CRED_CLIENT_PROTECTION_ENCRYPT:
    1227           0 :                                 cred->encryption_state = SMB_ENCRYPTION_REQUIRED;
    1228           0 :                                 break;
    1229             :                         }
    1230             :                 }
    1231             :         }
    1232             : 
    1233      280281 :         if (cred->kerberos_state_obtained <= CRED_SMB_CONF) {
    1234             :                 /* Will be set to default for invalid smb.conf values */
    1235      215809 :                 cred->kerberos_state = lpcfg_client_use_kerberos(lp_ctx);
    1236      215809 :                 cred->kerberos_state_obtained = CRED_SMB_CONF;
    1237             :         }
    1238             : 
    1239      280281 :         if (cred->gensec_features_obtained <= CRED_SMB_CONF) {
    1240      279094 :                 switch (protection) {
    1241      275163 :                 case CRED_CLIENT_PROTECTION_DEFAULT:
    1242      275163 :                         break;
    1243           0 :                 case CRED_CLIENT_PROTECTION_PLAIN:
    1244           0 :                         cred->gensec_features = 0;
    1245           0 :                         break;
    1246           0 :                 case CRED_CLIENT_PROTECTION_SIGN:
    1247           0 :                         cred->gensec_features = GENSEC_FEATURE_SIGN;
    1248           0 :                         break;
    1249           0 :                 case CRED_CLIENT_PROTECTION_ENCRYPT:
    1250           0 :                         cred->gensec_features =
    1251             :                                 GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL;
    1252           0 :                         break;
    1253             :                 }
    1254      279094 :                 cred->gensec_features_obtained = CRED_SMB_CONF;
    1255             :         }
    1256             : 
    1257      276342 :         return true;
    1258             : }
    1259             : 
    1260             : /**
    1261             :  * Guess defaults for credentials from environment variables,
    1262             :  * and from the configuration file
    1263             :  *
    1264             :  * @param cred Credentials structure to fill in
    1265             :  */
    1266      102715 : _PUBLIC_ bool cli_credentials_guess(struct cli_credentials *cred,
    1267             :                                     struct loadparm_context *lp_ctx)
    1268             : {
    1269         443 :         const char *error_string;
    1270      102715 :         const char *env = NULL;
    1271      102715 :         struct passwd *pwd = NULL;
    1272         443 :         bool ok;
    1273             : 
    1274      102715 :         if (lp_ctx != NULL) {
    1275      102713 :                 ok = cli_credentials_set_conf(cred, lp_ctx);
    1276      102713 :                 if (!ok) {
    1277           0 :                         return false;
    1278             :                 }
    1279             :         }
    1280             : 
    1281      102715 :         pwd = getpwuid(getuid());
    1282      102715 :         if (pwd != NULL) {
    1283      102150 :                 size_t len = strlen(pwd->pw_name);
    1284             : 
    1285      102150 :                 if (len > 0 && len <= 1024) {
    1286      102150 :                         (void)cli_credentials_parse_string(cred,
    1287      101707 :                                                            pwd->pw_name,
    1288             :                                                            CRED_GUESS_ENV);
    1289             :                 }
    1290             :         }
    1291             : 
    1292      102715 :         env = getenv("LOGNAME");
    1293      102715 :         if (env != NULL) {
    1294           0 :                 size_t len = strlen(env);
    1295             : 
    1296           0 :                 if (len > 0 && len <= 1024) {
    1297           0 :                         (void)cli_credentials_set_username(cred,
    1298             :                                                            env,
    1299             :                                                            CRED_GUESS_ENV);
    1300             :                 }
    1301             :         }
    1302             : 
    1303      102715 :         env = getenv("USER");
    1304      102715 :         if (env != NULL) {
    1305      102715 :                 size_t len = strlen(env);
    1306             : 
    1307      102715 :                 if (len > 0 && len <= 1024) {
    1308      102715 :                         char *p = NULL;
    1309             : 
    1310      102715 :                         (void)cli_credentials_parse_string(cred,
    1311             :                                                            env,
    1312             :                                                            CRED_GUESS_ENV);
    1313      102715 :                         if ((p = strchr_m(env, '%'))) {
    1314           0 :                                 memset(p, '\0', strlen(cred->password));
    1315             :                         }
    1316             :                 }
    1317             :         }
    1318             : 
    1319      102715 :         env = getenv("PASSWD");
    1320      102715 :         if (env != NULL) {
    1321           6 :                 size_t len = strlen(env);
    1322             : 
    1323           6 :                 if (len > 0 && len <= 1024) {
    1324           6 :                         (void)cli_credentials_set_password(cred,
    1325             :                                                            env,
    1326             :                                                            CRED_GUESS_ENV);
    1327             :                 }
    1328             :         }
    1329             : 
    1330      102715 :         env = getenv("PASSWD_FD");
    1331      102715 :         if (env != NULL) {
    1332           2 :                 size_t len = strlen(env);
    1333             : 
    1334           2 :                 if (len > 0 && len <= 1024) {
    1335           2 :                         int fd = atoi(env);
    1336             : 
    1337           2 :                         (void)cli_credentials_parse_password_fd(cred,
    1338             :                                                                 fd,
    1339             :                                                                 CRED_GUESS_FILE);
    1340             :                 }
    1341             :         }
    1342             : 
    1343      102715 :         env = getenv("PASSWD_FILE");
    1344      102715 :         if (env != NULL) {
    1345           2 :                 size_t len = strlen(env);
    1346             : 
    1347           2 :                 if (len > 0 && len <= 4096) {
    1348           2 :                         (void)cli_credentials_parse_password_file(cred,
    1349             :                                                                   env,
    1350             :                                                                   CRED_GUESS_FILE);
    1351             :                 }
    1352             :         }
    1353             : 
    1354      205428 :         if (lp_ctx != NULL &&
    1355      102713 :             cli_credentials_get_kerberos_state(cred) != CRED_USE_KERBEROS_DISABLED) {
    1356      101197 :                 (void)cli_credentials_set_ccache(cred,
    1357             :                                                  lp_ctx,
    1358             :                                                  NULL,
    1359             :                                                  CRED_GUESS_FILE,
    1360             :                                                  &error_string);
    1361             :         }
    1362             : 
    1363      102272 :         return true;
    1364             : }
    1365             : 
    1366             : /**
    1367             :  * Attach NETLOGON credentials for use with SCHANNEL
    1368             :  */
    1369             : 
    1370        1737 : _PUBLIC_ void cli_credentials_set_netlogon_creds(
    1371             :         struct cli_credentials *cred,
    1372             :         const struct netlogon_creds_CredentialState *netlogon_creds)
    1373             : {
    1374        1737 :         TALLOC_FREE(cred->netlogon_creds);
    1375        1737 :         if (netlogon_creds == NULL) {
    1376         549 :                 return;
    1377             :         }
    1378        1148 :         cred->netlogon_creds = netlogon_creds_copy(cred, netlogon_creds);
    1379             : }
    1380             : 
    1381             : /**
    1382             :  * Return attached NETLOGON credentials
    1383             :  */
    1384             : 
    1385      578258 : _PUBLIC_ struct netlogon_creds_CredentialState *cli_credentials_get_netlogon_creds(struct cli_credentials *cred)
    1386             : {
    1387      578258 :         return cred->netlogon_creds;
    1388             : }
    1389             : 
    1390             : /**
    1391             :  * Set NETLOGON secure channel type
    1392             :  */
    1393             : 
    1394       71393 : _PUBLIC_ void cli_credentials_set_secure_channel_type(struct cli_credentials *cred,
    1395             :                                              enum netr_SchannelType secure_channel_type)
    1396             : {
    1397       71393 :         cred->secure_channel_type = secure_channel_type;
    1398       71393 : }
    1399             : 
    1400             : /**
    1401             :  * Return NETLOGON secure channel type
    1402             :  */
    1403             : 
    1404      134052 : _PUBLIC_ time_t cli_credentials_get_password_last_changed_time(struct cli_credentials *cred)
    1405             : {
    1406      134052 :         return cred->password_last_changed_time;
    1407             : }
    1408             : 
    1409             : /**
    1410             :  * Set NETLOGON secure channel type
    1411             :  */
    1412             : 
    1413       67359 : _PUBLIC_ void cli_credentials_set_password_last_changed_time(struct cli_credentials *cred,
    1414             :                                                              time_t last_changed_time)
    1415             : {
    1416       67359 :         cred->password_last_changed_time = last_changed_time;
    1417       67359 : }
    1418             : 
    1419             : /**
    1420             :  * Return NETLOGON secure channel type
    1421             :  */
    1422             : 
    1423       10799 : _PUBLIC_ enum netr_SchannelType cli_credentials_get_secure_channel_type(struct cli_credentials *cred)
    1424             : {
    1425       10799 :         return cred->secure_channel_type;
    1426             : }
    1427             : 
    1428             : /**
    1429             :  * Fill in a credentials structure as the anonymous user
    1430             :  */
    1431      166414 : _PUBLIC_ void cli_credentials_set_anonymous(struct cli_credentials *cred)
    1432             : {
    1433      166414 :         cli_credentials_set_username(cred, "", CRED_SPECIFIED);
    1434      166414 :         cli_credentials_set_domain(cred, "", CRED_SPECIFIED);
    1435      166414 :         cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
    1436      166414 :         cli_credentials_set_principal(cred, NULL, CRED_SPECIFIED);
    1437      166414 :         cli_credentials_set_realm(cred, NULL, CRED_SPECIFIED);
    1438      166414 :         cli_credentials_set_workstation(cred, "", CRED_UNINITIALISED);
    1439      166414 :         cli_credentials_set_kerberos_state(cred,
    1440             :                                            CRED_USE_KERBEROS_DISABLED,
    1441             :                                            CRED_SPECIFIED);
    1442      166414 : }
    1443             : 
    1444             : /**
    1445             :  * Describe a credentials context as anonymous or authenticated
    1446             :  * @retval true if anonymous, false if a username is specified
    1447             :  */
    1448             : 
    1449      227876 : _PUBLIC_ bool cli_credentials_is_anonymous(struct cli_credentials *cred)
    1450             : {
    1451        3714 :         const char *username;
    1452             : 
    1453             :         /* if bind dn is set it's not anonymous */
    1454      227876 :         if (cred->bind_dn) {
    1455           0 :                 return false;
    1456             :         }
    1457             : 
    1458      227876 :         if (cred->machine_account_pending) {
    1459          14 :                 cli_credentials_set_machine_account(cred,
    1460             :                                                     cred->machine_account_pending_lp_ctx);
    1461             :         }
    1462             : 
    1463             :         /* if principal is set, it's not anonymous */
    1464      227876 :         if ((cred->principal != NULL) && cred->principal_obtained >= cred->username_obtained) {
    1465       51238 :                 return false;
    1466             :         }
    1467             : 
    1468      174987 :         username = cli_credentials_get_username(cred);
    1469             : 
    1470             :         /* Yes, it is deliberate that we die if we have a NULL pointer
    1471             :          * here - anonymous is "", not NULL, which is 'never specified,
    1472             :          * never guessed', ie programmer bug */
    1473      174987 :         if (!username[0]) {
    1474        9317 :                 return true;
    1475             :         }
    1476             : 
    1477      163773 :         return false;
    1478             : }
    1479             : 
    1480             : /**
    1481             :  * Mark the current password for a credentials struct as wrong. This will
    1482             :  * cause the password to be prompted again (if a callback is set).
    1483             :  *
    1484             :  * This will decrement the number of times the password can be tried.
    1485             :  *
    1486             :  * @retval whether the credentials struct is finished
    1487             :  */
    1488        1737 : _PUBLIC_ bool cli_credentials_wrong_password(struct cli_credentials *cred)
    1489             : {
    1490        1737 :         if (cred->password_obtained != CRED_CALLBACK_RESULT) {
    1491        1730 :                 return false;
    1492             :         }
    1493             : 
    1494           0 :         if (cred->password_tries == 0) {
    1495           0 :                 return false;
    1496             :         }
    1497             : 
    1498           0 :         cred->password_tries--;
    1499             : 
    1500           0 :         if (cred->password_tries == 0) {
    1501           0 :                 return false;
    1502             :         }
    1503             : 
    1504           0 :         cred->password_obtained = CRED_CALLBACK;
    1505           0 :         return true;
    1506             : }
    1507             : 
    1508      110618 : _PUBLIC_ void cli_credentials_get_ntlm_username_domain(struct cli_credentials *cred, TALLOC_CTX *mem_ctx,
    1509             :                                               const char **username,
    1510             :                                               const char **domain)
    1511             : {
    1512      110618 :         if (cred->principal_obtained >= cred->username_obtained) {
    1513        5241 :                 *domain = talloc_strdup(mem_ctx, "");
    1514        5241 :                 *username = cli_credentials_get_principal(cred, mem_ctx);
    1515             :         } else {
    1516      105377 :                 *domain = cli_credentials_get_domain(cred);
    1517      105377 :                 *username = cli_credentials_get_username(cred);
    1518             :         }
    1519      110618 : }
    1520             : 
    1521             : /**
    1522             :  * Read a named file, and parse it for username, domain, realm and password
    1523             :  *
    1524             :  * @param credentials Credentials structure on which to set the password
    1525             :  * @param file a named file to read the details from
    1526             :  * @param obtained This enum describes how 'specified' this password is
    1527             :  */
    1528             : 
    1529          61 : _PUBLIC_ bool cli_credentials_parse_file(struct cli_credentials *cred, const char *file, enum credentials_obtained obtained)
    1530             : {
    1531          61 :         uint16_t len = 0;
    1532           7 :         char *ptr, *val, *param;
    1533           7 :         char **lines;
    1534           7 :         int i, numlines;
    1535          61 :         const char *realm = NULL;
    1536          61 :         const char *domain = NULL;
    1537          61 :         const char *password = NULL;
    1538          61 :         const char *username = NULL;
    1539             : 
    1540          61 :         lines = file_lines_load(file, &numlines, 0, NULL);
    1541             : 
    1542          61 :         if (lines == NULL)
    1543             :         {
    1544             :                 /* fail if we can't open the credentials file */
    1545           0 :                 d_printf("ERROR: Unable to open credentials file!\n");
    1546           0 :                 return false;
    1547             :         }
    1548             : 
    1549         249 :         for (i = 0; i < numlines; i++) {
    1550         188 :                 len = strlen(lines[i]);
    1551             : 
    1552         188 :                 if (len == 0)
    1553           0 :                         continue;
    1554             : 
    1555             :                 /* break up the line into parameter & value.
    1556             :                  * will need to eat a little whitespace possibly */
    1557         188 :                 param = lines[i];
    1558         188 :                 if (!(ptr = strchr_m (lines[i], '=')))
    1559           0 :                         continue;
    1560             : 
    1561         188 :                 val = ptr+1;
    1562         188 :                 *ptr = '\0';
    1563             : 
    1564             :                 /* eat leading white space */
    1565         192 :                 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
    1566           4 :                         val++;
    1567             : 
    1568         188 :                 if (strwicmp("password", param) == 0) {
    1569          54 :                         password = val;
    1570         127 :                 } else if (strwicmp("username", param) == 0) {
    1571          54 :                         username = val;
    1572          66 :                 } else if (strwicmp("domain", param) == 0) {
    1573          52 :                         domain = val;
    1574           7 :                 } else if (strwicmp("realm", param) == 0) {
    1575           7 :                         realm = val;
    1576             :                 }
    1577             : 
    1578             :                 /*
    1579             :                  * We need to readd '=' in order to let
    1580             :                  * the strlen() work in the last loop
    1581             :                  * that clears the memory.
    1582             :                  */
    1583         188 :                 *ptr = '=';
    1584             :         }
    1585             : 
    1586          61 :         if (realm != NULL && strlen(realm) != 0) {
    1587             :                 /*
    1588             :                  * only overwrite with a valid string
    1589             :                  */
    1590           7 :                 cli_credentials_set_realm(cred, realm, obtained);
    1591             :         }
    1592             : 
    1593          61 :         if (domain != NULL && strlen(domain) != 0) {
    1594             :                 /*
    1595             :                  * only overwrite with a valid string
    1596             :                  */
    1597          59 :                 cli_credentials_set_domain(cred, domain, obtained);
    1598             :         }
    1599             : 
    1600          61 :         if (password != NULL) {
    1601             :                 /*
    1602             :                  * Here we allow "".
    1603             :                  */
    1604          61 :                 cli_credentials_set_password(cred, password, obtained);
    1605             :         }
    1606             : 
    1607          61 :         if (username != NULL) {
    1608             :                 /*
    1609             :                  * The last "username" line takes preference
    1610             :                  * if the string also contains domain, realm or
    1611             :                  * password.
    1612             :                  */
    1613          61 :                 cli_credentials_parse_string(cred, username, obtained);
    1614             :         }
    1615             : 
    1616         249 :         for (i = 0; i < numlines; i++) {
    1617         188 :                 len = strlen(lines[i]);
    1618         188 :                 memset(lines[i], 0, len);
    1619             :         }
    1620          61 :         talloc_free(lines);
    1621             : 
    1622          61 :         return true;
    1623             : }
    1624             : 
    1625             : /**
    1626             :  * Read a named file, and parse it for a password
    1627             :  *
    1628             :  * @param credentials Credentials structure on which to set the password
    1629             :  * @param file a named file to read the password from
    1630             :  * @param obtained This enum describes how 'specified' this password is
    1631             :  */
    1632             : 
    1633           2 : _PUBLIC_ bool cli_credentials_parse_password_file(struct cli_credentials *credentials, const char *file, enum credentials_obtained obtained)
    1634             : {
    1635           2 :         int fd = open(file, O_RDONLY, 0);
    1636           0 :         bool ret;
    1637             : 
    1638           2 :         if (fd < 0) {
    1639           0 :                 fprintf(stderr, "Error opening password file %s: %s\n",
    1640           0 :                                 file, strerror(errno));
    1641           0 :                 return false;
    1642             :         }
    1643             : 
    1644           2 :         ret = cli_credentials_parse_password_fd(credentials, fd, obtained);
    1645             : 
    1646           2 :         close(fd);
    1647             : 
    1648           2 :         return ret;
    1649             : }
    1650             : 
    1651             : 
    1652             : /**
    1653             :  * Read a file descriptor, and parse it for a password (eg from a file or stdin)
    1654             :  *
    1655             :  * @param credentials Credentials structure on which to set the password
    1656             :  * @param fd open file descriptor to read the password from
    1657             :  * @param obtained This enum describes how 'specified' this password is
    1658             :  */
    1659             : 
    1660           4 : _PUBLIC_ bool cli_credentials_parse_password_fd(struct cli_credentials *credentials,
    1661             :                                        int fd, enum credentials_obtained obtained)
    1662             : {
    1663           0 :         char *p;
    1664           0 :         char pass[128];
    1665             : 
    1666           4 :         if (credentials->password_obtained >= obtained) {
    1667           0 :                 return false;
    1668             :         }
    1669             : 
    1670           4 :         for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */
    1671          50 :                 p && p - pass < sizeof(pass) - 1;) {
    1672          46 :                 switch (read(fd, p, 1)) {
    1673          46 :                 case 1:
    1674          46 :                         if (*p != '\n' && *p != '\0') {
    1675          42 :                                 *++p = '\0'; /* advance p, and null-terminate pass */
    1676          42 :                                 break;
    1677             :                         }
    1678             : 
    1679           0 :                         FALL_THROUGH;
    1680             :                 case 0:
    1681           4 :                         if (p - pass) {
    1682           4 :                                 *p = '\0'; /* null-terminate it, just in case... */
    1683           4 :                                 p = NULL; /* then force the loop condition to become false */
    1684           4 :                                 break;
    1685             :                         }
    1686             : 
    1687           0 :                         fprintf(stderr,
    1688             :                                 "Error reading password from file descriptor "
    1689             :                                 "%d: empty password\n",
    1690             :                                 fd);
    1691           0 :                         return false;
    1692             : 
    1693           0 :                 default:
    1694           0 :                         fprintf(stderr, "Error reading password from file descriptor %d: %s\n",
    1695           0 :                                         fd, strerror(errno));
    1696           0 :                         return false;
    1697             :                 }
    1698             :         }
    1699             : 
    1700           4 :         cli_credentials_set_password(credentials, pass, obtained);
    1701           4 :         return true;
    1702             : }
    1703             : 
    1704             : /**
    1705             :  * @brief Set the SMB signing state to request for a SMB connection.
    1706             :  *
    1707             :  * @param[in]  creds          The credentials structure to update.
    1708             :  *
    1709             :  * @param[in]  signing_state  The signing state to set.
    1710             :  *
    1711             :  * @param obtained            This way the described signing state was specified.
    1712             :  *
    1713             :  * @return true if we could set the signing state, false otherwise.
    1714             :  */
    1715        3601 : _PUBLIC_ bool cli_credentials_set_smb_signing(struct cli_credentials *creds,
    1716             :                                               enum smb_signing_setting signing_state,
    1717             :                                               enum credentials_obtained obtained)
    1718             : {
    1719        3601 :         if (obtained >= creds->signing_state_obtained) {
    1720        3601 :                 creds->signing_state_obtained = obtained;
    1721        3601 :                 creds->signing_state = signing_state;
    1722        3601 :                 return true;
    1723             :         }
    1724             : 
    1725           0 :         return false;
    1726             : }
    1727             : 
    1728             : /**
    1729             :  * @brief Obtain the SMB signing state from a credentials structure.
    1730             :  *
    1731             :  * @param[in]  creds  The credential structure to obtain the SMB signing state
    1732             :  *                    from.
    1733             :  *
    1734             :  * @return The SMB signing state.
    1735             :  */
    1736             : _PUBLIC_ enum smb_signing_setting
    1737       17826 : cli_credentials_get_smb_signing(struct cli_credentials *creds)
    1738             : {
    1739       17826 :         return creds->signing_state;
    1740             : }
    1741             : 
    1742             : /**
    1743             :  * @brief Set the SMB IPC signing state to request for a SMB connection.
    1744             :  *
    1745             :  * @param[in]  creds          The credentials structure to update.
    1746             :  *
    1747             :  * @param[in]  signing_state  The signing state to set.
    1748             :  *
    1749             :  * @param obtained            This way the described signing state was specified.
    1750             :  *
    1751             :  * @return true if we could set the signing state, false otherwise.
    1752             :  */
    1753             : _PUBLIC_ bool
    1754         104 : cli_credentials_set_smb_ipc_signing(struct cli_credentials *creds,
    1755             :                                     enum smb_signing_setting ipc_signing_state,
    1756             :                                     enum credentials_obtained obtained)
    1757             : {
    1758         104 :         if (obtained >= creds->ipc_signing_state_obtained) {
    1759         104 :                 creds->ipc_signing_state_obtained = obtained;
    1760         104 :                 creds->ipc_signing_state = ipc_signing_state;
    1761         104 :                 return true;
    1762             :         }
    1763             : 
    1764           0 :         return false;
    1765             : }
    1766             : 
    1767             : /**
    1768             :  * @brief Obtain the SMB IPC signing state from a credentials structure.
    1769             :  *
    1770             :  * @param[in]  creds  The credential structure to obtain the SMB IPC signing
    1771             :  *                    state from.
    1772             :  *
    1773             :  * @return The SMB signing state.
    1774             :  */
    1775             : _PUBLIC_ enum smb_signing_setting
    1776        1628 : cli_credentials_get_smb_ipc_signing(struct cli_credentials *creds)
    1777             : {
    1778        1628 :         return creds->ipc_signing_state;
    1779             : }
    1780             : 
    1781             : /**
    1782             :  * @brief Set the SMB encryption state to request for a SMB connection.
    1783             :  *
    1784             :  * @param[in]  creds  The credentials structure to update.
    1785             :  *
    1786             :  * @param[in]  encryption_state  The encryption state to set.
    1787             :  *
    1788             :  * @param obtained  This way the described encryption state was specified.
    1789             :  *
    1790             :  * @return true if we could set the encryption state, false otherwise.
    1791             :  */
    1792        1645 : _PUBLIC_ bool cli_credentials_set_smb_encryption(struct cli_credentials *creds,
    1793             :                                                  enum smb_encryption_setting encryption_state,
    1794             :                                                  enum credentials_obtained obtained)
    1795             : {
    1796        1645 :         if (obtained >= creds->encryption_state_obtained) {
    1797        1645 :                 creds->encryption_state_obtained = obtained;
    1798        1645 :                 creds->encryption_state = encryption_state;
    1799        1645 :                 return true;
    1800             :         }
    1801             : 
    1802           0 :         return false;
    1803             : }
    1804             : 
    1805          14 : static const char *obtained_to_str(enum credentials_obtained obtained)
    1806             : {
    1807          14 :         switch (obtained) {
    1808           0 :         case CRED_UNINITIALISED:
    1809           0 :                 return "CRED_UNINITIALISED";
    1810           0 :         case CRED_SMB_CONF:
    1811           0 :                 return "CRED_SMB_CONF";
    1812           0 :         case CRED_CALLBACK:
    1813           0 :                 return "CRED_CALLBACK";
    1814           0 :         case CRED_GUESS_ENV:
    1815           0 :                 return "CRED_GUESS_ENV";
    1816           0 :         case CRED_GUESS_FILE:
    1817           0 :                 return "CRED_GUESS_FILE";
    1818           0 :         case CRED_CALLBACK_RESULT:
    1819           0 :                 return "CRED_CALLBACK_RESULT";
    1820           3 :         case CRED_SPECIFIED:
    1821           3 :                 return "CRED_SPECIFIED";
    1822             :         }
    1823             : 
    1824             :         /* Never reached */
    1825           0 :         return "";
    1826             : }
    1827             : 
    1828           1 : static const char *krb5_state_to_str(enum credentials_use_kerberos krb5_state)
    1829             : {
    1830           1 :         switch (krb5_state) {
    1831           0 :         case CRED_USE_KERBEROS_DISABLED:
    1832           0 :                 return "CRED_USE_KERBEROS_DISABLED";
    1833           1 :         case CRED_USE_KERBEROS_DESIRED:
    1834           1 :                 return "CRED_USE_KERBEROS_DESIRED";
    1835           0 :         case CRED_USE_KERBEROS_REQUIRED:
    1836           0 :                 return "CRED_USE_KERBEROS_REQUIRED";
    1837             :         }
    1838             : 
    1839             :         /* Never reached */
    1840           0 :         return "";
    1841             : }
    1842             : 
    1843           1 : static const char *krb5_fwd_to_str(enum credentials_krb_forwardable krb5_fwd)
    1844             : {
    1845           1 :         switch (krb5_fwd) {
    1846           0 :         case CRED_AUTO_KRB_FORWARDABLE:
    1847           0 :                 return "CRED_AUTO_KRB_FORWARDABLE";
    1848           0 :         case CRED_NO_KRB_FORWARDABLE:
    1849           0 :                 return "CRED_NO_KRB_FORWARDABLE";
    1850           0 :         case CRED_FORCE_KRB_FORWARDABLE:
    1851           0 :                 return "CRED_FORCE_KRB_FORWARDABLE";
    1852             :         }
    1853             : 
    1854             :         /* Never reached */
    1855           0 :         return "";
    1856             : }
    1857             : 
    1858           2 : static const char *signing_state_to_str(enum smb_signing_setting signing_state)
    1859             : {
    1860           2 :         switch(signing_state) {
    1861           0 :         case SMB_SIGNING_IPC_DEFAULT:
    1862           0 :                 return "SMB_SIGNING_IPC_DEFAULT";
    1863           1 :         case SMB_SIGNING_DEFAULT:
    1864           1 :                 return "SMB_SIGNING_DEFAULT";
    1865           0 :         case SMB_SIGNING_OFF:
    1866           0 :                 return "SMB_SIGNING_OFF";
    1867           0 :         case SMB_SIGNING_IF_REQUIRED:
    1868           0 :                 return "SMB_SIGNING_IF_REQUIRED";
    1869           0 :         case SMB_SIGNING_DESIRED:
    1870           0 :                 return "SMB_SIGNING_DESIRED";
    1871           1 :         case SMB_SIGNING_REQUIRED:
    1872           1 :                 return "SMB_SIGNING_REQUIRED";
    1873             :         }
    1874             : 
    1875             :         /* Never reached */
    1876           0 :         return "";
    1877             : }
    1878             : 
    1879           1 : static const char *encryption_state_to_str(enum smb_encryption_setting encryption_state)
    1880             : {
    1881           1 :         switch(encryption_state) {
    1882           0 :         case SMB_ENCRYPTION_DEFAULT:
    1883           0 :                 return "SMB_ENCRYPTION_DEFAULT";
    1884           0 :         case SMB_ENCRYPTION_OFF:
    1885           0 :                 return "SMB_ENCRYPTION_OFF";
    1886           0 :         case SMB_ENCRYPTION_IF_REQUIRED:
    1887           0 :                 return "SMB_ENCRYPTION_IF_REQUIRED";
    1888           0 :         case SMB_ENCRYPTION_DESIRED:
    1889           0 :                 return "SMB_ENCRYPTION_DESIRED";
    1890           0 :         case SMB_ENCRYPTION_REQUIRED:
    1891           0 :                 return "SMB_ENCRYPTION_REQUIRED";
    1892             :         }
    1893             : 
    1894             :         /* Never reached */
    1895           0 :         return "";
    1896             : }
    1897             : 
    1898           1 : _PUBLIC_ void cli_credentials_dump(struct cli_credentials *creds)
    1899             : {
    1900           1 :         DBG_ERR("CLI_CREDENTIALS:\n");
    1901           1 :         DBG_ERR("\n");
    1902           2 :         DBG_ERR("  Username: %s - %s\n",
    1903             :                 creds->username,
    1904             :                 obtained_to_str(creds->username_obtained));
    1905           1 :         DBG_ERR("  Workstation: %s - %s\n",
    1906             :                 creds->workstation,
    1907             :                 obtained_to_str(creds->workstation_obtained));
    1908           2 :         DBG_ERR("  Domain: %s - %s\n",
    1909             :                 creds->domain,
    1910             :                 obtained_to_str(creds->domain_obtained));
    1911           2 :         DBG_ERR("  Password: %s - %s\n",
    1912             :                 creds->password != NULL ? "*SECRET*" : "NULL",
    1913             :                 obtained_to_str(creds->password_obtained));
    1914           2 :         DBG_ERR("  Old password: %s\n",
    1915             :                 creds->old_password != NULL ? "*SECRET*" : "NULL");
    1916           1 :         DBG_ERR("  Password tries: %u\n",
    1917             :                 creds->password_tries);
    1918           1 :         DBG_ERR("  Realm: %s - %s\n",
    1919             :                 creds->realm,
    1920             :                 obtained_to_str(creds->realm_obtained));
    1921           1 :         DBG_ERR("  Principal: %s - %s\n",
    1922             :                 creds->principal,
    1923             :                 obtained_to_str(creds->principal_obtained));
    1924           1 :         DBG_ERR("  Salt principal: %s\n",
    1925             :                 creds->salt_principal);
    1926           1 :         DBG_ERR("  Impersonate principal: %s\n",
    1927             :                 creds->impersonate_principal);
    1928           1 :         DBG_ERR("  Self service: %s\n",
    1929             :                 creds->self_service);
    1930           1 :         DBG_ERR("  Target service: %s\n",
    1931             :                 creds->target_service);
    1932           2 :         DBG_ERR("  Kerberos state: %s - %s\n",
    1933             :                 krb5_state_to_str(creds->kerberos_state),
    1934             :                 obtained_to_str(creds->kerberos_state_obtained));
    1935           1 :         DBG_ERR("  Kerberos forwardable ticket: %s\n",
    1936             :                 krb5_fwd_to_str(creds->krb_forwardable));
    1937           2 :         DBG_ERR("  Signing state: %s - %s\n",
    1938             :                 signing_state_to_str(creds->signing_state),
    1939             :                 obtained_to_str(creds->signing_state_obtained));
    1940           2 :         DBG_ERR("  IPC signing state: %s - %s\n",
    1941             :                 signing_state_to_str(creds->ipc_signing_state),
    1942             :                 obtained_to_str(creds->ipc_signing_state_obtained));
    1943           1 :         DBG_ERR("  Encryption state: %s - %s\n",
    1944             :                 encryption_state_to_str(creds->encryption_state),
    1945             :                 obtained_to_str(creds->encryption_state_obtained));
    1946           1 :         DBG_ERR("  Gensec features: %#X\n",
    1947             :                 creds->gensec_features);
    1948           1 :         DBG_ERR("  Forced sasl mech: %s\n",
    1949             :                 creds->forced_sasl_mech);
    1950           1 :         DBG_ERR("  CCACHE: %p - %s\n",
    1951             :                 creds->ccache,
    1952             :                 obtained_to_str(creds->ccache_obtained));
    1953           1 :         DBG_ERR("  CLIENT_GSS_CREDS: %p - %s\n",
    1954             :                 creds->client_gss_creds,
    1955             :                 obtained_to_str(creds->client_gss_creds_obtained));
    1956           1 :         DBG_ERR("  SERVER_GSS_CREDS: %p - %s\n",
    1957             :                 creds->server_gss_creds,
    1958             :                 obtained_to_str(creds->server_gss_creds_obtained));
    1959           1 :         DBG_ERR("  KEYTAB: %p - %s\n",
    1960             :                 creds->keytab,
    1961             :                 obtained_to_str(creds->keytab_obtained));
    1962           1 :         DBG_ERR("  KVNO: %u\n",
    1963             :                 creds->kvno);
    1964           1 :         DBG_ERR("\n");
    1965           1 : }
    1966             : 
    1967             : /**
    1968             :  * @brief Obtain the SMB encryption state from a credentials structure.
    1969             :  *
    1970             :  * @param[in]  creds  The credential structure to obtain the SMB encryption state
    1971             :  *                    from.
    1972             :  *
    1973             :  * @return The SMB signing state.
    1974             :  */
    1975             : _PUBLIC_ enum smb_encryption_setting
    1976       65977 : cli_credentials_get_smb_encryption(struct cli_credentials *creds)
    1977             : {
    1978       65977 :         return creds->encryption_state;
    1979             : }
    1980             : 
    1981             : /**
    1982             :  * Encrypt a data blob using the session key and the negotiated encryption
    1983             :  * algorithm
    1984             :  *
    1985             :  * @param state Credential state, contains the session key and algorithm
    1986             :  * @param data Data blob containing the data to be encrypted.
    1987             :  *
    1988             :  */
    1989          98 : _PUBLIC_ NTSTATUS netlogon_creds_session_encrypt(
    1990             :         struct netlogon_creds_CredentialState *state,
    1991             :         DATA_BLOB data)
    1992             : {
    1993           0 :         NTSTATUS status;
    1994             : 
    1995          98 :         if (data.data == NULL || data.length == 0) {
    1996           0 :                 DBG_ERR("Nothing to encrypt "
    1997             :                         "data.data == NULL or data.length == 0\n");
    1998           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1999             :         }
    2000             :         /*
    2001             :          * Don't crypt an all-zero password it will give away the
    2002             :          * NETLOGON pipe session key .
    2003             :          */
    2004          98 :         if (all_zero(data.data, data.length)) {
    2005           0 :                 DBG_ERR("Supplied data all zeros, could leak session key\n");
    2006           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2007             :         }
    2008          98 :         if (state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
    2009          98 :                 status = netlogon_creds_aes_encrypt(state,
    2010             :                                                     data.data,
    2011             :                                                     data.length);
    2012           0 :         } else if (state->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    2013           0 :                 status = netlogon_creds_arcfour_crypt(state,
    2014             :                                                       data.data,
    2015             :                                                       data.length);
    2016             :         } else {
    2017           0 :                 DBG_ERR("Unsupported encryption option negotiated\n");
    2018           0 :                 status = NT_STATUS_NOT_SUPPORTED;
    2019             :         }
    2020          98 :         if (!NT_STATUS_IS_OK(status)) {
    2021           0 :                 return status;
    2022             :         }
    2023          98 :         return NT_STATUS_OK;
    2024             : }
    2025             : 

Generated by: LCOV version 1.14