passdb: Do not routinely clear the global memory returned by get_global_sam_sid()
[bbaumbach/samba-autobuild/.git] / source3 / passdb / machine_account_secrets.c
index 8aaea10d8c25482afce87a77858d7529223d2eed..4e35a726382c16678ac76ceba416aeb12b6f9712 100644 (file)
 #include "dbwrap/dbwrap.h"
 #include "../librpc/ndr/libndr.h"
 #include "util_tdb.h"
+#include "libcli/security/security.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
 
-/* Urrrg. global.... */
-bool global_machine_password_needs_changing;
-
 /**
  * Form a key for fetching the domain sid
  *
@@ -78,37 +76,43 @@ bool secrets_mark_domain_protected(const char *domain)
 bool secrets_clear_domain_protection(const char *domain)
 {
        bool ret;
-
-       ret = secrets_delete(protect_ids_keystr(domain));
-       if (!ret) {
-               DEBUG(0, ("Failed to remove Domain IDs protection\n"));
+       void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
+       
+       if (protection) {
+               SAFE_FREE(protection);
+               ret = secrets_delete(protect_ids_keystr(domain));
+               if (!ret) {
+                       DEBUG(0, ("Failed to remove Domain IDs protection\n"));
+               }
+               return ret;
        }
-       return ret;
+       return true;
 }
 
 bool secrets_store_domain_sid(const char *domain, const struct dom_sid  *sid)
 {
-#if _SAMBA_BUILD_ == 4
        char *protect_ids;
-#endif
        bool ret;
 
-#if _SAMBA_BUILD_ == 4
        protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
        if (protect_ids) {
                if (strncmp(protect_ids, "TRUE", 4)) {
                        DEBUG(0, ("Refusing to store a Domain SID, "
                                  "it has been marked as protected!\n"));
+                       SAFE_FREE(protect_ids);
                        return false;
                }
        }
-#endif
+       SAFE_FREE(protect_ids);
 
        ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
 
-       /* Force a re-query, in case we modified our domain */
-       if (ret)
-               reset_global_sam_sid();
+       /* Force a re-query, in the case where we modified our domain */
+       if (ret) {
+               if (dom_sid_equal(get_global_sam_sid(), sid) == false) {
+                       reset_global_sam_sid();
+               }
+       }
        return ret;
 }
 
@@ -134,24 +138,24 @@ bool secrets_fetch_domain_sid(const char *domain, struct dom_sid  *sid)
 
 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
 {
-#if _SAMBA_BUILD_ == 4
        char *protect_ids;
-#endif
        fstring key;
 
-#if _SAMBA_BUILD_ == 4
        protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
        if (protect_ids) {
                if (strncmp(protect_ids, "TRUE", 4)) {
                        DEBUG(0, ("Refusing to store a Domain SID, "
                                  "it has been marked as protected!\n"));
+                       SAFE_FREE(protect_ids);
                        return false;
                }
        }
-#endif
+       SAFE_FREE(protect_ids);
 
        slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
-       strupper_m(key);
+       if (!strupper_m(key)) {
+               return false;
+       }
        return secrets_store(key, guid, sizeof(struct GUID));
 }
 
@@ -163,7 +167,9 @@ bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
        struct GUID new_guid;
 
        slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
-       strupper_m(key);
+       if (!strupper_m(key)) {
+               return false;
+       }
        dyn_guid = (struct GUID *)secrets_fetch(key, &size);
 
        if (!dyn_guid) {
@@ -301,7 +307,8 @@ void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
 enum netr_SchannelType get_default_sec_channel(void)
 {
        if (lp_server_role() == ROLE_DOMAIN_BDC ||
-           lp_server_role() == ROLE_DOMAIN_PDC) {
+           lp_server_role() == ROLE_DOMAIN_PDC ||
+           lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
                return SEC_CHAN_BDC;
        } else {
                return SEC_CHAN_WKSTA;
@@ -316,7 +323,7 @@ enum netr_SchannelType get_default_sec_channel(void)
 ************************************************************************/
 
 bool secrets_fetch_trust_account_password_legacy(const char *domain,
-                                                uint8 ret_pwd[16],
+                                                uint8_t ret_pwd[16],
                                                 time_t *pass_last_set_time,
                                                 enum netr_SchannelType *channel)
 {
@@ -344,14 +351,6 @@ bool secrets_fetch_trust_account_password_legacy(const char *domain,
                *channel = get_default_sec_channel();
        }
 
-       /* Test if machine password has expired and needs to be changed */
-       if (lp_machine_password_timeout()) {
-               if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
-                               (time_t)lp_machine_password_timeout())) {
-                       global_machine_password_needs_changing = True;
-               }
-       }
-
        SAFE_FREE(pass);
        return True;
 }
@@ -362,7 +361,7 @@ bool secrets_fetch_trust_account_password_legacy(const char *domain,
  the above secrets_lock_trust_account_password().
 ************************************************************************/
 
-bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
+bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
                                          time_t *pass_last_set_time,
                                          enum netr_SchannelType *channel)
 {
@@ -453,8 +452,8 @@ bool secrets_store_machine_password(const char *pass, const char *domain,
                                    enum netr_SchannelType sec_channel)
 {
        bool ret;
-       uint32 last_change_time;
-       uint32 sec_channel_type;
+       uint32_t last_change_time;
+       uint32_t sec_channel_type;
 
        if (!secrets_store_prev_machine_password(domain)) {
                return false;
@@ -473,6 +472,92 @@ bool secrets_store_machine_password(const char *pass, const char *domain,
        return ret;
 }
 
+/************************************************************************
+ Set the machine trust account password, the old pw and last change
+ time, domain SID and salting principals based on values passed in
+ (added to supprt the secrets_tdb_sync module on secrets.ldb)
+************************************************************************/
+
+bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
+                                  const char *realm,
+                                  const char *salting_principal, uint32_t supported_enc_types,
+                                  const struct dom_sid *domain_sid, uint32_t last_change_time,
+                                  bool delete_join)
+{
+       bool ret;
+       uint8_t last_change_time_store[4];
+       TALLOC_CTX *frame = talloc_stackframe();
+       void *value;
+
+       if (delete_join) {
+               secrets_delete_machine_password_ex(domain);
+               secrets_delete_domain_sid(domain);
+               TALLOC_FREE(frame);
+               return true;
+       }
+
+       ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
+       if (!ret) {
+               TALLOC_FREE(frame);
+               return ret;
+       }
+
+       if (oldpass) {
+               ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
+       } else {
+               value = secrets_fetch_prev_machine_password(domain);
+               if (value) {
+                       SAFE_FREE(value);
+                       ret = secrets_delete_prev_machine_password(domain);
+               }
+       }
+       if (!ret) {
+               TALLOC_FREE(frame);
+               return ret;
+       }
+
+       /* We delete this and instead have the read code fall back to
+        * a default based on server role, as our caller can't specify
+        * this with any more certainty */
+       value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL);
+       if (value) {
+               SAFE_FREE(value);
+               ret = secrets_delete(machine_sec_channel_type_keystr(domain));
+               if (!ret) {
+                       TALLOC_FREE(frame);
+                       return ret;
+               }
+       }
+
+       SIVAL(&last_change_time_store, 0, last_change_time);
+       ret = secrets_store(machine_last_change_time_keystr(domain),
+                           &last_change_time_store, sizeof(last_change_time));
+
+       if (!ret) {
+               TALLOC_FREE(frame);
+               return ret;
+       }
+
+       ret = secrets_store_domain_sid(domain, domain_sid);
+
+       if (!ret) {
+               TALLOC_FREE(frame);
+               return ret;
+       }
+
+       if (realm && salting_principal) {
+               char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
+               if (!key) {
+                       TALLOC_FREE(frame);
+                       return false;
+               }
+               ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
+       }
+
+       TALLOC_FREE(frame);
+       return ret;
+}
+
 
 /************************************************************************
  Routine to fetch the previous plaintext machine account password for a realm
@@ -498,7 +583,7 @@ char *secrets_fetch_machine_password(const char *domain,
 
        if (pass_last_set_time) {
                size_t size;
-               uint32 *last_set_time;
+               uint32_t *last_set_time;
                last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
                if (last_set_time) {
                        *pass_last_set_time = IVAL(last_set_time,0);
@@ -510,7 +595,7 @@ char *secrets_fetch_machine_password(const char *domain,
 
        if (channel) {
                size_t size;
-               uint32 *channel_type;
+               uint32_t *channel_type;
                channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
                if (channel_type) {
                        *channel = IVAL(channel_type,0);