source: creddy/creddy.c @ f89b991

mei_rt2
Last change on this file since f89b991 was 2e9455f, checked in by Mei <mei@…>, 11 years ago

1) added namespace
2) tweak ?This,
3) allowing linking role/oset as constraining conditions
4) adding access_tests regression testing that uses GENI's access policy
5) added couple multi contexts regression tests
6) add compression/uncompression calls to abac_encode_string/abac_decode_string
(libstrongwan only allows 512 char for attribute rule storage)
7) add attribute_now option to creddy that takes a whole char string for attribute
rule

  • Property mode set to 100644
File size: 16.2 KB
Line 
1/***
2   creddy.c
3   main engine for creddy
4***/
5
6#include <assert.h>
7#include <errno.h>
8#ifdef __APPLE__
9#define link LINK_IGNORED
10#include <getopt.h>
11#undef link
12#else
13#include <getopt.h>
14#endif
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include "creddy.h"
20
21#define OPT_CN              1
22#define OPT_VALIDITY        2
23#define OPT_CERT            3
24#define OPT_ISSUER          4
25#define OPT_KEY             5
26#define OPT_ROLE            6
27#define OPT_SUBJECT_CERT    7
28#define OPT_SUBJECT_ROLE    8
29#define OPT_OUT             9 // the world oughta be opt-in only :(
30#define OPT_ATTRCERT        10
31#define OPT_SUBJECT_ID      11
32#define OPT_SHOW            12
33#define OPT_OSET            13
34#define OPT_SUBJECT_OSET    14
35#define OPT_SUBJECT_OBJ     15
36#define OPT_SUBJECT_LINK    16
37#define OPT_KEYSTORE        17
38#define OPT_PASSPHRASE      18
39#define OPT_STRING          19
40#define OPT_OUT_PROLOG      20
41#define OPT_NAMESPACE       21
42
43subject_t *subjects = NULL;
44int num_subjects = 0;
45int subjects_size = 0;
46
47char **subj_items = NULL;
48ENUM_CRED_TYPE *subj_items_type = NULL;
49int num_subj_items = 0;
50int subj_items_size = 0;
51
52void *xmalloc(size_t);
53
54void subject(char *subject, ENUM_SUBJ_TYPE type) {
55    if (num_subjects == subjects_size) {
56        subjects_size *= 2;
57        subjects = xrealloc(subjects, sizeof(subject_t) * subjects_size);
58    }
59
60    int i = num_subjects++;
61    subjects[i].id = NULL;
62    subjects[i].cert = NULL;
63    subjects[i].obj = NULL;
64    subjects[i].link = NULL;
65
66    subjects[i].cred_type = e_cred_none; // default
67    subjects[i].role = NULL;
68
69    subjects[i].subj_type = type;
70    switch (type) {
71      case e_subj_cert:
72        subjects[i].cert = subject;
73        break;
74      case e_subj_id:
75        subjects[i].id = subject;
76        break;
77      case e_subj_obj:
78        subjects[i].obj = subject;
79        break;
80    }
81}
82
83void subj_item(char *item, ENUM_CRED_TYPE type) {
84    if (num_subj_items == subj_items_size) {
85        subj_items_size *= 2;
86        subj_items = xrealloc(subj_items, sizeof(char *) * subj_items_size);
87        subj_items_type = xrealloc(subj_items_type, 
88                                  sizeof(ENUM_CRED_TYPE) * subj_items_size);
89    }
90
91    int i = num_subj_items++;
92    subj_items[i] = item;
93    subj_items_type[i] = type;
94}
95
96void link(char *role) {
97    /* use the last subject, should be cred type */
98    int i = num_subjects-1;
99    subjects[i].link = role;
100}
101void role(char *role) {
102    subj_item(role, e_cred_role);
103}
104
105void oset(char *oset) {
106    subj_item(oset, e_cred_oset);
107}
108
109int main(int argc, char **argv) {
110
111    libabac_init();
112    int ret;
113    options_t options = { 0, };
114    char *validity_str = NULL;
115
116    subjects = (subject_t *) xmalloc(sizeof(subject_t) * 2);
117    subjects_size = 2;
118
119    subj_items = (char **) xmalloc(sizeof(char *) * 2);
120    subj_items_type = (ENUM_CRED_TYPE *) xmalloc(sizeof(ENUM_CRED_TYPE) * 2);
121    subj_items_size = 2;
122
123    struct option getopts[] = {
124        { "help",       0, &options.help, 1 },
125        { "generate",   0, &options.mode, MODE_GENERATE },
126        { "verify",     0, &options.mode, MODE_VERIFY },
127        { "keyid",      0, &options.mode, MODE_KEYID },
128        { "attribute",  0, &options.mode, MODE_ATTRIBUTE },
129        { "attrnow",    0, &options.mode, MODE_ATTRIBUTE_NOW },
130        { "roles",      0, &options.mode, MODE_ROLES },
131        { "osets",      0, &options.mode, MODE_OSETS },
132        { "version",    0, &options.mode, MODE_VERSION },
133        { "display",    0, &options.mode, MODE_DISPLAY },
134        { "keycheck",   0, &options.mode, MODE_KEYCHECK },
135
136        { "cert",       1, 0, OPT_CERT },
137        { "p",          2, 0, OPT_PASSPHRASE },
138
139        // generate options
140        { "cn",         1, 0, OPT_CN },
141        { "validity",   1, 0, OPT_VALIDITY },
142
143        // attribute options
144        { "issuer",     1, 0, OPT_ISSUER },
145        { "key",        1, 0, OPT_KEY },
146        { "role",       1, 0, OPT_ROLE },
147        { "oset",       1, 0, OPT_OSET },
148        { "subject-cert", 1, 0, OPT_SUBJECT_CERT },
149        { "subject-id",   1, 0, OPT_SUBJECT_ID },
150        { "subject-role", 1, 0, OPT_SUBJECT_ROLE },
151        { "subject-oset", 1, 0, OPT_SUBJECT_OSET },
152        { "subject-obj",  1, 0, OPT_SUBJECT_OBJ },
153        { "subject-link", 1, 0, OPT_SUBJECT_LINK },
154        { "keystore",     1, 0, OPT_KEYSTORE },
155        { "out",          1, 0, OPT_OUT },
156        // attrnow options
157        { "out_prolog",   1, 0, OPT_OUT_PROLOG },
158        { "string",       1, 0, OPT_STRING },
159        { "namespace",    1, 0, OPT_NAMESPACE },
160
161        // verify option
162        { "attrcert",   1, 0, OPT_ATTRCERT },
163
164        // display options
165        { "show",       1, 0, OPT_SHOW },
166
167        { NULL },
168    };
169
170    options.passphrase=0;
171    for ( ; ; ) {
172        int c = getopt_long(argc, argv, "", getopts, NULL);
173        if (c < 0)
174            break;
175
176        switch (c) {
177            // set the option from the value in the getopts struct
178            case 0:
179                continue;
180
181            case OPT_CERT:
182                options.cert = xstrdup(optarg);
183                break;
184
185            // for keycheck and for generate and attribute
186            case OPT_PASSPHRASE:
187                options.passphrase=1;
188                options.pfile=NULL;
189                if(optarg)
190                    options.pfile=xstrdup(optarg);
191                break;
192
193            // generate options
194            case OPT_CN:
195                options.cn = xstrdup(optarg);
196                break;
197            case OPT_VALIDITY: // also an attribute option
198                validity_str = xstrdup(optarg);
199                break;
200
201            // attribute options
202            case OPT_ISSUER:
203                options.issuer = xstrdup(optarg);
204                break;
205            // for keycheck and for generate
206            case OPT_KEY:
207                options.key = xstrdup(optarg);
208                break;
209            case OPT_ROLE:
210                options.role = xstrdup(optarg);
211                options.cred_type = e_cred_role;
212                break;
213            case OPT_OSET:
214                options.oset = xstrdup(optarg);
215                options.cred_type = e_cred_oset;
216                break;
217            case OPT_SUBJECT_CERT:
218                subject(xstrdup(optarg), e_subj_cert);
219                break;
220            case OPT_SUBJECT_ID:
221                subject(xstrdup(optarg), e_subj_id);
222                break;
223            case OPT_SUBJECT_OBJ:
224                subject(xstrdup(optarg), e_subj_obj);
225                break;
226            case OPT_SUBJECT_LINK:
227                link(xstrdup(optarg));
228                break;
229            case OPT_SUBJECT_ROLE:
230                role(xstrdup(optarg));
231                break;
232            case OPT_SUBJECT_OSET:
233                oset(xstrdup(optarg));
234                break;
235            case OPT_KEYSTORE:
236                options.keystore=xstrdup(optarg);
237                break;
238            case OPT_OUT:
239                options.out = xstrdup(optarg);
240                break;
241            case OPT_OUT_PROLOG:
242                options.out_prolog = xstrdup(optarg);
243                break;
244            case OPT_NAMESPACE:
245                options.namespace = xstrdup(optarg);
246                break;
247            case OPT_STRING:
248                options.string = xstrdup(optarg);
249                break;
250
251            // verify options
252            case OPT_ATTRCERT:
253                options.attrcert = xstrdup(optarg);
254                break;
255
256            // display options
257            case OPT_SHOW:
258                options.show = xstrdup(optarg);
259                break;
260
261            case '?':
262                break;
263
264            default:
265                printf("wat\n");
266                return 45;
267        }
268    }
269
270    if (options.help || optind < argc) {
271        if (optind > 0 && optind < argc)
272            printf("I don't understand %s, %d\n", argv[optind], optind);
273        usage(&options);
274    }
275
276    // parse the validity
277    if (validity_str != NULL) {
278        char suffix = 'd'; // default suffix is days
279        int multiplier;
280
281        int len = strlen(validity_str);
282        assert(len > 0);
283
284        // get the suffix char if it's alphabetical
285        if (isalpha(validity_str[len - 1])) {
286            suffix = validity_str[len - 1];
287
288            // truncate
289            validity_str[len - 1] = '\0';
290            --len;
291
292            // make sure it's not only a suffix
293            if (len == 0) {
294                printf("Invalid validity\n");
295                usage(&options);
296            }
297        }
298
299        // convert the suffix to a multiplier
300        switch(suffix) {
301            case 's': multiplier =        1; break;
302            case 'm': multiplier =       60; break;
303            case 'h': multiplier =     3600; break;
304            case 'd': multiplier =    86400; break;
305            case 'y': multiplier = 31536000; break;
306            default:
307                printf("Invalid suffix, must be s m h d y\n");
308                usage(&options);
309        }
310
311        // ascii to int
312        char *end;
313        options.validity = strtol(validity_str, &end, 10);
314        if (errno != 0 || end - validity_str < len) {
315            printf("Invalid validity\n");
316            usage(&options);
317        }
318
319        if (options.validity <= 0) {
320            printf("Invalid validity: must be > 0\n");
321            usage(&options);
322        }
323
324        // multiply!
325        options.validity *= multiplier;
326
327        free(validity_str);
328    }
329
330    if (options.mode == MODE_ATTRIBUTE) {
331        int i;
332        int j;
333
334        // have to do error checking on subjects here
335        if (
336                (num_subjects == 0) ||
337                (num_subjects != (num_subj_items) && num_subjects != 1 
338                                 && (num_subj_items) != 0)
339           ) {
340            printf(
341                "You have %d subject%s and %d role/oset%s, which is mismatched\n",
342                num_subjects, num_subjects == 1 ? "" : "s",
343                (num_subj_items), (num_subj_items) == 1 ? "" : "s"
344            );
345            usage(&options);
346        }
347
348        for (i = 0; i < num_subj_items; ++i) {
349            subjects[i].cred_type=subj_items_type[i];
350            if(subj_items_type[i] == e_cred_role)
351                subjects[i].role = subj_items[i];
352                else subjects[i].oset=subj_items[i];
353        }
354        free(subj_items);
355
356        options.subjects = subjects;
357        options.num_subjects = num_subjects;
358    }
359
360    // launch the sub command
361    switch (options.mode) {
362        case MODE_GENERATE:
363            if (options.validity == 0) options.validity = 1080 * 86400;
364            generate_main(&options);
365            break;
366
367        case MODE_KEYCHECK:
368            keycheck_main(&options);
369            break;
370
371        case MODE_KEYID:
372            keyid_main(&options);
373            break;
374
375        case MODE_ATTRIBUTE:
376            if (options.validity == 0) options.validity = 365 * 86400;
377           attribute_main(&options);
378            break;
379
380        case MODE_ATTRIBUTE_NOW:
381            if (options.validity == 0) options.validity = 365 * 86400;
382           attribute_now_main(&options);
383            break;
384
385        case MODE_ROLES:
386            roles_main(&options);
387            break;
388
389        case MODE_OSETS:
390            osets_main(&options);
391            break;
392
393        case MODE_VERIFY:
394            verify_main(&options);
395            break;
396
397        case MODE_DISPLAY:
398            display_main(&options);
399            break;
400
401        case MODE_VERSION:
402            printf("ABAC/creddy " ABAC_VERSION "\n");
403            break;
404
405        default:
406            usage(&options);
407    }
408
409    return 0;
410}
411
412void usage(options_t *opts) {
413    if (opts->mode == MODE_GENERATE)
414        printf(
415            "Usage: creddy --generate --cn <name> [ --validity <time> ] [ --out <dir> ] [ --key <keyfile> ] [ --p <=pfile> ] \n"
416            "    generated cert will be in ${name}_ID.der, \n"
417            "    a generated private key in ${name}_private.pem \n"
418            "       unless a keyfile is supplied, \n"
419            "    if supplied keyfile is encrypted, \n"
420            "       a passphrase can be ingested through a pfile, \n"
421            "       or it will be prompted for interactively,  \n"
422            "    files output to dir if specified\n"
423            "    default validity: 1080 days\n"
424            "\n"
425            "    time is specified with optional suffix: s m h d y\n"
426            "    defaults to days if unspecified\n"
427        );
428
429    else if (opts->mode == MODE_VERIFY)
430        printf(
431            "Usage: creddy --verify --cert <cert> [ --attrcert <cert> ]\n"
432            "    if attrcert is provided, verify that it was issued by cert\n"
433            "    if attrcert is the same as cert, verify for self-signing cert\n"
434        );
435
436    else if (opts->mode == MODE_KEYID)
437        printf(
438            "Usage: creddy --keyid --cert <cert>\n"
439        );
440
441    else if (opts->mode == MODE_KEYCHECK)
442        printf(
443            "Usage: creddy --keycheck --key <key> --p <=pfile>\n"
444            "   check if the private key is accessible, \n"
445            "   if passphrase is supplied, it is used to decrypt the key\n"
446        );
447
448    else if (opts->mode == MODE_ATTRIBUTE_NOW)
449        printf(
450            "Usage: creddy --attrnow --string <attr> --out <file> --out_prolog <file> --namespace <nm> \n"
451            "   create and save an attribute credential for a namespace nm\n"
452            "   save the yap prolog clauses in a separate file\n"
453        );
454
455    else if (opts->mode == MODE_ATTRIBUTE)
456        printf(
457            "Usage: creddy --attribute \\\n"
458            "                --issuer <cert> --key <key> --p <=pfile>\\\n"
459            "                [ --role <role> | --oset <oset> ] \\\n"
460            "                [ --subject-cert <cert> | --subject-id <sha1> | --subject-obj <object> ] \\\n"
461            "                [ --subject-link <role> | --subject-role <role> | --subject-oset <oset> ]  ... ] \\\n"
462            "                [ --validity <time> ] --out <file>\n"
463            "    default validity: 365 days\n"
464            "    provide exactly one of --subject-cert / --subject-id / --subject-obj\n"
465            "    give multiple --subject-{cert,id} / --subject-{role,obj} pairs for intersection\n"
466            "\n"
467            "    time is specified with optional suffix: s m h d y\n"
468            "    defaults to days if unspecified\n"
469        );
470
471    else if (opts->mode == MODE_ROLES)
472        printf(
473            "Usage: creddy --roles --cert <cert>\n"
474        );
475
476    else if (opts->mode == MODE_OSETS)
477        printf(
478            "Usage: creddy --osets --cert <cert>\n"
479        );
480
481    else if (opts->mode == MODE_DISPLAY)
482        printf(
483            "Usage: creddy --display --show=[issuer,..,all] --cert <cert>\n"
484            "   values for --show are comma-separated:\n"
485            "       issuer      DN of issuer\n"
486            "       subject     DN of subject\n"
487            "       validity    validity period\n"
488            "       roles       attribute cert roles (fails silently on ID certs)\n"
489            "       osets       attribute cert osets (fails silently on ID certs)\n"
490            "       all         all of the above\n"
491            "   cert may be X.509 identity or attribute cert\n"
492        );
493
494    else
495        printf(
496            "Usage: creddy [ --<mode> ] [ --help ]\n"
497            "    --generate:  generate X.509 identity cert and optional private key\n"
498            "    --verify:    check validity of X.509 ID or attribute cert\n"
499            "    --keyid:     get fingerprint from X.509 ID cert\n"
500            "    --attribute: generate an X.509 attribute cert\n"
501            "    --roles:     list roles from an X.509 attribute cert\n"
502            "    --osets:     list osets from an X.509 attribute cert\n"
503            "    --display:   list metadata from an X.509 identity or attribute cert\n"
504            "    --keycheck:  test the private key\n"
505            "    --version:   display ABAC version\n"
506        );
507
508
509    exit(1);
510}
511
512void *xmalloc(size_t len) {
513    void *ret = malloc(len);
514    if (ret == NULL)
515        err(1, "couldn't malloc %d bytes\n", len);
516    return ret;
517}
518
519void *xrealloc(void *ptr, size_t size) {
520    void *ret = realloc(ptr, size);
521    if (ret == NULL)
522        err(1, "couldn't realloc %d bytes\n", size);
523    return ret;
524}
525
526char *xstrdup(char *string) {
527    char *dup = strdup(string);
528    if (dup == NULL)
529        err(1, "Can't dup %s", string);
530    return dup;
531}
Note: See TracBrowser for help on using the repository browser.