s3-talloc Change TALLOC_ZERO_P() to talloc_zero()
[nivanova/samba-autobuild/.git] / source3 / libsmb / samlogon_cache.c
index e2a4b3898f774649b45df7df60a00f220bbd8e3d..67c0e08114a2f19a485fdd1553f6d0df2f1ff94c 100644 (file)
@@ -5,6 +5,7 @@
    Copyright (C) Andrew Bartlett                2002.
    Copyright (C) Gerald Carter                 2003.
    Copyright (C) Tim Potter                    2003.
+   Copyright (C) Guenther Deschner             2008.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 */
 
 #include "includes.h"
+#include "system/filesys.h"
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+#include "../libcli/security/security.h"
+#include "util_tdb.h"
 
 #define NETSAMLOGON_TDB        "netsamlogon_cache.tdb"
 
@@ -32,12 +37,43 @@ static TDB_CONTEXT *netsamlogon_tdb = NULL;
 
 bool netsamlogon_cache_init(void)
 {
-       if (!netsamlogon_tdb) {
-               netsamlogon_tdb = tdb_open_log(lock_path(NETSAMLOGON_TDB), 0,
-                                              TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
+       bool first_try = true;
+       const char *path = NULL;
+       int ret;
+       struct tdb_context *tdb;
+
+       if (netsamlogon_tdb) {
+               return true;
+       }
+
+       path = cache_path(NETSAMLOGON_TDB);
+again:
+       tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
+                          O_RDWR | O_CREAT, 0600);
+       if (tdb == NULL) {
+               DEBUG(0,("tdb_open_log('%s') - failed\n", path));
+               goto clear;
+       }
+
+       ret = tdb_check(tdb, NULL, NULL);
+       if (ret != 0) {
+               tdb_close(tdb);
+               DEBUG(0,("tdb_check('%s') - failed\n", path));
+               goto clear;
        }
 
-       return (netsamlogon_tdb != NULL);
+       netsamlogon_tdb = tdb;
+       return true;
+
+clear:
+       if (!first_try) {
+               return false;
+       }
+       first_try = false;
+
+       DEBUG(0,("retry after truncate for '%s'\n", path));
+       truncate(path, 0);
+       goto again;
 }
 
 
@@ -58,48 +94,23 @@ bool netsamlogon_cache_shutdown(void)
  Clear cache getpwnam and getgroups entries from the winbindd cache
 ***********************************************************************/
 
-void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, struct netr_SamInfo3 *info3)
+void netsamlogon_clear_cached_user(const struct dom_sid *user_sid)
 {
-       bool got_tdb = false;
-       DOM_SID sid;
-       fstring key_str, sid_string;
-
-       /* We may need to call this function from smbd which will not have
-          winbindd_cache.tdb open.  Open the tdb if a NULL is passed. */
-
-       if (!tdb) {
-               tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
-                                  WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
-                                  TDB_DEFAULT, O_RDWR, 0600);
-               if (!tdb) {
-                       DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n"));
-                       return;
-               }
-               got_tdb = true;
-       }
+       fstring keystr;
 
-       sid_copy(&sid, info3->base.domain_sid);
-       sid_append_rid(&sid, info3->base.rid);
-
-       /* Clear U/SID cache entry */
-
-       fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid));
-
-       DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str));
-
-       tdb_delete(tdb, string_tdb_data(key_str));
-
-       /* Clear UG/SID cache entry */
-
-       fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, &sid));
+       if (!netsamlogon_cache_init()) {
+               DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
+                       "%s for write!\n",
+                       NETSAMLOGON_TDB));
+               return;
+       }
 
-       DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key_str));
+       /* Prepare key as DOMAIN-SID/USER-RID string */
+       sid_to_fstring(keystr, user_sid);
 
-       tdb_delete(tdb, string_tdb_data(key_str));
+       DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
 
-       if (got_tdb) {
-               tdb_close(tdb);
-       }
+       tdb_delete_bystring(netsamlogon_tdb, keystr);
 }
 
 /***********************************************************************
@@ -110,9 +121,9 @@ void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, struct netr_SamInfo3 *info3
 bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
 {
        TDB_DATA data;
-       fstring keystr, tmp;
+       fstring keystr;
        bool result = false;
-       DOM_SID user_sid;
+       struct dom_sid  user_sid;
        time_t t = time(NULL);
        TALLOC_CTX *mem_ctx;
        DATA_BLOB blob;
@@ -129,17 +140,16 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
                return false;
        }
 
-       sid_copy(&user_sid, info3->base.domain_sid);
-       sid_append_rid(&user_sid, info3->base.rid);
+       sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid);
 
        /* Prepare key as DOMAIN-SID/USER-RID string */
-       slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
+       sid_to_fstring(keystr, &user_sid);
 
        DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
 
        /* Prepare data */
 
-       if (!(mem_ctx = TALLOC_P( NULL, int))) {
+       if (!(mem_ctx = talloc( NULL, int))) {
                DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
                return false;
        }
@@ -148,7 +158,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
        /* so we fill it in since winbindd_getpwnam() makes use of it */
 
        if (!info3->base.account_name.string) {
-               info3->base.account_name.string = talloc_strdup(mem_ctx, username);
+               info3->base.account_name.string = talloc_strdup(info3, username);
        }
 
        r.timestamp = t;
@@ -183,7 +193,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
  free the user_info struct (malloc()'d memory)
 ***********************************************************************/
 
-struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
+struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid)
 {
        struct netr_SamInfo3 *info3 = NULL;
        TDB_DATA data;
@@ -207,13 +217,12 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *
                return NULL;
        }
 
-       info3 = TALLOC_ZERO_P(mem_ctx, struct netr_SamInfo3);
+       info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
        if (!info3) {
                goto done;
        }
 
-       blob.data = (uint8 *)data.dptr;
-       blob.length = data.dsize;
+       blob = data_blob_const(data.dptr, data.dsize);
 
        ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
                                      (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
@@ -225,10 +234,12 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
                tdb_delete(netsamlogon_tdb, data);
+               TALLOC_FREE(info3);
                goto done;
        }
 
-       info3 = talloc_memdup(mem_ctx, &r.info3, sizeof(r.info3));
+       info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
+                                                     sizeof(r.info3));
 
  done:
        SAFE_FREE(data.dptr);
@@ -255,7 +266,7 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *
 #endif
 }
 
-bool netsamlogon_cache_have(const DOM_SID *user_sid)
+bool netsamlogon_cache_have(const struct dom_sid *user_sid)
 {
        TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
        struct netr_SamInfo3 *info3 = NULL;