Fix valgrind memory leak in bug #6814 - Fixes for problems reported by valgrind
[nivanova/samba-autobuild/.git] / source3 / passdb / secrets.c
index a6adb904e23356b3e4f959442a66511bbaa4408b..29e06623960c4ce6a0a77c19d9827363d74f0450 100644 (file)
@@ -23,6 +23,7 @@
    such as the local SID and machine trust password */
 
 #include "includes.h"
+#include "../libcli/auth/libcli_auth.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
@@ -40,12 +41,12 @@ bool global_machine_password_needs_changing;
  *
  * @note Not called by systems with a working /dev/urandom.
  */
-static void get_rand_seed(int *new_seed)
+static void get_rand_seed(void *userdata, int *new_seed)
 {
        *new_seed = sys_getpid();
        if (db_ctx) {
-               dbwrap_change_int32_atomic(db_ctx, "INFO/random_seed",
-                                          new_seed, 1);
+               dbwrap_trans_change_int32_atomic(db_ctx, "INFO/random_seed",
+                                                new_seed, 1);
        }
 }
 
@@ -81,7 +82,7 @@ bool secrets_init(void)
         * This avoids a problem where systems without /dev/urandom
         * could send the same challenge to multiple clients
         */
-       set_rand_reseed_callback(get_rand_seed);
+       set_rand_reseed_callback(get_rand_seed, NULL);
 
        /* Ensure that the reseed is done now, while we are root, etc */
        generate_random_buffer(&dummy, sizeof(dummy));
@@ -391,7 +392,7 @@ void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
  Routine to get the default secure channel type for trust accounts
 ************************************************************************/
 
-uint32 get_default_sec_channel(void)
+enum netr_SchannelType get_default_sec_channel(void)
 {
        if (lp_server_role() == ROLE_DOMAIN_BDC ||
            lp_server_role() == ROLE_DOMAIN_PDC) {
@@ -411,7 +412,7 @@ uint32 get_default_sec_channel(void)
 bool secrets_fetch_trust_account_password_legacy(const char *domain,
                                                 uint8 ret_pwd[16],
                                                 time_t *pass_last_set_time,
-                                                uint32 *channel)
+                                                enum netr_SchannelType *channel)
 {
        struct machine_acct_pass *pass;
        size_t size = 0;
@@ -457,7 +458,7 @@ bool secrets_fetch_trust_account_password_legacy(const char *domain,
 
 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
                                          time_t *pass_last_set_time,
-                                         uint32 *channel)
+                                         enum netr_SchannelType *channel)
 {
        char *plaintext;
 
@@ -720,7 +721,7 @@ bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
        struct trusted_dom_pass pass;
        ZERO_STRUCT(pass);
 
-       if (!push_ucs2_allocate(&uni_dom_name, domain, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &uni_dom_name, domain, &converted_size)) {
                DEBUG(0, ("Could not convert domain name %s to unicode\n",
                          domain));
                return False;
@@ -728,7 +729,7 @@ bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
 
        strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
        pass.uni_name_len = strlen_w(uni_dom_name)+1;
-       SAFE_FREE(uni_dom_name);
+       TALLOC_FREE(uni_dom_name);
 
        /* last change time */
        pass.mod_time = time(NULL);
@@ -742,14 +743,14 @@ bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
 
        /* Calculate the length. */
        pass_len = tdb_trusted_dom_pass_pack(NULL, 0, &pass);
-       pass_buf = SMB_MALLOC_ARRAY(uint8, pass_len);
+       pass_buf = talloc_array(talloc_tos(), uint8, pass_len);
        if (!pass_buf) {
                return false;
        }
        pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_len, &pass);
        ret = secrets_store(trustdom_keystr(domain), (void *)pass_buf,
                        pass_len);
-       SAFE_FREE(pass_buf);
+       TALLOC_FREE(pass_buf);
        return ret;
 }
 
@@ -792,7 +793,8 @@ bool secrets_delete_domain_sid(const char *domain)
 the password is assumed to be a null terminated ascii string
 ************************************************************************/
 
-bool secrets_store_machine_password(const char *pass, const char *domain, uint32 sec_channel)
+bool secrets_store_machine_password(const char *pass, const char *domain,
+                                   enum netr_SchannelType sec_channel)
 {
        bool ret;
        uint32 last_change_time;
@@ -818,7 +820,7 @@ bool secrets_store_machine_password(const char *pass, const char *domain, uint32
 
 char *secrets_fetch_machine_password(const char *domain,
                                     time_t *pass_last_set_time,
-                                    uint32 *channel)
+                                    enum netr_SchannelType *channel)
 {
        char *ret;
        ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
@@ -889,6 +891,7 @@ bool fetch_ldap_pw(char **dn, char** pw)
        if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
                SAFE_FREE(*dn);
                DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
+               return false;
        }
 
        *pw=(char *)secrets_fetch(key, &size);
@@ -1133,7 +1136,11 @@ void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
  Open or create the schannel session store tdb.
 *******************************************************************************/
 
-static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
+#define SCHANNEL_STORE_VERSION_1 1
+#define SCHANNEL_STORE_VERSION_2 2 /* should not be used */
+#define SCHANNEL_STORE_VERSION_CURRENT SCHANNEL_STORE_VERSION_1
+
+TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
 {
        TDB_DATA vers;
        uint32 ver;
@@ -1152,21 +1159,28 @@ static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
                 return NULL;
         }
 
+ again:
        vers = tdb_fetch_bystring(tdb_sc, "SCHANNEL_STORE_VERSION");
        if (vers.dptr == NULL) {
                /* First opener, no version. */
-               SIVAL(&ver,0,1);
+               SIVAL(&ver,0,SCHANNEL_STORE_VERSION_CURRENT);
                vers.dptr = (uint8 *)&ver;
                vers.dsize = 4;
                tdb_store_bystring(tdb_sc, "SCHANNEL_STORE_VERSION", vers, TDB_REPLACE);
                vers.dptr = NULL;
        } else if (vers.dsize == 4) {
                ver = IVAL(vers.dptr,0);
-               if (ver != 1) {
-                       tdb_close(tdb_sc);
-                       tdb_sc = NULL;
+               if (ver == SCHANNEL_STORE_VERSION_2) {
                        DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n",
                                (int)ver, fname ));
+                       tdb_wipe_all(tdb_sc);
+                       goto again;
+               }
+               if (ver != SCHANNEL_STORE_VERSION_CURRENT) {
+                       DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n",
+                               (int)ver, fname ));
+                       tdb_close(tdb_sc);
+                       tdb_sc = NULL;
                }
        } else {
                tdb_close(tdb_sc);
@@ -1181,173 +1195,6 @@ static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
        return tdb_sc;
 }
 
-/******************************************************************************
- Store the schannel state after an AUTH2 call.
- Note we must be root here.
-*******************************************************************************/
-
-bool secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx,
-                               const char *remote_machine,
-                               const struct dcinfo *pdc)
-{
-       TDB_CONTEXT *tdb_sc = NULL;
-       TDB_DATA value;
-       bool ret;
-       char *keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
-                                                 SECRETS_SCHANNEL_STATE,
-                                                 remote_machine);
-       if (!keystr) {
-               return False;
-       }
-
-       /* Work out how large the record is. */
-       value.dsize = tdb_pack(NULL, 0, "dBBBBBfff",
-                               pdc->sequence,
-                               8, pdc->seed_chal.data,
-                               8, pdc->clnt_chal.data,
-                               8, pdc->srv_chal.data,
-                               16, pdc->sess_key,
-                               16, pdc->mach_pw,
-                               pdc->mach_acct,
-                               pdc->remote_machine,
-                               pdc->domain);
-
-       value.dptr = TALLOC_ARRAY(mem_ctx, uint8, value.dsize);
-       if (!value.dptr) {
-               TALLOC_FREE(keystr);
-               return False;
-       }
-
-       value.dsize = tdb_pack(value.dptr, value.dsize, "dBBBBBfff",
-                               pdc->sequence,
-                               8, pdc->seed_chal.data,
-                               8, pdc->clnt_chal.data,
-                               8, pdc->srv_chal.data,
-                               16, pdc->sess_key,
-                               16, pdc->mach_pw,
-                               pdc->mach_acct,
-                               pdc->remote_machine,
-                               pdc->domain);
-
-       tdb_sc = open_schannel_session_store(mem_ctx);
-       if (!tdb_sc) {
-               TALLOC_FREE(keystr);
-               TALLOC_FREE(value.dptr);
-               return False;
-       }
-
-       ret = (tdb_store_bystring(tdb_sc, keystr, value, TDB_REPLACE) == 0 ? True : False);
-
-       DEBUG(3,("secrets_store_schannel_session_info: stored schannel info with key %s\n",
-               keystr ));
-
-       tdb_close(tdb_sc);
-       TALLOC_FREE(keystr);
-       TALLOC_FREE(value.dptr);
-       return ret;
-}
-
-/******************************************************************************
- Restore the schannel state on a client reconnect.
- Note we must be root here.
-*******************************************************************************/
-
-bool secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
-                               const char *remote_machine,
-                               struct dcinfo **ppdc)
-{
-       TDB_CONTEXT *tdb_sc = NULL;
-       TDB_DATA value;
-       unsigned char *pseed_chal = NULL;
-       unsigned char *pclnt_chal = NULL;
-       unsigned char *psrv_chal = NULL;
-       unsigned char *psess_key = NULL;
-       unsigned char *pmach_pw = NULL;
-       uint32 l1, l2, l3, l4, l5;
-       int ret;
-       struct dcinfo *pdc = NULL;
-       char *keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
-                                                 SECRETS_SCHANNEL_STATE,
-                                                 remote_machine);
-
-       *ppdc = NULL;
-
-       if (!keystr) {
-               return False;
-       }
-
-       tdb_sc = open_schannel_session_store(mem_ctx);
-       if (!tdb_sc) {
-               TALLOC_FREE(keystr);
-               return False;
-       }
-
-       value = tdb_fetch_bystring(tdb_sc, keystr);
-       if (!value.dptr) {
-               DEBUG(0,("secrets_restore_schannel_session_info: Failed to find entry with key %s\n",
-                       keystr ));
-               tdb_close(tdb_sc);
-               return False;
-       }
-
-       pdc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
-
-       /* Retrieve the record. */
-       ret = tdb_unpack(value.dptr, value.dsize, "dBBBBBfff",
-                               &pdc->sequence,
-                               &l1, &pseed_chal,
-                               &l2, &pclnt_chal,
-                               &l3, &psrv_chal,
-                               &l4, &psess_key,
-                               &l5, &pmach_pw,
-                               &pdc->mach_acct,
-                               &pdc->remote_machine,
-                               &pdc->domain);
-
-       if (ret == -1 || l1 != 8 || l2 != 8 || l3 != 8 || l4 != 16 || l5 != 16) {
-               /* Bad record - delete it. */
-               tdb_delete_bystring(tdb_sc, keystr);
-               tdb_close(tdb_sc);
-               TALLOC_FREE(keystr);
-               TALLOC_FREE(pdc);
-               SAFE_FREE(pseed_chal);
-               SAFE_FREE(pclnt_chal);
-               SAFE_FREE(psrv_chal);
-               SAFE_FREE(psess_key);
-               SAFE_FREE(pmach_pw);
-               SAFE_FREE(value.dptr);
-               return False;
-       }
-
-       tdb_close(tdb_sc);
-
-       memcpy(pdc->seed_chal.data, pseed_chal, 8);
-       memcpy(pdc->clnt_chal.data, pclnt_chal, 8);
-       memcpy(pdc->srv_chal.data, psrv_chal, 8);
-       memcpy(pdc->sess_key, psess_key, 16);
-       memcpy(pdc->mach_pw, pmach_pw, 16);
-
-       /* We know these are true so didn't bother to store them. */
-       pdc->challenge_sent = True;
-       pdc->authenticated = True;
-
-       DEBUG(3,("secrets_restore_schannel_session_info: restored schannel info key %s\n",
-               keystr ));
-
-       SAFE_FREE(pseed_chal);
-       SAFE_FREE(pclnt_chal);
-       SAFE_FREE(psrv_chal);
-       SAFE_FREE(psess_key);
-       SAFE_FREE(pmach_pw);
-
-       TALLOC_FREE(keystr);
-       SAFE_FREE(value.dptr);
-
-       *ppdc = pdc;
-
-       return True;
-}
-
 bool secrets_store_generic(const char *owner, const char *key, const char *secret)
 {
        char *tdbkey = NULL;