~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source3/winbindd/winbindd_cache.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
*/
25
25
 
26
26
#include "includes.h"
 
27
#include "system/filesys.h"
27
28
#include "winbindd.h"
28
29
#include "tdb_validate.h"
29
30
#include "../libcli/auth/libcli_auth.h"
30
31
#include "../librpc/gen_ndr/ndr_wbint.h"
 
32
#include "ads.h"
 
33
#include "nss_info.h"
 
34
#include "../libcli/security/security.h"
 
35
#include "passdb/machine_sid.h"
 
36
#include "util_tdb.h"
31
37
 
32
38
#undef DBGC_CLASS
33
39
#define DBGC_CLASS DBGC_WINBIND
34
40
 
35
 
#define WINBINDD_CACHE_VERSION 1
 
41
#define WINBINDD_CACHE_VERSION 2
36
42
#define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION"
37
43
 
38
44
extern struct winbindd_methods reconnect_methods;
40
46
extern struct winbindd_methods ads_methods;
41
47
#endif
42
48
extern struct winbindd_methods builtin_passdb_methods;
 
49
extern struct winbindd_methods sam_passdb_methods;
43
50
 
44
51
/*
45
52
 * JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES.
92
99
struct cache_entry {
93
100
        NTSTATUS status;
94
101
        uint32 sequence_number;
 
102
        uint64_t timeout;
95
103
        uint8 *data;
96
104
        uint32 len, ofs;
97
105
};
102
110
 
103
111
static struct winbind_cache *wcache;
104
112
 
105
 
void winbindd_check_cache_size(time_t t)
106
 
{
107
 
        static time_t last_check_time;
108
 
        struct stat st;
109
 
 
110
 
        if (last_check_time == (time_t)0)
111
 
                last_check_time = t;
112
 
 
113
 
        if (t - last_check_time < 60 && t - last_check_time > 0)
114
 
                return;
115
 
 
116
 
        if (wcache == NULL || wcache->tdb == NULL) {
117
 
                DEBUG(0, ("Unable to check size of tdb cache - cache not open !\n"));
118
 
                return;
119
 
        }
120
 
 
121
 
        if (fstat(tdb_fd(wcache->tdb), &st) == -1) {
122
 
                DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) ));
123
 
                return;
124
 
        }
125
 
 
126
 
        if (st.st_size > WINBINDD_MAX_CACHE_SIZE) {
127
 
                DEBUG(10,("flushing cache due to size (%lu) > (%lu)\n",
128
 
                        (unsigned long)st.st_size,
129
 
                        (unsigned long)WINBINDD_MAX_CACHE_SIZE));
130
 
                wcache_flush_cache();
131
 
        }
132
 
}
133
 
 
134
113
/* get the winbind_cache structure */
135
114
static struct winbind_cache *get_cache(struct winbindd_domain *domain)
136
115
{
142
121
                domain->backend = &builtin_passdb_methods;
143
122
                domain->initialized = True;
144
123
        }
 
124
 
 
125
        if (strequal(domain->name, get_global_sam_name()) &&
 
126
            sid_check_is_domain(&domain->sid)) {
 
127
                domain->backend = &sam_passdb_methods;
 
128
                domain->initialized = True;
 
129
        }
 
130
 
145
131
        if ( !domain->initialized ) {
146
132
                init_dc_connection( domain );
147
133
        }
223
209
}
224
210
 
225
211
/*
 
212
  pull a uint64_t from a cache entry
 
213
*/
 
214
static uint64_t centry_uint64_t(struct cache_entry *centry)
 
215
{
 
216
        uint64_t ret;
 
217
 
 
218
        if (!centry_check_bytes(centry, 8)) {
 
219
                smb_panic_fn("centry_uint64_t");
 
220
        }
 
221
        ret = BVAL(centry->data, centry->ofs);
 
222
        centry->ofs += 8;
 
223
        return ret;
 
224
}
 
225
 
 
226
/*
226
227
  pull a uint32 from a cache entry 
227
228
*/
228
229
static uint32 centry_uint32(struct cache_entry *centry)
276
277
        }
277
278
        ret = IVAL(centry->data, centry->ofs);
278
279
        centry->ofs += 4;
279
 
        ret += (uint64_t)IVAL(centry->data, centry->ofs) << 32;
 
280
        ret += (uint64)IVAL(centry->data, centry->ofs) << 32;
280
281
        centry->ofs += 4;
281
282
        return ret;
282
283
}
614
615
        }
615
616
 
616
617
        /* if the server is down or the cache entry is not older than the
617
 
           current sequence number then it is OK */
618
 
        if (wcache_server_down(domain) || 
619
 
            centry->sequence_number == domain->sequence_number) {
 
618
           current sequence number or it did not timeout then it is OK */
 
619
        if (wcache_server_down(domain)
 
620
            || ((centry->sequence_number == domain->sequence_number)
 
621
                && (centry->timeout > time(NULL)))) {
620
622
                DEBUG(10,("centry_expired: Key %s for domain %s is good.\n",
621
623
                        keystr, domain->name ));
622
624
                return false;
647
649
        centry->len = data.dsize;
648
650
        centry->ofs = 0;
649
651
 
650
 
        if (centry->len < 8) {
 
652
        if (centry->len < 16) {
651
653
                /* huh? corrupt cache? */
652
 
                DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s (len < 8) ?\n", kstr));
 
654
                DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s "
 
655
                          "(len < 16)?\n", kstr));
653
656
                centry_free(centry);
654
657
                return NULL;
655
658
        }
656
659
 
657
660
        centry->status = centry_ntstatus(centry);
658
661
        centry->sequence_number = centry_uint32(centry);
 
662
        centry->timeout = centry_uint64_t(centry);
659
663
 
660
664
        return centry;
661
665
}
662
666
 
 
667
static bool is_my_own_sam_domain(struct winbindd_domain *domain)
 
668
{
 
669
        if (strequal(domain->name, get_global_sam_name()) &&
 
670
            sid_check_is_domain(&domain->sid)) {
 
671
                return true;
 
672
        }
 
673
 
 
674
        return false;
 
675
}
 
676
 
 
677
static bool is_builtin_domain(struct winbindd_domain *domain)
 
678
{
 
679
        if (strequal(domain->name, "BUILTIN") &&
 
680
            sid_check_is_builtin(&domain->sid)) {
 
681
                return true;
 
682
        }
 
683
 
 
684
        return false;
 
685
}
 
686
 
663
687
/*
664
688
  fetch an entry from the cache, with a varargs key. auto-fetch the sequence
665
689
  number and return status
675
699
        char *kstr;
676
700
        struct cache_entry *centry;
677
701
 
678
 
        if (!winbindd_use_cache()) {
 
702
        if (!winbindd_use_cache() ||
 
703
            is_my_own_sam_domain(domain) ||
 
704
            is_builtin_domain(domain)) {
679
705
                return NULL;
680
706
        }
681
707
 
742
768
}
743
769
 
744
770
/*
 
771
  push a uint64_t into a centry
 
772
*/
 
773
static void centry_put_uint64_t(struct cache_entry *centry, uint64_t v)
 
774
{
 
775
        centry_expand(centry, 8);
 
776
        SBVAL(centry->data, centry->ofs, v);
 
777
        centry->ofs += 8;
 
778
}
 
779
 
 
780
/*
745
781
  push a uint32 into a centry 
746
782
*/
747
783
static void centry_put_uint32(struct cache_entry *centry, uint32 v)
807
843
        centry->ofs += 16;
808
844
}
809
845
 
810
 
static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid) 
 
846
static void centry_put_sid(struct cache_entry *centry, const struct dom_sid *sid)
811
847
{
812
848
        fstring sid_string;
813
849
        centry_put_string(centry, sid_to_fstring(sid_string, sid));
862
898
        centry->data = SMB_XMALLOC_ARRAY(uint8, centry->len);
863
899
        centry->ofs = 0;
864
900
        centry->sequence_number = domain->sequence_number;
 
901
        centry->timeout = lp_winbind_cache_time() + time(NULL);
865
902
        centry_put_ntstatus(centry, status);
866
903
        centry_put_uint32(centry, centry->sequence_number);
 
904
        centry_put_uint64_t(centry, centry->timeout);
867
905
        return centry;
868
906
}
869
907
 
895
933
 
896
934
static void wcache_save_name_to_sid(struct winbindd_domain *domain, 
897
935
                                    NTSTATUS status, const char *domain_name,
898
 
                                    const char *name, const DOM_SID *sid, 
 
936
                                    const char *name, const struct dom_sid *sid,
899
937
                                    enum lsa_SidType type)
900
938
{
901
939
        struct cache_entry *centry;
915
953
}
916
954
 
917
955
static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, 
918
 
                                    const DOM_SID *sid, const char *domain_name, const char *name, enum lsa_SidType type)
 
956
                                    const struct dom_sid *sid, const char *domain_name, const char *name, enum lsa_SidType type)
919
957
{
920
958
        struct cache_entry *centry;
921
959
        fstring sid_string;
1212
1250
        return status;
1213
1251
}
1214
1252
 
1215
 
NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid)
 
1253
NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const struct dom_sid *sid)
1216
1254
{
1217
1255
        struct winbind_cache *cache = get_cache(domain);
1218
1256
        TDB_DATA data;
1247
1285
 
1248
1286
NTSTATUS wcache_get_creds(struct winbindd_domain *domain, 
1249
1287
                          TALLOC_CTX *mem_ctx, 
1250
 
                          const DOM_SID *sid,
 
1288
                          const struct dom_sid *sid,
1251
1289
                          const uint8 **cached_nt_pass,
1252
1290
                          const uint8 **cached_salt)
1253
1291
{
1327
1365
/* Store creds for a SID - only writes out new salted ones. */
1328
1366
 
1329
1367
NTSTATUS wcache_save_creds(struct winbindd_domain *domain, 
1330
 
                           TALLOC_CTX *mem_ctx, 
1331
 
                           const DOM_SID *sid, 
 
1368
                           const struct dom_sid *sid,
1332
1369
                           const uint8 nt_pass[NT_HASH_LEN])
1333
1370
{
1334
1371
        struct cache_entry *centry;
1525
1562
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
1526
1563
                                TALLOC_CTX *mem_ctx,
1527
1564
                                uint32 *num_entries, 
1528
 
                                struct acct_info **info)
 
1565
                                struct wb_acct_info **info)
1529
1566
{
1530
1567
        struct winbind_cache *cache = get_cache(domain);
1531
1568
        struct cache_entry *centry = NULL;
1547
1584
        if (*num_entries == 0)
1548
1585
                goto do_cached;
1549
1586
 
1550
 
        (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
 
1587
        (*info) = TALLOC_ARRAY(mem_ctx, struct wb_acct_info, *num_entries);
1551
1588
        if (! (*info)) {
1552
1589
                smb_panic_fn("enum_dom_groups out of memory");
1553
1590
        }
1620
1657
static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
1621
1658
                                TALLOC_CTX *mem_ctx,
1622
1659
                                uint32 *num_entries, 
1623
 
                                struct acct_info **info)
 
1660
                                struct wb_acct_info **info)
1624
1661
{
1625
1662
        struct winbind_cache *cache = get_cache(domain);
1626
1663
        struct cache_entry *centry = NULL;
1642
1679
        if (*num_entries == 0)
1643
1680
                goto do_cached;
1644
1681
 
1645
 
        (*info) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_entries);
 
1682
        (*info) = TALLOC_ARRAY(mem_ctx, struct wb_acct_info, *num_entries);
1646
1683
        if (! (*info)) {
1647
1684
                smb_panic_fn("enum_dom_groups out of memory");
1648
1685
        }
1766
1803
                            const char *domain_name,
1767
1804
                            const char *name,
1768
1805
                            uint32_t flags,
1769
 
                            DOM_SID *sid,
 
1806
                            struct dom_sid *sid,
1770
1807
                            enum lsa_SidType *type)
1771
1808
{
1772
1809
        NTSTATUS status;
1875
1912
   given */
1876
1913
static NTSTATUS sid_to_name(struct winbindd_domain *domain,
1877
1914
                            TALLOC_CTX *mem_ctx,
1878
 
                            const DOM_SID *sid,
 
1915
                            const struct dom_sid *sid,
1879
1916
                            char **domain_name,
1880
1917
                            char **name,
1881
1918
                            enum lsa_SidType *type)
1938
1975
 
1939
1976
static NTSTATUS rids_to_names(struct winbindd_domain *domain,
1940
1977
                              TALLOC_CTX *mem_ctx,
1941
 
                              const DOM_SID *domain_sid,
 
1978
                              const struct dom_sid *domain_sid,
1942
1979
                              uint32 *rids,
1943
1980
                              size_t num_rids,
1944
1981
                              char **domain_name,
1976
2013
        have_mapped = have_unmapped = false;
1977
2014
 
1978
2015
        for (i=0; i<num_rids; i++) {
1979
 
                DOM_SID sid;
 
2016
                struct dom_sid sid;
1980
2017
                struct cache_entry *centry;
1981
2018
                fstring tmp;
1982
2019
 
2008
2045
 
2009
2046
                        (*names)[i] = centry_string(centry, *names);
2010
2047
 
2011
 
                } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) {
 
2048
                } else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)
 
2049
                           || NT_STATUS_EQUAL(centry->status, STATUS_SOME_UNMAPPED)) {
2012
2050
                        have_unmapped = true;
2013
2051
 
2014
2052
                } else {
2049
2087
                        have_mapped = have_unmapped = false;
2050
2088
 
2051
2089
                        for (i=0; i<num_rids; i++) {
2052
 
                                DOM_SID sid;
 
2090
                                struct dom_sid sid;
2053
2091
                                struct cache_entry *centry;
2054
2092
                                fstring tmp;
2055
2093
 
2109
2147
        */
2110
2148
        if (NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED)) {
2111
2149
                for (i = 0; i < num_rids; i++) {
2112
 
                        DOM_SID sid;
 
2150
                        struct dom_sid sid;
2113
2151
                        const char *name = "";
2114
2152
                        const enum lsa_SidType type = SID_NAME_UNKNOWN;
2115
2153
                        NTSTATUS status = NT_STATUS_NONE_MAPPED;
2136
2174
        refresh_sequence_number(domain, false);
2137
2175
 
2138
2176
        for (i=0; i<num_rids; i++) {
2139
 
                DOM_SID sid;
 
2177
                struct dom_sid sid;
2140
2178
                NTSTATUS status;
2141
2179
 
2142
2180
                if (!sid_compose(&sid, domain_sid, rids[i])) {
2222
2260
/* Lookup user information from a rid */
2223
2261
static NTSTATUS query_user(struct winbindd_domain *domain,
2224
2262
                           TALLOC_CTX *mem_ctx,
2225
 
                           const DOM_SID *user_sid,
 
2263
                           const struct dom_sid *user_sid,
2226
2264
                           struct wbint_userinfo *info)
2227
2265
{
2228
2266
        NTSTATUS status;
2331
2369
/* Lookup groups a user is a member of. */
2332
2370
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
2333
2371
                                  TALLOC_CTX *mem_ctx,
2334
 
                                  const DOM_SID *user_sid,
2335
 
                                  uint32 *num_groups, DOM_SID **user_gids)
 
2372
                                  const struct dom_sid *user_sid,
 
2373
                                  uint32 *num_groups, struct dom_sid **user_gids)
2336
2374
{
2337
2375
        struct cache_entry *centry = NULL;
2338
2376
        NTSTATUS status;
2482
2520
 
2483
2521
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
2484
2522
                                   TALLOC_CTX *mem_ctx,
2485
 
                                   uint32 num_sids, const DOM_SID *sids,
 
2523
                                   uint32 num_sids, const struct dom_sid *sids,
2486
2524
                                   uint32 *num_aliases, uint32 **alias_rids)
2487
2525
{
2488
2526
        struct cache_entry *centry = NULL;
2586
2624
                return NT_STATUS_OK;
2587
2625
        }
2588
2626
 
2589
 
        *sid_mem = talloc_array(mem_ctx, DOM_SID, *num_names);
 
2627
        *sid_mem = talloc_array(mem_ctx, struct dom_sid, *num_names);
2590
2628
        *names = talloc_array(mem_ctx, char *, *num_names);
2591
2629
        *name_types = talloc_array(mem_ctx, uint32, *num_names);
2592
2630
 
2615
2653
 
2616
2654
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
2617
2655
                                TALLOC_CTX *mem_ctx,
2618
 
                                const DOM_SID *group_sid,
 
2656
                                const struct dom_sid *group_sid,
2619
2657
                                enum lsa_SidType type,
2620
2658
                                uint32 *num_names,
2621
 
                                DOM_SID **sid_mem, char ***names,
 
2659
                                struct dom_sid **sid_mem, char ***names,
2622
2660
                                uint32 **name_types)
2623
2661
{
2624
2662
        struct cache_entry *centry = NULL;
2965
3003
/* Invalidate the getpwnam and getgroups entries for a winbindd domain */
2966
3004
 
2967
3005
void wcache_invalidate_samlogon(struct winbindd_domain *domain, 
2968
 
                                struct netr_SamInfo3 *info3)
 
3006
                                const struct dom_sid *sid)
2969
3007
{
2970
 
        DOM_SID sid;
2971
3008
        fstring key_str, sid_string;
2972
3009
        struct winbind_cache *cache;
2973
3010
 
2987
3024
                return;
2988
3025
        }
2989
3026
 
2990
 
        sid_copy(&sid, info3->base.domain_sid);
2991
 
        sid_append_rid(&sid, info3->base.rid);
2992
 
 
2993
3027
        /* Clear U/SID cache entry */
2994
 
        fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, &sid));
 
3028
        fstr_sprintf(key_str, "U/%s", sid_to_fstring(sid_string, sid));
2995
3029
        DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
2996
3030
        tdb_delete(cache->tdb, string_tdb_data(key_str));
2997
3031
 
2998
3032
        /* Clear UG/SID cache entry */
2999
 
        fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, &sid));
 
3033
        fstr_sprintf(key_str, "UG/%s", sid_to_fstring(sid_string, sid));
3000
3034
        DEBUG(10, ("wcache_invalidate_samlogon: clearing %s\n", key_str));
3001
3035
        tdb_delete(cache->tdb, string_tdb_data(key_str));
3002
3036
 
3003
3037
        /* Samba/winbindd never needs this. */
3004
 
        netsamlogon_clear_cached_user(info3);
 
3038
        netsamlogon_clear_cached_user(sid);
3005
3039
}
3006
3040
 
3007
3041
bool wcache_invalidate_cache(void)
3024
3058
        return true;
3025
3059
}
3026
3060
 
 
3061
bool wcache_invalidate_cache_noinit(void)
 
3062
{
 
3063
        struct winbindd_domain *domain;
 
3064
 
 
3065
        for (domain = domain_list(); domain; domain = domain->next) {
 
3066
                struct winbind_cache *cache;
 
3067
 
 
3068
                /* Skip uninitialized domains. */
 
3069
                if (!domain->initialized && !domain->internal) {
 
3070
                        continue;
 
3071
                }
 
3072
 
 
3073
                cache = get_cache(domain);
 
3074
 
 
3075
                DEBUG(10, ("wcache_invalidate_cache: invalidating cache "
 
3076
                           "entries for %s\n", domain->name));
 
3077
                if (cache) {
 
3078
                        if (cache->tdb) {
 
3079
                                tdb_traverse(cache->tdb, traverse_fn, NULL);
 
3080
                                /*
 
3081
                                 * Flushing cache has nothing to with domains.
 
3082
                                 * return here if we successfully flushed once.
 
3083
                                 * To avoid unnecessary traversing the cache.
 
3084
                                 */
 
3085
                                return true;
 
3086
                        } else {
 
3087
                                return false;
 
3088
                        }
 
3089
                }
 
3090
        }
 
3091
        return true;
 
3092
}
 
3093
 
3027
3094
bool init_wcache(void)
3028
3095
{
3029
3096
        if (wcache == NULL) {
3037
3104
        /* when working offline we must not clear the cache on restart */
3038
3105
        wcache->tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
3039
3106
                                WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, 
3040
 
                                lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), 
 
3107
                                TDB_INCOMPATIBLE_HASH |
 
3108
                                        (lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST)),
3041
3109
                                O_RDWR|O_CREAT, 0600);
3042
3110
 
3043
3111
        if (wcache->tdb == NULL) {
3114
3182
        }
3115
3183
}
3116
3184
 
3117
 
bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
 
3185
bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
3118
3186
                       char **domain_name, char **name,
3119
3187
                       enum lsa_SidType *type)
3120
3188
{
3130
3198
        return NT_STATUS_IS_OK(status);
3131
3199
}
3132
3200
 
3133
 
bool lookup_cached_name(TALLOC_CTX *mem_ctx,
3134
 
                        const char *domain_name,
 
3201
bool lookup_cached_name(const char *domain_name,
3135
3202
                        const char *name,
3136
 
                        DOM_SID *sid,
 
3203
                        struct dom_sid *sid,
3137
3204
                        enum lsa_SidType *type)
3138
3205
{
3139
3206
        struct winbindd_domain *domain;
3158
3225
 
3159
3226
void cache_name2sid(struct winbindd_domain *domain, 
3160
3227
                    const char *domain_name, const char *name,
3161
 
                    enum lsa_SidType type, const DOM_SID *sid)
 
3228
                    enum lsa_SidType type, const struct dom_sid *sid)
3162
3229
{
3163
3230
        refresh_sequence_number(domain, false);
3164
3231
        wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name,
3210
3277
        /* when working offline we must not clear the cache on restart */
3211
3278
        wcache->tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
3212
3279
                                WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, 
3213
 
                                lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), 
 
3280
                                TDB_INCOMPATIBLE_HASH |
 
3281
                                (lp_winbind_offline_logon() ? TDB_DEFAULT : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST)),
3214
3282
                                O_RDWR|O_CREAT, 0600);
3215
3283
 
3216
3284
        if (!wcache->tdb) {
3283
3351
        return 0;
3284
3352
}
3285
3353
 
3286
 
NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid) 
 
3354
NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const struct dom_sid *sid)
3287
3355
{
3288
3356
        struct winbind_cache *cache = get_cache(domain);
3289
3357
        NTSTATUS status;
3448
3516
        centry->len = data.dsize;
3449
3517
        centry->ofs = 0;
3450
3518
 
3451
 
        if (centry->len < 8) {
 
3519
        if (centry->len < 16) {
3452
3520
                /* huh? corrupt cache? */
3453
 
                DEBUG(0,("create_centry_validate: Corrupt cache for key %s (len < 8) ?\n", kstr));
 
3521
                DEBUG(0,("create_centry_validate: Corrupt cache for key %s "
 
3522
                         "(len < 16) ?\n", kstr));
3454
3523
                centry_free(centry);
3455
3524
                state->bad_entry = true;
3456
3525
                state->success = false;
3459
3528
 
3460
3529
        centry->status = NT_STATUS(centry_uint32(centry));
3461
3530
        centry->sequence_number = centry_uint32(centry);
 
3531
        centry->timeout = centry_uint64_t(centry);
3462
3532
        return centry;
3463
3533
}
3464
3534
 
3484
3554
 
3485
3555
        (void)centry_uint32(centry);
3486
3556
        if (NT_STATUS_IS_OK(centry->status)) {
3487
 
                DOM_SID sid;
 
3557
                struct dom_sid sid;
3488
3558
                (void)centry_sid(centry, &sid);
3489
3559
        }
3490
3560
 
3524
3594
                      struct tdb_validation_status *state)
3525
3595
{
3526
3596
        struct cache_entry *centry = create_centry_validate(keystr, dbuf, state);
3527
 
        DOM_SID sid;
 
3597
        struct dom_sid sid;
3528
3598
 
3529
3599
        if (!centry) {
3530
3600
                return 1;
3632
3702
        num_entries = (int32)centry_uint32(centry);
3633
3703
 
3634
3704
        for (i=0; i< num_entries; i++) {
3635
 
                DOM_SID sid;
 
3705
                struct dom_sid sid;
3636
3706
                (void)centry_string(centry, mem_ctx);
3637
3707
                (void)centry_string(centry, mem_ctx);
3638
3708
                (void)centry_string(centry, mem_ctx);
3690
3760
        num_groups = centry_uint32(centry);
3691
3761
 
3692
3762
        for (i=0; i< num_groups; i++) {
3693
 
                DOM_SID sid;
 
3763
                struct dom_sid sid;
3694
3764
                centry_sid(centry, &sid);
3695
3765
        }
3696
3766
 
3741
3811
        num_names = centry_uint32(centry);
3742
3812
 
3743
3813
        for (i=0; i< num_names; i++) {
3744
 
                DOM_SID sid;
 
3814
                struct dom_sid sid;
3745
3815
                centry_sid(centry, &sid);
3746
3816
                (void)centry_string(centry, mem_ctx);
3747
3817
                (void)centry_uint32(centry);
4028
4098
 
4029
4099
        tdb = tdb_open_log(tdb_path, 
4030
4100
                           WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
 
4101
                           TDB_INCOMPATIBLE_HASH |
4031
4102
                           ( lp_winbind_offline_logon() 
4032
4103
                             ? TDB_DEFAULT 
4033
4104
                             : TDB_DEFAULT | TDB_CLEAR_IF_FIRST ),
4472
4543
        return d;       
4473
4544
}
4474
4545
 
 
4546
/*********************************************************************
 
4547
 ********************************************************************/
 
4548
 
 
4549
struct winbindd_tdc_domain*
 
4550
        wcache_tdc_fetch_domainbysid(TALLOC_CTX *ctx,
 
4551
                                     const struct dom_sid *sid)
 
4552
{
 
4553
        struct winbindd_tdc_domain *dom_list = NULL;
 
4554
        size_t num_domains = 0;
 
4555
        int i;
 
4556
        struct winbindd_tdc_domain *d = NULL;
 
4557
 
 
4558
        DEBUG(10,("wcache_tdc_fetch_domainbysid: Searching for domain %s\n",
 
4559
                  sid_string_dbg(sid)));
 
4560
 
 
4561
        if (!init_wcache()) {
 
4562
                return false;
 
4563
        }
 
4564
 
 
4565
        /* fetch the list */
 
4566
 
 
4567
        wcache_tdc_fetch_list(&dom_list, &num_domains);
 
4568
 
 
4569
        for (i = 0; i<num_domains; i++) {
 
4570
                if (sid_equal(sid, &(dom_list[i].sid))) {
 
4571
                        DEBUG(10, ("wcache_tdc_fetch_domainbysid: "
 
4572
                                   "Found domain %s for SID %s\n",
 
4573
                                   dom_list[i].domain_name,
 
4574
                                   sid_string_dbg(sid)));
 
4575
 
 
4576
                        d = TALLOC_P(ctx, struct winbindd_tdc_domain);
 
4577
                        if (!d)
 
4578
                                break;
 
4579
 
 
4580
                        d->domain_name = talloc_strdup(d,
 
4581
                                                       dom_list[i].domain_name);
 
4582
 
 
4583
                        d->dns_name = talloc_strdup(d, dom_list[i].dns_name);
 
4584
                        sid_copy(&d->sid, &dom_list[i].sid);
 
4585
                        d->trust_flags = dom_list[i].trust_flags;
 
4586
                        d->trust_type = dom_list[i].trust_type;
 
4587
                        d->trust_attribs = dom_list[i].trust_attribs;
 
4588
 
 
4589
                        break;
 
4590
                }
 
4591
        }
 
4592
 
 
4593
        TALLOC_FREE(dom_list);
 
4594
 
 
4595
        return d;
 
4596
}
 
4597
 
4475
4598
 
4476
4599
/*********************************************************************
4477
4600
 ********************************************************************/
4492
4615
 
4493
4616
static void wcache_save_user_pwinfo(struct winbindd_domain *domain, 
4494
4617
                                    NTSTATUS status,
4495
 
                                    const DOM_SID *user_sid,
 
4618
                                    const struct dom_sid *user_sid,
4496
4619
                                    const char *homedir,
4497
4620
                                    const char *shell,
4498
4621
                                    const char *gecos,
4516
4639
        centry_free(centry);
4517
4640
}
4518
4641
 
 
4642
#ifdef HAVE_ADS
 
4643
 
4519
4644
NTSTATUS nss_get_info_cached( struct winbindd_domain *domain, 
4520
 
                              const DOM_SID *user_sid,
 
4645
                              const struct dom_sid *user_sid,
4521
4646
                              TALLOC_CTX *ctx,
4522
 
                              ADS_STRUCT *ads, LDAPMessage *msg,
4523
4647
                              const char **homedir, const char **shell,
4524
4648
                              const char **gecos, gid_t *p_gid)
4525
4649
{
4551
4675
 
4552
4676
do_query:
4553
4677
 
4554
 
        nt_status = nss_get_info( domain->name, user_sid, ctx, ads, msg, 
 
4678
        nt_status = nss_get_info( domain->name, user_sid, ctx,
4555
4679
                                  homedir, shell, gecos, p_gid );
4556
4680
 
4557
4681
        DEBUG(10, ("nss_get_info returned %s\n", nt_errstr(nt_status)));
4575
4699
        return nt_status;       
4576
4700
}
4577
4701
 
 
4702
#endif
4578
4703
 
4579
4704
/* the cache backend methods are exposed via this structure */
4580
4705
struct winbindd_methods cache_methods = {
4640
4765
        TDB_DATA key, data;
4641
4766
        bool ret = false;
4642
4767
 
4643
 
        if (!wcache_opnum_cacheable(opnum)) {
 
4768
        if (!wcache_opnum_cacheable(opnum) ||
 
4769
            is_my_own_sam_domain(domain) ||
 
4770
            is_builtin_domain(domain)) {
4644
4771
                return false;
4645
4772
        }
4646
4773
 
4657
4784
        if (data.dptr == NULL) {
4658
4785
                return false;
4659
4786
        }
4660
 
        if (data.dsize < 4) {
 
4787
        if (data.dsize < 12) {
4661
4788
                goto fail;
4662
4789
        }
4663
4790
 
4664
4791
        if (!is_domain_offline(domain)) {
4665
4792
                uint32_t entry_seqnum, dom_seqnum, last_check;
 
4793
                uint64_t entry_timeout;
4666
4794
 
4667
4795
                if (!wcache_fetch_seqnum(domain->name, &dom_seqnum,
4668
4796
                                         &last_check)) {
4674
4802
                                   (int)entry_seqnum));
4675
4803
                        goto fail;
4676
4804
                }
 
4805
                entry_timeout = BVAL(data.dptr, 4);
 
4806
                if (time(NULL) > entry_timeout) {
 
4807
                        DEBUG(10, ("Entry has timed out\n"));
 
4808
                        goto fail;
 
4809
                }
4677
4810
        }
4678
4811
 
4679
 
        resp->data = (uint8_t *)talloc_memdup(mem_ctx, data.dptr + 4,
4680
 
                                              data.dsize - 4);
 
4812
        resp->data = (uint8_t *)talloc_memdup(mem_ctx, data.dptr + 12,
 
4813
                                              data.dsize - 12);
4681
4814
        if (resp->data == NULL) {
4682
4815
                DEBUG(10, ("talloc failed\n"));
4683
4816
                goto fail;
4684
4817
        }
4685
 
        resp->length = data.dsize - 4;
 
4818
        resp->length = data.dsize - 12;
4686
4819
 
4687
4820
        ret = true;
4688
4821
fail:
4695
4828
{
4696
4829
        TDB_DATA key, data;
4697
4830
        uint32_t dom_seqnum, last_check;
 
4831
        uint64_t timeout;
4698
4832
 
4699
 
        if (!wcache_opnum_cacheable(opnum)) {
 
4833
        if (!wcache_opnum_cacheable(opnum) ||
 
4834
            is_my_own_sam_domain(domain) ||
 
4835
            is_builtin_domain(domain)) {
4700
4836
                return;
4701
4837
        }
4702
4838
 
4714
4850
                return;
4715
4851
        }
4716
4852
 
4717
 
        data.dsize = resp->length + 4;
 
4853
        timeout = time(NULL) + lp_winbind_cache_time();
 
4854
 
 
4855
        data.dsize = resp->length + 12;
4718
4856
        data.dptr = talloc_array(key.dptr, uint8_t, data.dsize);
4719
4857
        if (data.dptr == NULL) {
4720
4858
                goto done;
4721
4859
        }
4722
4860
 
4723
4861
        SIVAL(data.dptr, 0, dom_seqnum);
4724
 
        memcpy(data.dptr+4, resp->data, resp->length);
 
4862
        SBVAL(data.dptr, 4, timeout);
 
4863
        memcpy(data.dptr + 12, resp->data, resp->length);
4725
4864
 
4726
4865
        tdb_store(wcache->tdb, key, data, 0);
4727
4866