libcli/security Provide a common, top level libcli/security/security.h
[kai/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 #include "idmap_cache.h"
22 #include "../libcli/security/security.h"
23
24 /**
25  * Find a sid2uid mapping
26  * @param[in] sid               the sid to map
27  * @param[out] puid             where to put the result
28  * @param[out] expired          is the cache entry expired?
29  * @retval Was anything in the cache at all?
30  *
31  * If *puid == -1 this was a negative mapping.
32  */
33
34 bool idmap_cache_find_sid2uid(const struct dom_sid *sid, uid_t *puid,
35                               bool *expired)
36 {
37         fstring sidstr;
38         char *key;
39         char *value;
40         char *endptr;
41         time_t timeout;
42         uid_t uid;
43         bool ret;
44
45         key = talloc_asprintf(talloc_tos(), "IDMAP/SID2UID/%s",
46                               sid_to_fstring(sidstr, sid));
47         if (key == NULL) {
48                 return false;
49         }
50         ret = gencache_get(key, &value, &timeout);
51         TALLOC_FREE(key);
52         if (!ret) {
53                 return false;
54         }
55         uid = strtol(value, &endptr, 10);
56         ret = (*endptr == '\0');
57         SAFE_FREE(value);
58         if (ret) {
59                 *puid = uid;
60                 *expired = (timeout <= time(NULL));
61         }
62         return ret;
63 }
64
65 /**
66  * Find a uid2sid mapping
67  * @param[in] uid               the uid to map
68  * @param[out] sid              where to put the result
69  * @param[out] expired          is the cache entry expired?
70  * @retval Was anything in the cache at all?
71  *
72  * If "is_null_sid(sid)", this was a negative mapping.
73  */
74
75 bool idmap_cache_find_uid2sid(uid_t uid, struct dom_sid *sid, bool *expired)
76 {
77         char *key;
78         char *value;
79         time_t timeout;
80         bool ret = true;
81
82         key = talloc_asprintf(talloc_tos(), "IDMAP/UID2SID/%d", (int)uid);
83         if (key == NULL) {
84                 return false;
85         }
86         ret = gencache_get(key, &value, &timeout);
87         TALLOC_FREE(key);
88         if (!ret) {
89                 return false;
90         }
91         ZERO_STRUCTP(sid);
92         if (value[0] != '-') {
93                 ret = string_to_sid(sid, value);
94         }
95         SAFE_FREE(value);
96         if (ret) {
97                 *expired = (timeout <= time(NULL));
98         }
99         return ret;
100 }
101
102 /**
103  * Store a mapping in the idmap cache
104  * @param[in] sid               the sid to map
105  * @param[in] uid               the uid to map
106  *
107  * If both parameters are valid values, then a positive mapping in both
108  * directions is stored. If "is_null_sid(sid)" is true, then this will be a
109  * negative mapping of uid, we want to cache that for this uid we could not
110  * find anything. Likewise if "uid==-1", then we want to cache that we did not
111  * find a mapping for the sid passed here.
112  */
113
114 void idmap_cache_set_sid2uid(const struct dom_sid *sid, uid_t uid)
115 {
116         time_t now = time(NULL);
117         time_t timeout;
118         fstring sidstr, key, value;
119
120         if (!is_null_sid(sid)) {
121                 fstr_sprintf(key, "IDMAP/SID2UID/%s",
122                              sid_to_fstring(sidstr, sid));
123                 fstr_sprintf(value, "%d", (int)uid);
124                 timeout = (uid == -1)
125                         ? lp_idmap_negative_cache_time()
126                         : lp_idmap_cache_time();
127                 gencache_set(key, value, now + timeout);
128         }
129         if (uid != -1) {
130                 fstr_sprintf(key, "IDMAP/UID2SID/%d", (int)uid);
131                 if (is_null_sid(sid)) {
132                         /* negative uid mapping */
133                         fstrcpy(value, "-");
134                         timeout = lp_idmap_negative_cache_time();
135                 }
136                 else {
137                         sid_to_fstring(value, sid);
138                         timeout = lp_idmap_cache_time();
139                 }
140                 gencache_set(key, value, now + timeout);
141         }
142 }
143
144 /**
145  * Find a sid2gid mapping
146  * @param[in] sid               the sid to map
147  * @param[out] pgid             where to put the result
148  * @param[out] expired          is the cache entry expired?
149  * @retval Was anything in the cache at all?
150  *
151  * If *pgid == -1 this was a negative mapping.
152  */
153
154 bool idmap_cache_find_sid2gid(const struct dom_sid *sid, gid_t *pgid,
155                               bool *expired)
156 {
157         fstring sidstr;
158         char *key;
159         char *value;
160         char *endptr;
161         time_t timeout;
162         gid_t gid;
163         bool ret;
164
165         key = talloc_asprintf(talloc_tos(), "IDMAP/SID2GID/%s",
166                               sid_to_fstring(sidstr, sid));
167         if (key == NULL) {
168                 return false;
169         }
170         ret = gencache_get(key, &value, &timeout);
171         TALLOC_FREE(key);
172         if (!ret) {
173                 return false;
174         }
175         gid = strtol(value, &endptr, 10);
176         ret = (*endptr == '\0');
177         SAFE_FREE(value);
178         if (ret) {
179                 *pgid = gid;
180                 *expired = (timeout <= time(NULL));
181         }
182         return ret;
183 }
184
185 /**
186  * Find a gid2sid mapping
187  * @param[in] gid               the gid to map
188  * @param[out] sid              where to put the result
189  * @param[out] expired          is the cache entry expired?
190  * @retval Was anything in the cache at all?
191  *
192  * If "is_null_sid(sid)", this was a negative mapping.
193  */
194
195 bool idmap_cache_find_gid2sid(gid_t gid, struct dom_sid *sid, bool *expired)
196 {
197         char *key;
198         char *value;
199         time_t timeout;
200         bool ret = true;
201
202         key = talloc_asprintf(talloc_tos(), "IDMAP/GID2SID/%d", (int)gid);
203         if (key == NULL) {
204                 return false;
205         }
206         ret = gencache_get(key, &value, &timeout);
207         TALLOC_FREE(key);
208         if (!ret) {
209                 return false;
210         }
211         ZERO_STRUCTP(sid);
212         if (value[0] != '-') {
213                 ret = string_to_sid(sid, value);
214         }
215         SAFE_FREE(value);
216         if (ret) {
217                 *expired = (timeout <= time(NULL));
218         }
219         return ret;
220 }
221
222 /**
223  * Store a mapping in the idmap cache
224  * @param[in] sid               the sid to map
225  * @param[in] gid               the gid to map
226  *
227  * If both parameters are valid values, then a positive mapping in both
228  * directions is stored. If "is_null_sid(sid)" is true, then this will be a
229  * negative mapping of gid, we want to cache that for this gid we could not
230  * find anything. Likewise if "gid==-1", then we want to cache that we did not
231  * find a mapping for the sid passed here.
232  */
233
234 void idmap_cache_set_sid2gid(const struct dom_sid *sid, gid_t gid)
235 {
236         time_t now = time(NULL);
237         time_t timeout;
238         fstring sidstr, key, value;
239
240         if (!is_null_sid(sid)) {
241                 fstr_sprintf(key, "IDMAP/SID2GID/%s",
242                              sid_to_fstring(sidstr, sid));
243                 fstr_sprintf(value, "%d", (int)gid);
244                 timeout = (gid == -1)
245                         ? lp_idmap_negative_cache_time()
246                         : lp_idmap_cache_time();
247                 gencache_set(key, value, now + timeout);
248         }
249         if (gid != -1) {
250                 fstr_sprintf(key, "IDMAP/GID2SID/%d", (int)gid);
251                 if (is_null_sid(sid)) {
252                         /* negative gid mapping */
253                         fstrcpy(value, "-");
254                         timeout = lp_idmap_negative_cache_time();
255                 }
256                 else {
257                         sid_to_fstring(value, sid);
258                         timeout = lp_idmap_cache_time();
259                 }
260                 gencache_set(key, value, now + timeout);
261         }
262 }