~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/hx509/ks_dir.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2006 Kungliga Tekniska Högskolan
 
3
 * (Royal Institute of Technology, Stockholm, Sweden).
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 *
 
10
 * 1. Redistributions of source code must retain the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer.
 
12
 *
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 *
 
17
 * 3. Neither the name of the Institute nor the names of its contributors
 
18
 *    may be used to endorse or promote products derived from this software
 
19
 *    without specific prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
31
 * SUCH DAMAGE.
 
32
 */
 
33
 
 
34
#include "hx_locl.h"
 
35
RCSID("$Id$");
 
36
#include <dirent.h>
 
37
 
 
38
/*
 
39
 * The DIR keyset module is strange compared to the other modules
 
40
 * since it does lazy evaluation and really doesn't keep any local
 
41
 * state except for the directory iteration and cert iteration of
 
42
 * files. DIR ignores most errors so that the consumer doesn't get
 
43
 * failes for stray files in directories.
 
44
 */
 
45
 
 
46
struct dircursor {
 
47
    DIR *dir;
 
48
    hx509_certs certs;
 
49
    void *iter;
 
50
};
 
51
 
 
52
/*
 
53
 *
 
54
 */
 
55
 
 
56
static int
 
57
dir_init(hx509_context context,
 
58
         hx509_certs certs, void **data, int flags,
 
59
         const char *residue, hx509_lock lock)
 
60
{
 
61
    *data = NULL;
 
62
 
 
63
    {
 
64
        struct stat sb;
 
65
        int ret;
 
66
 
 
67
        ret = stat(residue, &sb);
 
68
        if (ret == -1) {
 
69
            hx509_set_error_string(context, 0, ENOENT,
 
70
                                   "No such file %s", residue);
 
71
            return ENOENT;
 
72
        }
 
73
 
 
74
        if ((sb.st_mode & S_IFDIR) == 0) {
 
75
            hx509_set_error_string(context, 0, ENOTDIR,
 
76
                                   "%s is not a directory", residue);
 
77
            return ENOTDIR;
 
78
        }
 
79
    }
 
80
 
 
81
    *data = strdup(residue);
 
82
    if (*data == NULL) {
 
83
        hx509_clear_error_string(context);
 
84
        return ENOMEM;
 
85
    }
 
86
 
 
87
    return 0;
 
88
}
 
89
 
 
90
static int
 
91
dir_free(hx509_certs certs, void *data)
 
92
{
 
93
    free(data);
 
94
    return 0;
 
95
}
 
96
 
 
97
 
 
98
 
 
99
static int
 
100
dir_iter_start(hx509_context context,
 
101
               hx509_certs certs, void *data, void **cursor)
 
102
{
 
103
    struct dircursor *d;
 
104
 
 
105
    *cursor = NULL;
 
106
 
 
107
    d = calloc(1, sizeof(*d));
 
108
    if (d == NULL) {
 
109
        hx509_clear_error_string(context);
 
110
        return ENOMEM;
 
111
    }
 
112
 
 
113
    d->dir = opendir(data);
 
114
    if (d->dir == NULL) {
 
115
        hx509_clear_error_string(context);
 
116
        free(d);
 
117
        return errno;
 
118
    }
 
119
    rk_cloexec(dirfd(d->dir));
 
120
    d->certs = NULL;
 
121
    d->iter = NULL;
 
122
 
 
123
    *cursor = d;
 
124
    return 0;
 
125
}
 
126
 
 
127
static int
 
128
dir_iter(hx509_context context,
 
129
         hx509_certs certs, void *data, void *iter, hx509_cert *cert)
 
130
{
 
131
    struct dircursor *d = iter;
 
132
    int ret = 0;
 
133
 
 
134
    *cert = NULL;
 
135
 
 
136
    do {
 
137
        struct dirent *dir;
 
138
        char *fn;
 
139
 
 
140
        if (d->certs) {
 
141
            ret = hx509_certs_next_cert(context, d->certs, d->iter, cert);
 
142
            if (ret) {
 
143
                hx509_certs_end_seq(context, d->certs, d->iter);
 
144
                d->iter = NULL;
 
145
                hx509_certs_free(&d->certs);
 
146
                return ret;
 
147
            }
 
148
            if (*cert) {
 
149
                ret = 0;
 
150
                break;
 
151
            }
 
152
            hx509_certs_end_seq(context, d->certs, d->iter);
 
153
            d->iter = NULL;
 
154
            hx509_certs_free(&d->certs);
 
155
        }
 
156
 
 
157
        dir = readdir(d->dir);
 
158
        if (dir == NULL) {
 
159
            ret = 0;
 
160
            break;
 
161
        }
 
162
        if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0)
 
163
            continue;
 
164
        
 
165
        if (asprintf(&fn, "FILE:%s/%s", (char *)data, dir->d_name) == -1)
 
166
            return ENOMEM;
 
167
        
 
168
        ret = hx509_certs_init(context, fn, 0, NULL, &d->certs);
 
169
        if (ret == 0) {
 
170
 
 
171
            ret = hx509_certs_start_seq(context, d->certs, &d->iter);
 
172
            if (ret)
 
173
            hx509_certs_free(&d->certs);
 
174
        }
 
175
        /* ignore errors */
 
176
        if (ret) {
 
177
            d->certs = NULL;
 
178
            ret = 0;
 
179
        }
 
180
 
 
181
        free(fn);
 
182
    } while(ret == 0);
 
183
 
 
184
    return ret;
 
185
}
 
186
 
 
187
 
 
188
static int
 
189
dir_iter_end(hx509_context context,
 
190
             hx509_certs certs,
 
191
             void *data,
 
192
             void *cursor)
 
193
{
 
194
    struct dircursor *d = cursor;
 
195
 
 
196
    if (d->certs) {
 
197
        hx509_certs_end_seq(context, d->certs, d->iter);
 
198
        d->iter = NULL;
 
199
        hx509_certs_free(&d->certs);
 
200
    }
 
201
    closedir(d->dir);
 
202
    free(d);
 
203
    return 0;
 
204
}
 
205
 
 
206
 
 
207
static struct hx509_keyset_ops keyset_dir = {
 
208
    "DIR",
 
209
    0,
 
210
    dir_init,
 
211
    NULL,
 
212
    dir_free,
 
213
    NULL,
 
214
    NULL,
 
215
    dir_iter_start,
 
216
    dir_iter,
 
217
    dir_iter_end
 
218
};
 
219
 
 
220
void
 
221
_hx509_ks_dir_register(hx509_context context)
 
222
{
 
223
    _hx509_ks_register(context, &keyset_dir);
 
224
}