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

Generated by: LCOV version 1.14