Merge branch 'master' of ssh://git.samba.org/data/git/samba
[samba.git] / source3 / lib / idmap_cache.c
1 /*
2    Unix SMB/CIFS implementation.
3    ID Mapping Cache
4
5    Copyright (C) Volker Lendecke        2008
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
19
20 #include "includes.h"
21
22 /**
23  * Find a sid2uid mapping
24  * @param[in] sid               the sid to map
25  * @param[out] puid             where to put the result
26  * @param[out] expired          is the cache entry expired?
27  * @retval Was anything in the cache at all?
28  *
29  * If *puid == -1 this was a negative mapping.
30  */
31
32 bool idmap_cache_find_sid2uid(const struct dom_sid *sid, uid_t *puid,
33                               bool *expired)
34 {
35         fstring sidstr;
36         char *key;
37         char *value;
38         char *endptr;
39         time_t timeout;
40         uid_t uid;
41         bool ret;
42
43         key = talloc_asprintf(talloc_tos(), "IDMAP/SID2UID/%s",
44                               sid_to_fstring(sidstr, sid));
45         if (key == NULL) {
46                 return false;
47         }
48         ret = gencache_get(key, &value, &timeout);
49         TALLOC_FREE(key);
50         if (!ret) {
51                 return false;
52         }
53         uid = strtol(value, &endptr, 10);
54         ret = (*endptr == '\0');
55         SAFE_FREE(value);
56         if (ret) {
57                 *puid = uid;
58                 *expired = (timeout <= time(NULL));
59         }
60         return ret;
61 }
62
63 /**
64  * Find a uid2sid mapping
65  * @param[in] uid               the uid to map
66  * @param[out] sid              where to put the result
67  * @param[out] expired          is the cache entry expired?
68  * @retval Was anything in the cache at all?
69  *
70  * If "is_null_sid(sid)", this was a negative mapping.
71  */
72
73 bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired)
74 {
75         char *key;
76         char *value;
77         time_t timeout;
78         bool ret = true;
79
80         key = talloc_asprintf(talloc_tos(), "IDMAP/UID2SID/%d", (int)uid);
81         if (key == NULL) {
82                 return false;
83         }
84         ret = gencache_get(key, &value, &timeout);
85         TALLOC_FREE(key);
86         if (!ret) {
87                 return false;
88         }
89         ZERO_STRUCTP(sid);
90         if (value[0] != '-') {
91                 ret = string_to_sid(sid, value);
92         }
93         SAFE_FREE(value);
94         if (ret) {
95                 *expired = (timeout <= time(NULL));
96         }
97         return ret;
98 }
99
100 /**
101  * Store a mapping in the idmap cache
102  * @param[in] sid               the sid to map
103  * @param[in] uid               the uid to map
104  *
105  * If both parameters are valid values, then a positive mapping in both
106  * directions is stored. If "is_null_sid(sid)" is true, then this will be a
107  * negative mapping of uid, we want to cache that for this uid we could not
108  * find anything. Likewise if "uid==-1", then we want to cache that we did not
109  * find a mapping for the sid passed here.
110  */
111
112 void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid)
113 {
114         time_t now = time(NULL);
115         time_t timeout;
116         fstring sidstr, key, value;
117
118         if (!is_null_sid(sid)) {
119                 fstr_sprintf(key, "IDMAP/SID2UID/%s",
120                              sid_to_fstring(sidstr, sid));
121                 fstr_sprintf(value, "%d", (int)uid);
122                 timeout = (uid == -1)
123                         ? lp_idmap_negative_cache_time()
124                         : lp_idmap_cache_time();
125                 gencache_set(key, value, now + timeout);
126         }
127         if (uid != -1) {
128                 fstr_sprintf(key, "IDMAP/UID2SID/%d", (int)uid);
129                 if (is_null_sid(sid)) {
130                         /* negative uid mapping */
131                         fstrcpy(value, "-");
132                         timeout = lp_idmap_negative_cache_time();
133                 }
134                 else {
135                         sid_to_fstring(value, sid);
136                         timeout = lp_idmap_cache_time();
137                 }
138                 gencache_set(key, value, now + timeout);
139         }
140 }
141
142 /**
143  * Find a sid2gid mapping
144  * @param[in] sid               the sid to map
145  * @param[out] pgid             where to put the result
146  * @param[out] expired          is the cache entry expired?
147  * @retval Was anything in the cache at all?
148  *
149  * If *pgid == -1 this was a negative mapping.
150  */
151
152 bool idmap_cache_find_sid2gid(const struct dom_sid *sid, gid_t *pgid,
153                               bool *expired)
154 {
155         fstring sidstr;
156         char *key;
157         char *value;
158         char *endptr;
159         time_t timeout;
160         gid_t gid;
161         bool ret;
162
163         key = talloc_asprintf(talloc_tos(), "IDMAP/SID2GID/%s",
164                               sid_to_fstring(sidstr, sid));
165         if (key == NULL) {
166                 return false;
167         }
168         ret = gencache_get(key, &value, &timeout);
169         TALLOC_FREE(key);
170         if (!ret) {
171                 return false;
172         }
173         gid = strtol(value, &endptr, 10);
174         ret = (*endptr == '\0');
175         SAFE_FREE(value);
176         if (ret) {
177                 *pgid = gid;
178                 *expired = (timeout <= time(NULL));
179         }
180         return ret;
181 }
182
183 /**
184  * Find a gid2sid mapping
185  * @param[in] gid               the gid to map
186  * @param[out] sid              where to put the result
187  * @param[out] expired          is the cache entry expired?
188  * @retval Was anything in the cache at all?
189  *
190  * If "is_null_sid(sid)", this was a negative mapping.
191  */
192
193 bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired)
194 {
195         char *key;
196         char *value;
197         time_t timeout;
198         bool ret = true;
199
200         key = talloc_asprintf(talloc_tos(), "IDMAP/GID2SID/%d", (int)gid);
201         if (key == NULL) {
202                 return false;
203         }
204         ret = gencache_get(key, &value, &timeout);
205         TALLOC_FREE(key);
206         if (!ret) {
207                 return false;
208         }
209         ZERO_STRUCTP(sid);
210         if (value[0] != '-') {
211                 ret = string_to_sid(sid, value);
212         }
213         SAFE_FREE(value);
214         if (ret) {
215                 *expired = (timeout <= time(NULL));
216         }
217         return ret;
218 }
219
220 /**
221  * Store a mapping in the idmap cache
222  * @param[in] sid               the sid to map
223  * @param[in] gid               the gid to map
224  *
225  * If both parameters are valid values, then a positive mapping in both
226  * directions is stored. If "is_null_sid(sid)" is true, then this will be a
227  * negative mapping of gid, we want to cache that for this gid we could not
228  * find anything. Likewise if "gid==-1", then we want to cache that we did not
229  * find a mapping for the sid passed here.
230  */
231
232 void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid)
233 {
234         time_t now = time(NULL);
235         time_t timeout;
236         fstring sidstr, key, value;
237
238         if (!is_null_sid(sid)) {
239                 fstr_sprintf(key, "IDMAP/SID2GID/%s",
240                              sid_to_fstring(sidstr, sid));
241                 fstr_sprintf(value, "%d", (int)gid);
242                 timeout = (gid == -1)
243                         ? lp_idmap_negative_cache_time()
244                         : lp_idmap_cache_time();
245                 gencache_set(key, value, now + timeout);
246         }
247         if (gid != -1) {
248                 fstr_sprintf(key, "IDMAP/GID2SID/%d", (int)gid);
249                 if (is_null_sid(sid)) {
250                         /* negative gid mapping */
251                         fstrcpy(value, "-");
252                         timeout = lp_idmap_negative_cache_time();
253                 }
254                 else {
255                         sid_to_fstring(value, sid);
256                         timeout = lp_idmap_cache_time();
257                 }
258                 gencache_set(key, value, now + timeout);
259         }
260 }