source: creddy/creddy.c

Last change on this file was 756011e, checked in by Ted Faber <faber@…>, 11 years ago

Now we pass -Wall with no warnings.

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