LCOV - code coverage report
Current view: top level - auth/credentials - credentials.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 552 783 70.5 %
Date: 2021-09-23 10:06:22 Functions: 58 71 81.7 %

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

Generated by: LCOV version 1.13