~ubuntu-branches/debian/sid/ecryptfs-utils/sid

« back to all changes in this revision

Viewing changes to src/libecryptfs/cmd_ln_parser.c

  • Committer: Bazaar Package Importer
  • Author(s): William Lima
  • Date: 2007-05-09 16:21:23 UTC
  • Revision ID: james.westby@ubuntu.com-20070509162123-b2ge8a5w7weqt5ea
Tags: upstream-15
ImportĀ upstreamĀ versionĀ 15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Copyright (C) 2006 International Business Machines Corp.
 
3
 *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
 
4
 *              Trevor Highland <trevor.highland@gmail.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License as
 
8
 * published by the Free Software Foundation; either version 2 of the
 
9
 * License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
 
 
22
#ifndef S_SPLINT_S
 
23
#include <sys/types.h>
 
24
#include <sys/stat.h>
 
25
#endif /* S_SPLINT_S */
 
26
#include <sys/mman.h>
 
27
#include <fcntl.h>
 
28
#include <string.h>
 
29
#ifndef S_SPLINT_S
 
30
#include <stdio.h>
 
31
#include <syslog.h>
 
32
#endif /* S_SPLINT_S */
 
33
#include <errno.h>
 
34
#include <stdlib.h>
 
35
#include <pwd.h>
 
36
#include "../include/ecryptfs.h"
 
37
 
 
38
#define MAX_TOK_LEN 128
 
39
#define MAX_FILE_SIZE 0xa000
 
40
 
 
41
int print_nvp_list(struct ecryptfs_name_val_pair *dst)
 
42
{
 
43
        syslog(LOG_ERR, "Printing nvp list\n");
 
44
        while (dst) {
 
45
                syslog(LOG_ERR, "name=%s\n", dst->name);
 
46
                syslog(LOG_ERR, "val=%s\n", dst->value);
 
47
                dst = dst->next;
 
48
        }
 
49
        return 0;
 
50
}
 
51
 
 
52
/**
 
53
 * For each name in dst that is also in src, set the value in dst to
 
54
 * that which is in src.
 
55
 *
 
56
 * For each name in src that is not in dst, append a copy of the node
 
57
 * onto dst.
 
58
 */
 
59
int ecryptfs_nvp_list_union(struct ecryptfs_name_val_pair *dst,
 
60
                            struct ecryptfs_name_val_pair *src)
 
61
{
 
62
        int rc = 0;
 
63
        struct ecryptfs_name_val_pair *dst_cursor;
 
64
        struct ecryptfs_name_val_pair *src_cursor;
 
65
 
 
66
        src_cursor = src->next;
 
67
        while (src_cursor) {
 
68
                int found_match;
 
69
                struct ecryptfs_name_val_pair *prev_dst_cursor;
 
70
 
 
71
                if (!src_cursor->name)
 
72
                        goto next_src_cursor;
 
73
                found_match = 0;
 
74
                prev_dst_cursor = dst;
 
75
                dst_cursor = dst->next;
 
76
                while (dst_cursor) {
 
77
                        if (!dst_cursor->name)
 
78
                                goto next_dst_cursor;
 
79
                        if (strcmp(src_cursor->name, dst_cursor->name) == 0) {
 
80
                                found_match = 1;
 
81
                                free(dst_cursor->value);
 
82
                                rc = asprintf(&dst_cursor->value, "%s",
 
83
                                              src_cursor->value);
 
84
                                if (rc == -1) {
 
85
                                        rc = -ENOMEM;
 
86
                                        goto out;
 
87
                                }
 
88
                        }
 
89
next_dst_cursor:
 
90
                        prev_dst_cursor = dst_cursor;
 
91
                        dst_cursor = dst_cursor->next;
 
92
                }
 
93
                if (!found_match) {
 
94
                        prev_dst_cursor->next = dst_cursor =
 
95
                                malloc(sizeof(struct ecryptfs_name_val_pair));
 
96
                        if (!dst_cursor) {
 
97
                                rc = -ENOMEM;
 
98
                                goto out;
 
99
                        }
 
100
                        dst_cursor->next = NULL;
 
101
                        dst_cursor->flags = src_cursor->flags;
 
102
                        rc = asprintf(&dst_cursor->name, "%s",
 
103
                                      src_cursor->name);
 
104
                        if (rc == -1) {
 
105
                                rc = -ENOMEM;
 
106
                                goto out;
 
107
                        }
 
108
                        rc = asprintf(&dst_cursor->value, "%s",
 
109
                                      src_cursor->value);
 
110
                        if (rc == -1) {
 
111
                                rc = -ENOMEM;
 
112
                                goto out;
 
113
                        }
 
114
                }
 
115
next_src_cursor:
 
116
                src_cursor = src_cursor->next;
 
117
        }
 
118
out:
 
119
        return rc;
 
120
}
 
121
 
 
122
int
 
123
ecryptfs_parse_rc_file_fullpath(struct ecryptfs_name_val_pair *nvp_list_head,
 
124
                                char *fullpath)
 
125
{
 
126
        int rc;
 
127
        int fd;
 
128
 
 
129
        fd = open(fullpath, O_RDONLY);
 
130
        if (fd == -1) {
 
131
                rc = -EIO;
 
132
                goto out;
 
133
        }
 
134
        rc = parse_options_file(fd, nvp_list_head);
 
135
        close(fd);
 
136
out:
 
137
        return rc;
 
138
}
 
139
 
 
140
int ecryptfs_parse_rc_file(struct ecryptfs_name_val_pair *nvp_list_head)
 
141
{
 
142
        char *home;
 
143
        uid_t uid;
 
144
        struct passwd *pw;
 
145
        char *rcfile_fullpath;
 
146
        int rc;
 
147
 
 
148
        uid = getuid();
 
149
        pw = getpwuid(uid);
 
150
        home = pw->pw_dir;
 
151
        rc = asprintf(&rcfile_fullpath, "%s/.ecryptfsrc", home);
 
152
        if (rc == -1) {
 
153
                rc = -ENOMEM;
 
154
                goto out;
 
155
        }
 
156
        rc = ecryptfs_parse_rc_file_fullpath(nvp_list_head, rcfile_fullpath);
 
157
        free(rcfile_fullpath);
 
158
out:
 
159
        return rc;
 
160
}
 
161
 
 
162
int process_comma_tok(struct ecryptfs_name_val_pair **current, char *tok,
 
163
                      /*@null@*/ char *prefix)
 
164
{
 
165
        int tok_len = (int)strlen(tok);
 
166
        char new_prefix[MAX_TOK_LEN];
 
167
        char sub_token[MAX_TOK_LEN];
 
168
        char *name = NULL;
 
169
        char *value = NULL;
 
170
        int i, j, st_len;
 
171
        int rc = 0;
 
172
 
 
173
        if(tok && tok[0] == '\0') {
 
174
                goto out;
 
175
        }
 
176
        if (tok_len < 0 || tok_len > MAX_TOK_LEN) {
 
177
                rc = -EINVAL;
 
178
                goto out;
 
179
        }
 
180
        if (tok[0] == '=' || tok[0] == ':') {
 
181
                rc = -EINVAL;
 
182
                goto out;
 
183
        }
 
184
        j = 0;
 
185
        if (tok_len > 4 && !memcmp(tok, "key=", 4))
 
186
                for (i = 4; i < tok_len; i++) {
 
187
                        if (tok[i] == ':')
 
188
                                goto process_colon_list;
 
189
                }
 
190
        goto process_nv_pair;
 
191
process_colon_list:
 
192
        new_prefix[j] = '\0';
 
193
        i = 0;
 
194
        j = 0;
 
195
        while (i < tok_len) {
 
196
                if (tok[i] == ':') {
 
197
                        sub_token[j] = '\0';
 
198
                        if ((rc = process_comma_tok(current, sub_token, NULL)))
 
199
                                goto out;
 
200
                        j = 0;
 
201
                } else
 
202
                        sub_token[j++] = tok[i];
 
203
                i++;
 
204
        }
 
205
        sub_token[j] = '\0';
 
206
        rc = process_comma_tok(current, sub_token, new_prefix);
 
207
        goto out;
 
208
process_nv_pair:
 
209
        st_len = snprintf(sub_token, MAX_TOK_LEN, "%s%s",
 
210
                          (prefix ? prefix : ""), tok);
 
211
        j = 0;
 
212
        for (i = 0; i < st_len; i++)
 
213
                if (sub_token[i] == '=') {
 
214
                        if (!(name = malloc(i + 1))) {
 
215
                                rc = -ENOMEM;
 
216
                                goto out;
 
217
                        }
 
218
                        memcpy(name, sub_token, i);
 
219
                        name[i] = '\0';
 
220
                        j = i;
 
221
                }
 
222
        if (!name) {
 
223
                if (!(name = malloc(i+1))) {
 
224
                        rc = -ENOMEM;
 
225
                        goto out;
 
226
                }
 
227
                memcpy(name, sub_token, i);
 
228
                name[i] = '\0';
 
229
        } else {
 
230
                if((i-j) > 1) {
 
231
                        if (!(value = malloc(i - j + 1))) {
 
232
                                rc = -ENOMEM;
 
233
                                goto out;
 
234
                        }
 
235
                        memcpy(value, &sub_token[j+1], (i - j));
 
236
                        value[(i - j)] = '\0';
 
237
                }
 
238
        }
 
239
        if (!((*current)->next =
 
240
              malloc(sizeof(struct ecryptfs_name_val_pair)))) {
 
241
                rc = -ENOMEM;
 
242
                goto out;
 
243
        }
 
244
        if (strlen(name) == 0) {
 
245
                free(name);
 
246
                free(value);
 
247
        } else {
 
248
                *current = (*current)->next;
 
249
                (*current)->name = name;
 
250
                (*current)->value = value;
 
251
                (*current)->next = NULL;
 
252
        }
 
253
out:
 
254
        return rc;
 
255
}
 
256
 
 
257
/**
 
258
 * name=val,key=PKI:name1=val1:name2=val2,name=val...
 
259
 */
 
260
int generate_nv_list(struct ecryptfs_name_val_pair *head, char *buf)
 
261
{
 
262
        struct ecryptfs_name_val_pair *current = head;
 
263
        char tok_str[MAX_TOK_LEN];
 
264
        int buf_len = strlen(buf);
 
265
        int i, j = 0;
 
266
        int rc = 0;
 
267
 
 
268
        for (i = 0; i < buf_len; i++) {
 
269
                if (buf[i] == ',' || buf[i] == '\n') {
 
270
                        tok_str[j] = '\0';
 
271
                        if ((rc = process_comma_tok(&current, tok_str, NULL)))
 
272
                                goto out;
 
273
                        j = 0;
 
274
                } else
 
275
                        tok_str[j++] = buf[i];
 
276
                if (j == MAX_TOK_LEN)
 
277
                        goto out;
 
278
        }
 
279
        tok_str[j] = '\0';
 
280
        if ((rc = process_comma_tok(&current, tok_str, NULL)))
 
281
                goto out;
 
282
out:
 
283
        return rc;
 
284
}
 
285
 
 
286
int ecryptfs_parse_options(char *opts, struct ecryptfs_name_val_pair *head)
 
287
{
 
288
        return generate_nv_list(head, opts);
 
289
}
 
290
 
 
291
int parse_options_file(int fd, struct ecryptfs_name_val_pair *head)
 
292
{
 
293
        int rc = 0;
 
294
        int pagesize;
 
295
        char *data;
 
296
        off_t file_size;
 
297
        struct stat filestat;
 
298
 
 
299
        rc = fstat(fd, &filestat);
 
300
        if (rc)
 
301
                goto out;
 
302
        pagesize = getpagesize();
 
303
        file_size = filestat.st_size;
 
304
        if (file_size > MAX_FILE_SIZE) {
 
305
                syslog(LOG_ERR, "File size too large\n");
 
306
                rc = -1;
 
307
                goto out;
 
308
        }
 
309
        if (file_size % pagesize) {
 
310
                file_size -= file_size % pagesize;
 
311
                file_size += pagesize;
 
312
        }
 
313
        data = mmap((caddr_t)0, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
 
314
        if (data == MAP_FAILED) {
 
315
                rc = errno;
 
316
                goto out;
 
317
        }
 
318
        rc = generate_nv_list(head, data);
 
319
        munmap(data, file_size);
 
320
out:
 
321
        return rc;
 
322
}