source: creddy/creddy.c @ 08bb122

abac0-leakabac0-meicompt_changesgec13mei-idmei-rt0-nmei_rt0tvf-new-xml 0.2.0
Last change on this file since 08bb122 was 00d21a1, checked in by Mike Ryan <mikeryan@…>, 13 years ago

finer granularity over validity periods

API: ID and attr certs take seconds for validity period
command line: validity option takes a suffix for time period

fixes #20

this is an API-breaking change, so a bump to 0.2.0 is necessary

  • Property mode set to 100644
File size: 11.2 KB
Line 
1#include <assert.h>
2#include <errno.h>
3#include <getopt.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8#include "creddy_common.h"
9
10#define OPT_CN              1
11#define OPT_VALIDITY        2
12#define OPT_CERT            3
13#define OPT_ISSUER          4
14#define OPT_KEY             5
15#define OPT_ROLE            6
16#define OPT_SUBJECT_CERT    7
17#define OPT_SUBJECT_ROLE    8
18#define OPT_OUT             9 // the world oughta be opt-in only :(
19#define OPT_ATTRCERT        10
20#define OPT_SUBJECT_ID      11
21#define OPT_SHOW            12
22
23subject_t *subjects = NULL;
24int num_subjects = 0;
25int subjects_size = 0;
26
27char **roles = NULL;
28int num_roles = 0;
29int roles_size = 0;
30
31void subject(char *subject, int cert) {
32    if (num_subjects == subjects_size) {
33        subjects_size *= 2;
34        subjects = xrealloc(subjects, sizeof(subject_t) * subjects_size);
35    }
36
37    int i = num_subjects++;
38    subjects[i].id = NULL;
39    subjects[i].cert = NULL;
40    subjects[i].role = NULL;
41
42    if (cert)
43        subjects[i].cert = subject;
44    else
45        subjects[i].id = subject;
46}
47
48void role(char *role) {
49    if (num_roles == roles_size) {
50        roles_size *= 2;
51        roles = xrealloc(roles, sizeof(char *) * roles_size);
52    }
53
54    int i = num_roles++;
55    roles[i] = role;
56}
57
58int main(int argc, char **argv) {
59    int ret;
60    options_t options = { 0, };
61    char *validity_str = NULL;
62
63    subjects = xmalloc(sizeof(subject_t) * 2);
64    subjects_size = 2;
65
66    roles = xmalloc(sizeof(char *) * 2);
67    roles_size = 2;
68
69    struct option getopts[] = {
70        { "help",       0, &options.help, 1 },
71        { "generate",   0, &options.mode, MODE_GENERATE },
72        { "verify",     0, &options.mode, MODE_VERIFY },
73        { "keyid",      0, &options.mode, MODE_KEYID },
74        { "attribute",  0, &options.mode, MODE_ATTRIBUTE },
75        { "roles",      0, &options.mode, MODE_ROLES },
76        { "version",    0, &options.mode, MODE_VERSION },
77        { "display",    0, &options.mode, MODE_DISPLAY },
78
79        { "cert",       1, 0, OPT_CERT },
80
81        // generate options
82        { "cn",         1, 0, OPT_CN },
83        { "validity",   1, 0, OPT_VALIDITY },
84
85        // attribute options
86        { "issuer",     1, 0, OPT_ISSUER },
87        { "key",        1, 0, OPT_KEY },
88        { "role",       1, 0, OPT_ROLE },
89        { "subject-cert", 1, 0, OPT_SUBJECT_CERT },
90        { "subject-id", 1, 0, OPT_SUBJECT_ID },
91        { "subject-role", 1, 0, OPT_SUBJECT_ROLE },
92        { "out",          1, 0, OPT_OUT },
93
94        // verify option
95        { "attrcert",   1, 0, OPT_ATTRCERT },
96
97        // display options
98        { "show",       1, 0, OPT_SHOW },
99
100        { NULL },
101    };
102
103    for ( ; ; ) {
104        int c = getopt_long(argc, argv, "", getopts, NULL);
105        if (c < 0)
106            break;
107
108        switch (c) {
109            // set the option from the value in the getopts struct
110            case 0:
111                continue;
112
113            case OPT_CERT:
114                options.cert = xstrdup(optarg);
115                break;
116
117            // generate options
118            case OPT_CN:
119                options.cn = xstrdup(optarg);
120                break;
121            case OPT_VALIDITY: // also an attribute option
122                validity_str = xstrdup(optarg);
123                break;
124
125            // attribute options
126            case OPT_ISSUER:
127                options.issuer = xstrdup(optarg);
128                break;
129            case OPT_KEY:
130                options.key = xstrdup(optarg);
131                break;
132            case OPT_ROLE:
133                options.role = xstrdup(optarg);
134                break;
135            case OPT_SUBJECT_CERT:
136                subject(xstrdup(optarg), 1);
137                break;
138            case OPT_SUBJECT_ID:
139                subject(xstrdup(optarg), 0);
140                break;
141            case OPT_SUBJECT_ROLE:
142                role(xstrdup(optarg));
143                break;
144            case OPT_OUT:
145                options.out = xstrdup(optarg);
146                break;
147
148            // verify options
149            case OPT_ATTRCERT:
150                options.attrcert = xstrdup(optarg);
151                break;
152
153            // display options
154            case OPT_SHOW:
155                options.show = xstrdup(optarg);
156                break;
157
158            case '?':
159                break;
160
161            default:
162                printf("wat\n");
163                return 45;
164        }
165    }
166
167    if (options.help || optind < argc) {
168        if (optind > 0 && optind < argc)
169            printf("I don't understand %s\n", argv[optind]);
170        usage(&options);
171    }
172
173    // parse the validity
174    if (validity_str != NULL) {
175        char suffix = 'd'; // default suffix is days
176        int multiplier;
177
178        int len = strlen(validity_str);
179        assert(len > 0);
180
181        // get the suffix char if it's alphabetical
182        if (isalpha(validity_str[len - 1])) {
183            suffix = validity_str[len - 1];
184
185            // truncate
186            validity_str[len - 1] = '\0';
187            --len;
188
189            // make sure it's not only a suffix
190            if (len == 0) {
191                printf("Invalid validity\n");
192                usage(&options);
193            }
194        }
195
196        // convert the suffix to a multiplier
197        switch(suffix) {
198            case 's': multiplier =        1; break;
199            case 'm': multiplier =       60; break;
200            case 'h': multiplier =     3600; break;
201            case 'd': multiplier =    86400; break;
202            case 'y': multiplier = 31536000; break;
203            default:
204                printf("Invalid suffix, must be s m h d y\n");
205                usage(&options);
206        }
207
208        // ascii to int
209        char *end;
210        options.validity = strtol(validity_str, &end, 10);
211        if (errno != 0 || end - validity_str < len) {
212            printf("Invalid validity\n");
213            usage(&options);
214        }
215
216        if (options.validity <= 0) {
217            printf("Invalid validity: must be > 0\n");
218            usage(&options);
219        }
220
221        // multiply!
222        options.validity *= multiplier;
223
224        free(validity_str);
225    }
226
227    if (options.mode == MODE_ATTRIBUTE) {
228        int i;
229
230        // have to do error checking on subjects here
231        if (
232                (num_subjects == 0) ||
233                (num_subjects != num_roles && num_subjects != 1 && num_roles != 0)
234           ) {
235            printf(
236                "You have %d subject%s and %d role%s, which is invalid\n",
237                num_subjects, num_subjects == 1 ? "" : "s",
238                num_roles, num_roles == 1 ? "" : "s"
239            );
240            usage(&options);
241        }
242
243        for (i = 0; i < num_roles; ++i)
244            subjects[i].role = roles[i];
245        free(roles);
246
247        options.subjects = subjects;
248        options.num_subjects = num_subjects;
249    }
250
251    // launch the sub command
252    switch (options.mode) {
253        case MODE_GENERATE:
254            if (options.validity == 0) options.validity = 1080 * 86400;
255            generate_main(&options);
256            break;
257
258        case MODE_KEYID:
259            keyid_main(&options);
260            break;
261
262        case MODE_ATTRIBUTE:
263            if (options.validity == 0) options.validity = 365 * 86400;
264            attribute_main(&options);
265            break;
266
267        case MODE_ROLES:
268            roles_main(&options);
269            break;
270
271        case MODE_VERIFY:
272            verify_main(&options);
273            break;
274
275        case MODE_DISPLAY:
276            display_main(&options);
277            break;
278
279        case MODE_VERSION:
280            printf("ABAC/creddy " ABAC_VERSION "\n");
281            break;
282
283        default:
284            usage(&options);
285    }
286
287    return 0;
288}
289
290void usage(options_t *opts) {
291    if (opts->mode == MODE_GENERATE)
292        printf(
293            "Usage: creddy --generate --cn <name> [ --validity <time> ] [ --out <dir> ]\n"
294            "    cert will be in ${name}_ID.der, private key in ${name}_private.pem\n"
295            "    files output to dir if specified\n"
296            "    default validity: 1080 days\n"
297            "\n"
298            "    time is specified with optional suffix: s m h d y\n"
299            "    defaults to days if unspecified\n"
300        );
301
302    else if (opts->mode == MODE_VERIFY)
303        printf(
304            "Usage: creddy --verify --cert <cert> [ --attrcert <cert> ]\n"
305            "    if attrcert is provided, verify that it was issued by cert\n"
306        );
307
308    else if (opts->mode == MODE_KEYID)
309        printf(
310            "Usage: creddy --keyid --cert <cert>\n"
311        );
312
313    else if (opts->mode == MODE_ATTRIBUTE)
314        printf(
315            "Usage: creddy --attribute \\\n"
316            "                --issuer <cert> --key <key> --role <role> \\\n"
317            "                [ --subject-cert <cert> | --subject-id <sha1> \\\n"
318            "                    [ --subject-role <role> ]  ... ] \\\n"
319            "                [ --validity <time> ] --out <file>\n"
320            "    default validity: 365 days\n"
321            "    provide exactly one of --subject-cert / --subject-id\n"
322            "    give multiple --subject-{cert,id} / --subject-role pairs for intersection\n"
323            "\n"
324            "    time is specified with optional suffix: s m h d y\n"
325            "    defaults to days if unspecified\n"
326        );
327
328    else if (opts->mode == MODE_ROLES)
329        printf(
330            "Usage: creddy --roles --cert <cert>\n"
331        );
332
333    else if (opts->mode == MODE_DISPLAY)
334        printf(
335            "Usage: creddy --display --show=[issuer,..,all] --cert <cert>\n"
336            "   values for --show are comma-separated:\n"
337            "       issuer      DN of issuer\n"
338            "       subject     DN of subject\n"
339            "       validity    validity period\n"
340            "       roles       attribute cert roles (fails silently on ID certs)\n"
341            "       all         all of the above\n"
342            "   cert may be X.509 identity or attribute cert\n"
343        );
344
345    else
346        printf(
347            "Usage: creddy [ --<mode> ] [ --help ]\n"
348            "    --generate:  generate X.509 identity cert and private key\n"
349            "    --verify:    check validity of X.509 ID or attribute cert\n"
350            "    --keyid:     get fingerprint from X.509 ID cert\n"
351            "    --attribute: generate an X.509 attribute cert\n"
352            "    --roles:     list roles from an X.509 attribute cert\n"
353            "    --display:   list metadata from an X.509 identity or attribute cert\n"
354            "    --version:   display ABAC version\n"
355        );
356
357
358    exit(1);
359}
360
361void *xmalloc(size_t len) {
362    void *ret = malloc(len);
363    if (ret == NULL)
364        err(1, "couldn't malloc %d bytes\n", len);
365    return ret;
366}
367
368void *xrealloc(void *ptr, size_t size) {
369    void *ret = realloc(ptr, size);
370    if (ret == NULL)
371        err(1, "couldn't realloc %d bytes\n", size);
372    return ret;
373}
374
375char *xstrdup(char *string) {
376    char *dup = strdup(string);
377    if (dup == NULL)
378        err(1, "Can't dup %s", string);
379    return dup;
380}
381
382certificate_t *attr_cert_from_file(char *filename) {
383    libabac_init();
384    certificate_t *cert = lib->creds->create(lib->creds,
385        CRED_CERTIFICATE, CERT_X509_AC,
386        BUILD_FROM_FILE, filename,
387        BUILD_END
388    );
389    if (cert == NULL)
390        errx(1, "Couldn't load attribute cert %s", filename);
391
392    return cert;
393}
Note: See TracBrowser for help on using the repository browser.