~ubuntu-branches/ubuntu/karmic/sssd/karmic

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2009-08-24 16:35:11 UTC
  • Revision ID: james.westby@ubuntu.com-20090824163511-l20qd53jlb0bv56d
Tags: upstream-0.5.0
ImportĀ upstreamĀ versionĀ 0.5.0

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
}