~ubuntu-branches/ubuntu/saucy/sssd/saucy

« back to all changes in this revision

Viewing changes to server/responder/nss/nsssrv_nc.c

  • Committer: Stéphane Graber
  • Date: 2011-06-15 16:23:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: stgraber@ubuntu.com-20110615162314-rbhoppnpaxfqo5q7
Merge 1.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
   SSSD
3
 
 
4
 
   NSS Responder
5
 
 
6
 
   Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
7
 
 
8
 
   This program is free software; you can redistribute it and/or modify
9
 
   it under the terms of the GNU General Public License as published by
10
 
   the Free Software Foundation; either version 3 of the License, or
11
 
   (at your option) any later version.
12
 
 
13
 
   This program is distributed in the hope that it will be useful,
14
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
   GNU General Public License for more details.
17
 
 
18
 
   You should have received a copy of the GNU General Public License
19
 
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 
*/
21
 
 
22
 
#include "util/util.h"
23
 
#include <fcntl.h>
24
 
#include <time.h>
25
 
#include "tdb.h"
26
 
 
27
 
#define NC_ENTRY_PREFIX "NCE/"
28
 
#define NC_USER_PREFIX NC_ENTRY_PREFIX"USER"
29
 
#define NC_GROUP_PREFIX NC_ENTRY_PREFIX"GROUP"
30
 
#define NC_UID_PREFIX NC_ENTRY_PREFIX"UID"
31
 
#define NC_GID_PREFIX NC_ENTRY_PREFIX"GID"
32
 
 
33
 
struct nss_nc_ctx {
34
 
    struct tdb_context *tdb;
35
 
};
36
 
 
37
 
static int string_to_tdb_data(char *str, TDB_DATA *ret)
38
 
{
39
 
    if (!str || !ret) return EINVAL;
40
 
 
41
 
    ret->dptr = (uint8_t *)str;
42
 
    ret->dsize = strlen(str)+1;
43
 
 
44
 
    return EOK;
45
 
}
46
 
 
47
 
int nss_ncache_init(TALLOC_CTX *memctx, struct nss_nc_ctx **_ctx)
48
 
{
49
 
    struct nss_nc_ctx *ctx;
50
 
 
51
 
    ctx = talloc_zero(memctx, struct nss_nc_ctx);
52
 
    if (!ctx) return ENOMEM;
53
 
 
54
 
    errno = 0;
55
 
    /* open a memory only tdb with default hash size */
56
 
    ctx->tdb = tdb_open("memcache", 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0);
57
 
    if (!ctx->tdb) return errno;
58
 
 
59
 
    *_ctx = ctx;
60
 
    return EOK;
61
 
};
62
 
 
63
 
static int nss_ncache_check_str(struct nss_nc_ctx *ctx, char *str, int ttl)
64
 
{
65
 
    TDB_DATA key;
66
 
    TDB_DATA data;
67
 
    unsigned long long int timestamp;
68
 
    bool expired = false;
69
 
    char *ep;
70
 
    int ret;
71
 
 
72
 
    ret = string_to_tdb_data(str, &key);
73
 
    if (ret != EOK) goto done;
74
 
 
75
 
    data = tdb_fetch(ctx->tdb, key);
76
 
 
77
 
    if (!data.dptr) {
78
 
        ret = ENOENT;
79
 
        goto done;
80
 
    }
81
 
 
82
 
    if (ttl == -1) {
83
 
        /* a negative ttl means: never expires */
84
 
        ret = EEXIST;
85
 
        goto done;
86
 
    }
87
 
 
88
 
    errno = 0;
89
 
    timestamp = strtoull((const char *)data.dptr, &ep, 0);
90
 
    if (errno != 0 || *ep != '\0') {
91
 
        /* Malformed entry, remove it and return no entry */
92
 
        expired = true;
93
 
        goto done;
94
 
    }
95
 
 
96
 
    if (timestamp == 0) {
97
 
        /* a 0 timestamp means this is a permanent entry */
98
 
        ret = EEXIST;
99
 
        goto done;
100
 
    }
101
 
 
102
 
    if (timestamp + ttl > time(NULL)) {
103
 
        /* still valid */
104
 
        ret = EEXIST;
105
 
        goto done;
106
 
    }
107
 
 
108
 
    expired = true;
109
 
 
110
 
done:
111
 
    if (expired) {
112
 
        /* expired, remove and return no entry */
113
 
        tdb_delete(ctx->tdb, key);
114
 
        ret = ENOENT;
115
 
    }
116
 
 
117
 
    return ret;
118
 
}
119
 
 
120
 
static int nss_ncache_set_str(struct nss_nc_ctx *ctx,
121
 
                              char *str, bool permanent)
122
 
{
123
 
    TDB_DATA key;
124
 
    TDB_DATA data;
125
 
    char *timest;
126
 
    int ret;
127
 
 
128
 
    ret = string_to_tdb_data(str, &key);
129
 
    if (ret != EOK) return ret;
130
 
 
131
 
    if (permanent) {
132
 
        timest = talloc_strdup(ctx, "0");
133
 
    } else {
134
 
        timest = talloc_asprintf(ctx, "%llu",
135
 
                                 (unsigned long long int)time(NULL));
136
 
    }
137
 
    if (!timest) return ENOMEM;
138
 
 
139
 
    ret = string_to_tdb_data(timest, &data);
140
 
    if (ret != EOK) goto done;
141
 
 
142
 
    ret = tdb_store(ctx->tdb, key, data, TDB_REPLACE);
143
 
    if (ret != 0) {
144
 
        DEBUG(1, ("Negative cache failed to set entry: [%s]",
145
 
                  tdb_errorstr(ctx->tdb)));
146
 
        ret = EFAULT;
147
 
    }
148
 
 
149
 
done:
150
 
    talloc_free(timest);
151
 
    return ret;
152
 
}
153
 
 
154
 
int nss_ncache_check_user(struct nss_nc_ctx *ctx, int ttl,
155
 
                          const char *domain, const char *name)
156
 
{
157
 
    char *str;
158
 
    int ret;
159
 
 
160
 
    if (!name || !*name) return EINVAL;
161
 
 
162
 
    str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
163
 
    if (!str) return ENOMEM;
164
 
 
165
 
    ret = nss_ncache_check_str(ctx, str, ttl);
166
 
 
167
 
    talloc_free(str);
168
 
    return ret;
169
 
}
170
 
 
171
 
int nss_ncache_check_group(struct nss_nc_ctx *ctx, int ttl,
172
 
                           const char *domain, const char *name)
173
 
{
174
 
    char *str;
175
 
    int ret;
176
 
 
177
 
    if (!name || !*name) return EINVAL;
178
 
 
179
 
    str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
180
 
    if (!str) return ENOMEM;
181
 
 
182
 
    ret = nss_ncache_check_str(ctx, str, ttl);
183
 
 
184
 
    talloc_free(str);
185
 
    return ret;
186
 
}
187
 
 
188
 
int nss_ncache_check_uid(struct nss_nc_ctx *ctx, int ttl, uid_t uid)
189
 
{
190
 
    char *str;
191
 
    int ret;
192
 
 
193
 
    str = talloc_asprintf(ctx, "%s/%u", NC_UID_PREFIX, uid);
194
 
    if (!str) return ENOMEM;
195
 
 
196
 
    ret = nss_ncache_check_str(ctx, str, ttl);
197
 
 
198
 
    talloc_free(str);
199
 
    return ret;
200
 
}
201
 
 
202
 
int nss_ncache_check_gid(struct nss_nc_ctx *ctx, int ttl, gid_t gid)
203
 
{
204
 
    char *str;
205
 
    int ret;
206
 
 
207
 
    str = talloc_asprintf(ctx, "%s/%u", NC_GID_PREFIX, gid);
208
 
    if (!str) return ENOMEM;
209
 
 
210
 
    ret = nss_ncache_check_str(ctx, str, ttl);
211
 
 
212
 
    talloc_free(str);
213
 
    return ret;
214
 
}
215
 
 
216
 
int nss_ncache_set_user(struct nss_nc_ctx *ctx, bool permanent,
217
 
                        const char *domain, const char *name)
218
 
{
219
 
    char *str;
220
 
    int ret;
221
 
 
222
 
    if (!name || !*name) return EINVAL;
223
 
 
224
 
    str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
225
 
    if (!str) return ENOMEM;
226
 
 
227
 
    ret = nss_ncache_set_str(ctx, str, permanent);
228
 
 
229
 
    talloc_free(str);
230
 
    return ret;
231
 
}
232
 
 
233
 
int nss_ncache_set_group(struct nss_nc_ctx *ctx, bool permanent,
234
 
                        const char *domain, const char *name)
235
 
{
236
 
    char *str;
237
 
    int ret;
238
 
 
239
 
    if (!name || !*name) return EINVAL;
240
 
 
241
 
    str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
242
 
    if (!str) return ENOMEM;
243
 
 
244
 
    ret = nss_ncache_set_str(ctx, str, permanent);
245
 
 
246
 
    talloc_free(str);
247
 
    return ret;
248
 
}
249
 
 
250
 
int nss_ncache_set_uid(struct nss_nc_ctx *ctx, bool permanent, uid_t uid)
251
 
{
252
 
    char *str;
253
 
    int ret;
254
 
 
255
 
    str = talloc_asprintf(ctx, "%s/%u", NC_UID_PREFIX, uid);
256
 
    if (!str) return ENOMEM;
257
 
 
258
 
    ret = nss_ncache_set_str(ctx, str, permanent);
259
 
 
260
 
    talloc_free(str);
261
 
    return ret;
262
 
}
263
 
 
264
 
int nss_ncache_set_gid(struct nss_nc_ctx *ctx, bool permanent, gid_t gid)
265
 
{
266
 
    char *str;
267
 
    int ret;
268
 
 
269
 
    str = talloc_asprintf(ctx, "%s/%u", NC_GID_PREFIX, gid);
270
 
    if (!str) return ENOMEM;
271
 
 
272
 
    ret = nss_ncache_set_str(ctx, str, permanent);
273
 
 
274
 
    talloc_free(str);
275
 
    return ret;
276
 
}
277
 
 
278
 
static int delete_permanent(struct tdb_context *tdb,
279
 
                            TDB_DATA key, TDB_DATA data, void *state)
280
 
{
281
 
    unsigned long long int timestamp;
282
 
    bool remove_key = false;
283
 
    char *ep;
284
 
 
285
 
    if (strncmp((char *)key.dptr,
286
 
                NC_ENTRY_PREFIX, sizeof(NC_ENTRY_PREFIX)) != 0) {
287
 
        /* not interested in this key */
288
 
        return 0;
289
 
    }
290
 
 
291
 
    errno = 0;
292
 
    timestamp = strtoull((const char *)data.dptr, &ep, 0);
293
 
    if (errno != 0 || *ep != '\0') {
294
 
        /* Malformed entry, remove it */
295
 
        remove_key = true;
296
 
        goto done;
297
 
    }
298
 
 
299
 
    if (timestamp == 0) {
300
 
        /* a 0 timestamp means this is a permanent entry */
301
 
        remove_key = true;
302
 
    }
303
 
 
304
 
done:
305
 
    if (remove_key) {
306
 
        return tdb_delete(tdb, key);
307
 
    }
308
 
 
309
 
    return 0;
310
 
}
311
 
 
312
 
int nss_ncache_reset_permament(struct nss_nc_ctx *ctx)
313
 
{
314
 
    int ret;
315
 
 
316
 
    ret = tdb_traverse(ctx->tdb, delete_permanent, NULL);
317
 
    if (ret < 0)
318
 
        return EIO;
319
 
 
320
 
    return EOK;
321
 
}