LCOV - code coverage report
Current view: top level - auth/credentials - credentials.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 593 822 72.1 %
Date: 2024-04-21 15:09:00 Functions: 59 72 81.9 %

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

Generated by: LCOV version 1.14