LCOV - code coverage report
Current view: top level - source3/passdb - secrets.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 74 229 32.3 %
Date: 2024-04-21 15:09:00 Functions: 11 20 55.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Copyright (C) Andrew Tridgell 1992-2001
       4             :    Copyright (C) Andrew Bartlett      2002
       5             :    Copyright (C) Rafal Szczesniak     2002
       6             :    Copyright (C) Tim Potter           2001
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : /* the Samba secrets database stores any generated, private information
      23             :    such as the local SID and machine trust password */
      24             : 
      25             : #include "includes.h"
      26             : #include "system/filesys.h"
      27             : #include "../libcli/auth/libcli_auth.h"
      28             : #include "librpc/gen_ndr/ndr_secrets.h"
      29             : #include "secrets.h"
      30             : #include "dbwrap/dbwrap.h"
      31             : #include "dbwrap/dbwrap_open.h"
      32             : #include "../libcli/security/security.h"
      33             : #include "util_tdb.h"
      34             : #include "auth/credentials/credentials.h"
      35             : 
      36             : #undef DBGC_CLASS
      37             : #define DBGC_CLASS DBGC_PASSDB
      38             : 
      39             : static struct db_context *db_ctx;
      40             : 
      41             : /* open up the secrets database with specified private_dir path */
      42      208126 : bool secrets_init_path(const char *private_dir)
      43             : {
      44      208126 :         char *fname = NULL;
      45        7417 :         TALLOC_CTX *frame;
      46             : 
      47      208126 :         if (db_ctx != NULL) {
      48      182295 :                 return True;
      49             :         }
      50             : 
      51       18478 :         if (private_dir == NULL) {
      52           0 :                 return False;
      53             :         }
      54             : 
      55       18478 :         frame = talloc_stackframe();
      56       18478 :         fname = talloc_asprintf(frame, "%s/secrets.tdb", private_dir);
      57       18478 :         if (fname == NULL) {
      58           0 :                 TALLOC_FREE(frame);
      59           0 :                 return False;
      60             :         }
      61             : 
      62       18478 :         db_ctx = db_open(NULL, fname, 0,
      63             :                          TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
      64             :                          DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
      65             : 
      66       18478 :         if (db_ctx == NULL) {
      67           0 :                 DEBUG(0,("Failed to open %s\n", fname));
      68           0 :                 TALLOC_FREE(frame);
      69           0 :                 return False;
      70             :         }
      71             : 
      72       18478 :         TALLOC_FREE(frame);
      73       18414 :         return True;
      74             : }
      75             : 
      76             : /* open up the secrets database */
      77      138492 : bool secrets_init(void)
      78             : {
      79      138492 :         return secrets_init_path(lp_private_dir());
      80             : }
      81             : 
      82       71848 : struct db_context *secrets_db_ctx(void)
      83             : {
      84       71848 :         if (!secrets_init()) {
      85           0 :                 return NULL;
      86             :         }
      87             : 
      88       71848 :         return db_ctx;
      89             : }
      90             : 
      91             : /*
      92             :  * close secrets.tdb
      93             :  */
      94        1065 : void secrets_shutdown(void)
      95             : {
      96        1065 :         TALLOC_FREE(db_ctx);
      97        1065 : }
      98             : 
      99             : /* read a entry from the secrets database - the caller must free the result
     100             :    if size is non-null then the size of the entry is put in there
     101             :  */
     102       56712 : void *secrets_fetch(const char *key, size_t *size)
     103             : {
     104        1810 :         TDB_DATA dbuf;
     105        1810 :         void *result;
     106        1810 :         NTSTATUS status;
     107             : 
     108       56712 :         if (!secrets_init()) {
     109           0 :                 return NULL;
     110             :         }
     111             : 
     112       56712 :         status = dbwrap_fetch(db_ctx, talloc_tos(), string_tdb_data(key),
     113             :                               &dbuf);
     114       56712 :         if (!NT_STATUS_IS_OK(status)) {
     115       13140 :                 return NULL;
     116             :         }
     117             : 
     118       43499 :         result = smb_memdup(dbuf.dptr, dbuf.dsize);
     119       43499 :         if (result == NULL) {
     120           0 :                 return NULL;
     121             :         }
     122             :         /*
     123             :          * secrets_fetch() is a generic code and may be used for sensitive data,
     124             :          * so clear the local dbuf.dptr memory via BURN_PTR_SIZE().
     125             :          * The future plan is to convert secrets_fetch() to talloc.
     126             :          * That would improve performance via:
     127             :          * - avoid smb_memdup() above, instead directly return dbuf.dptr
     128             :          * - BURN_PTR_SIZE() will be done not here but in the caller and only
     129             :          *   if the caller asks for sensitive data.
     130             :          */
     131       43499 :         BURN_PTR_SIZE(dbuf.dptr, dbuf.dsize);
     132       43499 :         TALLOC_FREE(dbuf.dptr);
     133             : 
     134       43499 :         if (size) {
     135       38621 :                 *size = dbuf.dsize;
     136             :         }
     137             : 
     138       41762 :         return result;
     139             : }
     140             : 
     141             : /* store a secrets entry
     142             :  */
     143        2414 : bool secrets_store(const char *key, const void *data, size_t size)
     144             : {
     145         170 :         NTSTATUS status;
     146             : 
     147        2414 :         if (!secrets_init()) {
     148           0 :                 return false;
     149             :         }
     150             : 
     151        2414 :         status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
     152             :                                     make_tdb_data((const uint8_t *)data, size),
     153             :                                     TDB_REPLACE);
     154        2414 :         return NT_STATUS_IS_OK(status);
     155             : }
     156             : 
     157           0 : bool secrets_store_creds(struct cli_credentials *creds)
     158             : {
     159           0 :         const char *p = NULL;
     160           0 :         bool ok;
     161             : 
     162           0 :         p = cli_credentials_get_username(creds);
     163           0 :         if (p == NULL) {
     164           0 :                 return false;
     165             :         }
     166             : 
     167           0 :         ok = secrets_store(SECRETS_AUTH_USER, p, strlen(p) + 1);
     168           0 :         if (!ok) {
     169           0 :                 DBG_ERR("Failed storing auth user name\n");
     170           0 :                 return false;
     171             :         }
     172             : 
     173             : 
     174           0 :         p = cli_credentials_get_domain(creds);
     175           0 :         if (p == NULL) {
     176           0 :                 return false;
     177             :         }
     178             : 
     179           0 :         ok = secrets_store(SECRETS_AUTH_DOMAIN, p, strlen(p) + 1);
     180           0 :         if (!ok) {
     181           0 :                 DBG_ERR("Failed storing auth domain name\n");
     182           0 :                 return false;
     183             :         }
     184             : 
     185             : 
     186           0 :         p = cli_credentials_get_password(creds);
     187           0 :         if (p == NULL) {
     188           0 :                 return false;
     189             :         }
     190             : 
     191           0 :         ok = secrets_store(SECRETS_AUTH_PASSWORD, p, strlen(p) + 1);
     192           0 :         if (!ok) {
     193           0 :                 DBG_ERR("Failed storing auth password\n");
     194           0 :                 return false;
     195             :         }
     196             : 
     197           0 :         return true;
     198             : }
     199             : 
     200             : 
     201             : /* delete a secets database entry
     202             :  */
     203         492 : bool secrets_delete_entry(const char *key)
     204             : {
     205           9 :         NTSTATUS status;
     206         492 :         if (!secrets_init()) {
     207           0 :                 return false;
     208             :         }
     209             : 
     210         492 :         status = dbwrap_trans_delete(db_ctx, string_tdb_data(key));
     211             : 
     212         492 :         return NT_STATUS_IS_OK(status);
     213             : }
     214             : 
     215             : /*
     216             :  * Deletes the key if it exists.
     217             :  */
     218        1323 : bool secrets_delete(const char *key)
     219             : {
     220          21 :         bool exists;
     221             : 
     222        1323 :         if (!secrets_init()) {
     223           0 :                 return false;
     224             :         }
     225             : 
     226        1323 :         exists = dbwrap_exists(db_ctx, string_tdb_data(key));
     227        1323 :         if (!exists) {
     228         926 :                 return true;
     229             :         }
     230             : 
     231         376 :         return secrets_delete_entry(key);
     232             : }
     233             : 
     234             : /**
     235             :  * Form a key for fetching a trusted domain password
     236             :  *
     237             :  * @param domain trusted domain name
     238             :  *
     239             :  * @return stored password's key
     240             :  **/
     241         804 : static char *trustdom_keystr(const char *domain)
     242             : {
     243           0 :         char *keystr;
     244             : 
     245         804 :         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
     246             :                                             SECRETS_DOMTRUST_ACCT_PASS,
     247             :                                             domain);
     248         804 :         SMB_ASSERT(keystr != NULL);
     249         804 :         return keystr;
     250             : }
     251             : 
     252             : /************************************************************************
     253             :  Routine to get account password to trusted domain
     254             : ************************************************************************/
     255             : 
     256         800 : bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
     257             :                                            struct dom_sid *sid, time_t *pass_last_set_time)
     258             : {
     259           0 :         struct TRUSTED_DOM_PASS pass;
     260           0 :         enum ndr_err_code ndr_err;
     261             : 
     262             :         /* unpacking structures */
     263           0 :         DATA_BLOB blob;
     264             : 
     265             :         /* fetching trusted domain password structure */
     266         800 :         if (!(blob.data = (uint8_t *)secrets_fetch(trustdom_keystr(domain),
     267             :                                                    &blob.length))) {
     268         800 :                 DEBUG(5, ("secrets_fetch failed!\n"));
     269         800 :                 return False;
     270             :         }
     271             : 
     272             :         /* unpack trusted domain password */
     273           0 :         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
     274             :                         (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
     275             : 
     276             :         /* This blob is NOT talloc based! */
     277           0 :         BURN_FREE(blob.data, blob.length);
     278             : 
     279           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     280           0 :                 return false;
     281             :         }
     282             : 
     283           0 :         if (pass.pass != NULL) {
     284           0 :                 talloc_keep_secret(discard_const_p(char, pass.pass));
     285             :         }
     286             : 
     287             :         /* the trust's password */
     288           0 :         if (pwd) {
     289           0 :                 *pwd = SMB_STRDUP(pass.pass);
     290           0 :                 if (!*pwd) {
     291           0 :                         return False;
     292             :                 }
     293             :         }
     294             : 
     295             :         /* last change time */
     296           0 :         if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
     297             : 
     298             :         /* domain sid */
     299           0 :         if (sid != NULL) sid_copy(sid, &pass.domain_sid);
     300             : 
     301           0 :         return True;
     302             : }
     303             : 
     304             : /**
     305             :  * Routine to store the password for trusted domain
     306             :  *
     307             :  * @param domain remote domain name
     308             :  * @param pwd plain text password of trust relationship
     309             :  * @param sid remote domain sid
     310             :  *
     311             :  * @return true if succeeded
     312             :  **/
     313             : 
     314           4 : bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
     315             :                                            const struct dom_sid *sid)
     316             : {
     317           0 :         bool ret;
     318             : 
     319             :         /* packing structures */
     320           0 :         DATA_BLOB blob;
     321           0 :         enum ndr_err_code ndr_err;
     322           0 :         struct TRUSTED_DOM_PASS pass;
     323           4 :         ZERO_STRUCT(pass);
     324             : 
     325           4 :         pass.uni_name = domain;
     326           4 :         pass.uni_name_len = strlen(domain)+1;
     327             : 
     328             :         /* last change time */
     329           4 :         pass.mod_time = time(NULL);
     330             : 
     331             :         /* password of the trust */
     332           4 :         pass.pass_len = strlen(pwd);
     333           4 :         pass.pass = pwd;
     334             : 
     335             :         /* domain sid */
     336           4 :         sid_copy(&pass.domain_sid, sid);
     337             : 
     338           4 :         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass,
     339             :                         (ndr_push_flags_fn_t)ndr_push_TRUSTED_DOM_PASS);
     340           4 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     341           0 :                 return false;
     342             :         }
     343             : 
     344           4 :         ret = secrets_store(trustdom_keystr(domain), blob.data, blob.length);
     345             : 
     346             :         /* This blob is talloc based. */
     347           4 :         data_blob_clear_free(&blob);
     348             : 
     349           4 :         return ret;
     350             : }
     351             : 
     352             : /************************************************************************
     353             :  Routine to delete the password for trusted domain
     354             : ************************************************************************/
     355             : 
     356           0 : bool trusted_domain_password_delete(const char *domain)
     357             : {
     358           0 :         return secrets_delete_entry(trustdom_keystr(domain));
     359             : }
     360             : 
     361           0 : bool secrets_store_ldap_pw(const char* dn, char* pw)
     362             : {
     363           0 :         char *key = NULL;
     364           0 :         bool ret;
     365             : 
     366           0 :         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
     367           0 :                 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
     368           0 :                 return False;
     369             :         }
     370             : 
     371           0 :         ret = secrets_store(key, pw, strlen(pw)+1);
     372             : 
     373           0 :         SAFE_FREE(key);
     374           0 :         return ret;
     375             : }
     376             : 
     377             : /*******************************************************************
     378             :  Find the ldap password.
     379             : ******************************************************************/
     380             : 
     381           0 : bool fetch_ldap_pw(char **dn, char** pw)
     382             : {
     383           0 :         char *key = NULL;
     384           0 :         size_t size = 0;
     385             : 
     386           0 :         *dn = smb_xstrdup(lp_ldap_admin_dn());
     387             : 
     388           0 :         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
     389           0 :                 SAFE_FREE(*dn);
     390           0 :                 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
     391           0 :                 return false;
     392             :         }
     393             : 
     394           0 :         *pw=(char *)secrets_fetch(key, &size);
     395           0 :         SAFE_FREE(key);
     396             : 
     397           0 :         if (*pw == NULL || size == 0 || (*pw)[size-1] != '\0') {
     398           0 :                 DBG_ERR("No valid password for %s\n", *dn);
     399           0 :                 BURN_FREE_STR(*pw);
     400           0 :                 SAFE_FREE(*dn);
     401           0 :                 return false;
     402             :         }
     403             : 
     404           0 :         return true;
     405             : }
     406             : 
     407             : /*******************************************************************************
     408             :  Store a complete AFS keyfile into secrets.tdb.
     409             : *******************************************************************************/
     410             : 
     411           0 : bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
     412             : {
     413           0 :         fstring key;
     414             : 
     415           0 :         if ((cell == NULL) || (keyfile == NULL))
     416           0 :                 return False;
     417             : 
     418           0 :         if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
     419           0 :                 return False;
     420             : 
     421           0 :         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
     422           0 :         return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
     423             : }
     424             : 
     425             : /*******************************************************************************
     426             :  Fetch the current (highest) AFS key from secrets.tdb
     427             : *******************************************************************************/
     428           0 : bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
     429             : {
     430           0 :         fstring key;
     431           0 :         struct afs_keyfile *keyfile;
     432           0 :         size_t size = 0;
     433           0 :         uint32_t i;
     434             : 
     435           0 :         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
     436             : 
     437           0 :         keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
     438             : 
     439           0 :         if (keyfile == NULL)
     440           0 :                 return False;
     441             : 
     442           0 :         if (size != sizeof(struct afs_keyfile)) {
     443           0 :                 BURN_FREE(keyfile, sizeof(*keyfile));
     444           0 :                 return False;
     445             :         }
     446             : 
     447           0 :         i = ntohl(keyfile->nkeys);
     448             : 
     449           0 :         if (i > SECRETS_AFS_MAXKEYS) {
     450           0 :                 BURN_FREE(keyfile, sizeof(*keyfile));
     451           0 :                 return False;
     452             :         }
     453             : 
     454           0 :         *result = keyfile->entry[i-1];
     455             : 
     456           0 :         result->kvno = ntohl(result->kvno);
     457             : 
     458           0 :         BURN_FREE(keyfile, sizeof(*keyfile));
     459             : 
     460           0 :         return True;
     461             : }
     462             : 
     463             : /******************************************************************************
     464             :   When kerberos is not available, choose between anonymous or
     465             :   authenticated connections.
     466             : 
     467             :   We need to use an authenticated connection if DCs have the
     468             :   RestrictAnonymous registry entry set > 0, or the "Additional
     469             :   restrictions for anonymous connections" set in the win2k Local
     470             :   Security Policy.
     471             : 
     472             :   Caller to free() result in domain, username, password
     473             : *******************************************************************************/
     474           0 : void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
     475             : {
     476           0 :         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
     477           0 :         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
     478           0 :         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
     479             : 
     480           0 :         if (*username && **username) {
     481             : 
     482           0 :                 if (!*domain || !**domain) {
     483           0 :                         SAFE_FREE(*domain);
     484           0 :                         *domain = smb_xstrdup(lp_workgroup());
     485             :                 }
     486             : 
     487           0 :                 if (!*password || !**password) {
     488           0 :                         BURN_FREE_STR(*password);
     489           0 :                         *password = smb_xstrdup("");
     490             :                 }
     491             : 
     492           0 :                 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
     493             :                           *domain, *username));
     494             : 
     495             :         } else {
     496           0 :                 DEBUG(3, ("IPC$ connections done anonymously\n"));
     497           0 :                 SAFE_FREE(*username);
     498           0 :                 SAFE_FREE(*domain);
     499           0 :                 BURN_FREE_STR(*password);
     500           0 :                 *username = smb_xstrdup("");
     501           0 :                 *domain = smb_xstrdup("");
     502           0 :                 *password = smb_xstrdup("");
     503             :         }
     504           0 : }
     505             : 
     506           0 : bool secrets_store_generic(const char *owner, const char *key, const char *secret)
     507             : {
     508           0 :         char *tdbkey = NULL;
     509           0 :         bool ret;
     510             : 
     511           0 :         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
     512           0 :                 DEBUG(0, ("asprintf failed!\n"));
     513           0 :                 return False;
     514             :         }
     515             : 
     516           0 :         ret = secrets_store(tdbkey, secret, strlen(secret)+1);
     517             : 
     518           0 :         SAFE_FREE(tdbkey);
     519           0 :         return ret;
     520             : }
     521             : 
     522             : /*******************************************************************
     523             :  Find the ldap password.
     524             : ******************************************************************/
     525             : 
     526           0 : char *secrets_fetch_generic(const char *owner, const char *key)
     527             : {
     528           0 :         char *secret = NULL;
     529           0 :         char *tdbkey = NULL;
     530             : 
     531           0 :         if (( ! owner) || ( ! key)) {
     532           0 :                 DEBUG(1, ("Invalid Parameters\n"));
     533           0 :                 return NULL;
     534             :         }
     535             : 
     536           0 :         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
     537           0 :                 DEBUG(0, ("Out of memory!\n"));
     538           0 :                 return NULL;
     539             :         }
     540             : 
     541           0 :         secret = (char *)secrets_fetch(tdbkey, NULL);
     542           0 :         SAFE_FREE(tdbkey);
     543             : 
     544           0 :         return secret;
     545             : }
     546             : 

Generated by: LCOV version 1.14