Convert idmap_cache to gencache
[samba.git] / source3 / winbindd / idmap_cache.c
1 /*
2    Unix SMB/CIFS implementation.
3    ID Mapping Cache
4
5    Copyright (C) Volker Lendecke        2008
6    Copyright (C) Simo Sorce             2006
7    Copyright (C) Rafal Szczesniak       2002
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
21
22 #include "includes.h"
23 #include "winbindd.h"
24
25 static char *idmap_cache_sidkey(TALLOC_CTX *ctx, const DOM_SID *sid)
26 {
27         fstring sidstr;
28
29         return talloc_asprintf(ctx, "IDMAP/SID/%s",
30                                sid_to_fstring(sidstr, sid));
31 }
32
33 static char *idmap_cache_idkey(TALLOC_CTX *ctx, const struct unixid *xid)
34 {
35         return talloc_asprintf(ctx, "IDMAP/%s/%lu",
36                                (xid->type==ID_TYPE_UID)?"UID":"GID",
37                                (unsigned long)xid->id);
38 }
39
40 NTSTATUS idmap_cache_set(const struct id_map *id)
41 {
42         NTSTATUS ret;
43         time_t timeout = time(NULL) + lp_idmap_cache_time();
44         char *sidkey;
45         char *idkey;
46
47         /* Don't cache lookups in the S-1-22-{1,2} domain */
48
49         if (sid_check_is_in_unix_users(id->sid)
50             || sid_check_is_in_unix_groups(id->sid)) {
51                 return NT_STATUS_OK;
52         }
53
54         sidkey = idmap_cache_sidkey(talloc_tos(), id->sid);
55         if (sidkey == NULL) {
56                 return NT_STATUS_NO_MEMORY;
57         }
58
59         /* use sidkey as the local memory ctx */
60         idkey = idmap_cache_idkey(sidkey, &id->xid);
61         if (idkey == NULL) {
62                 ret = NT_STATUS_NO_MEMORY;
63                 goto done;
64         }
65
66         if (!gencache_set(idkey, sidkey, timeout)
67             || !gencache_set(sidkey, idkey, timeout)) {
68                 DEBUG(3, ("Failed to store cache entry!\n"));
69                 ret = NT_STATUS_ACCESS_DENIED;
70                 goto done;
71         }
72
73         ret = NT_STATUS_OK;
74
75 done:
76         TALLOC_FREE(sidkey);
77         return ret;
78 }
79
80 NTSTATUS idmap_cache_set_negative_sid(const struct id_map *id)
81 {
82         NTSTATUS ret = NT_STATUS_OK;
83         char *sidkey;
84
85         sidkey = idmap_cache_sidkey(talloc_tos(), id->sid);
86         if (sidkey == NULL) {
87                 return NT_STATUS_NO_MEMORY;
88         }
89
90         if (!gencache_set(sidkey, "IDMAP/NEGATIVE",
91                           time(NULL) + lp_idmap_negative_cache_time())) {
92                 DEBUG(3, ("Failed to store cache entry!\n"));
93                 ret = NT_STATUS_ACCESS_DENIED;
94                 goto done;
95         }
96
97 done:
98         TALLOC_FREE(sidkey);
99         return ret;
100 }
101
102 NTSTATUS idmap_cache_set_negative_id(const struct id_map *id)
103 {
104         NTSTATUS ret = NT_STATUS_OK;
105         char *idkey;
106
107         idkey = idmap_cache_idkey(talloc_tos(), &id->xid);
108         if (idkey == NULL) {
109                 return NT_STATUS_NO_MEMORY;
110         }
111
112         if (!gencache_set(idkey, "IDMAP/NEGATIVE",
113                           time(NULL) + lp_idmap_negative_cache_time())) {
114                 DEBUG(3, ("Failed to store cache entry!\n"));
115                 ret = NT_STATUS_ACCESS_DENIED;
116                 goto done;
117         }
118
119 done:
120         TALLOC_FREE(idkey);
121         return ret;
122 }
123
124 /*
125  * search the cache for the SID an return a mapping if found
126  */
127
128 bool idmap_cache_map_sid(const struct dom_sid *sid, struct unixid *xid,
129                          bool *mapped, bool *expired)
130 {
131         bool ret = false;
132         time_t timeout;
133         char *sidkey;
134         char *value;
135         char *rem;
136
137         sidkey = idmap_cache_sidkey(talloc_tos(), sid);
138         if (sidkey == NULL) {
139                 DEBUG(0, ("idmap_cache_sidkey failed\n"));
140                 return false;
141         }
142
143         if (!gencache_get(sidkey, &value, &timeout)) {
144                 TALLOC_FREE(sidkey);
145                 return false;
146         }
147
148         if (strcmp(value, "IDMAP/NEGATIVE") == 0) {
149                 *mapped = false;
150         }
151         else if (strncmp(value, "IDMAP/UID/", 10) == 0) {
152                 *mapped = true;
153                 xid->type = ID_TYPE_UID;
154                 xid->id = strtol(&value[10], &rem, 10);
155                 if (*rem != '\0') {
156                         goto fail;
157                 }
158         }
159         else if (strncmp(value, "IDMAP/GID/", 10) == 0) {
160                 *mapped = true;
161                 xid->type = ID_TYPE_GID;
162                 xid->id = strtol(&value[10], &rem, 10);
163                 if (*rem != '\0') {
164                         goto fail;
165                 }
166         }
167         else {
168                 goto fail;
169         }
170
171         *expired = (timeout <= time(NULL));
172
173         ret = true;
174
175  fail:
176         if (!ret) {
177                 DEBUG(1, ("Invalid entry %s in cache\n", value));
178         }
179         SAFE_FREE(value);
180         TALLOC_FREE(sidkey);
181         return ret;
182 }
183
184 /*
185  * search the cache for the ID an return a mapping if found
186  */
187
188 bool idmap_cache_map_id(const struct unixid *xid, struct dom_sid *psid,
189                         bool *mapped, bool *expired)
190 {
191         bool ret = false;
192         time_t timeout;
193         char *idkey;
194         char *value;
195
196         idkey = idmap_cache_idkey(talloc_tos(), xid);
197         if (idkey == NULL) {
198                 return false;
199         }
200
201         if (!gencache_get(idkey, &value, &timeout)) {
202                 TALLOC_FREE(idkey);
203                 return false;
204         }
205
206         if (strcmp(value, "IDMAP/NEGATIVE") == 0) {
207                 *mapped = false;
208         }
209         else if (strncmp(value, "IDMAP/SID/", 10) == 0) {
210                 *mapped = true;
211                 if (!string_to_sid(psid, value+10)) {
212                         goto fail;
213                 }
214         }
215         else {
216                 goto fail;
217         }
218
219         ret = true;
220
221  fail:
222         if (!ret) {
223                 DEBUG(1, ("Invalid entry %s in cache\n", value));
224         }
225         SAFE_FREE(value);
226         TALLOC_FREE(idkey);
227         return ret;
228 }
229