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
RevLine 
[461541a]1
2/* creddy.c */
3
[abd7c25]4#include <assert.h>
[00d21a1]5#include <errno.h>
[abd7c25]6#include <getopt.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
[461541a]10#include <ctype.h>
11#include <err.h>
[abd7c25]12
[04f5da1]13#include "creddy_common.h"
[756011e]14#include "libabac_common.h"
15#include "abac.h"
16#include "abac_list.h"
17#include "abac_verifier.h"
[9ac7fb4]18
[abd7c25]19#define OPT_CN              1
20#define OPT_VALIDITY        2
[fd0febd]21#define OPT_CERT            3
[085f159]22#define OPT_ISSUER          4
23#define OPT_KEY             5
24#define OPT_ROLE            6
[ee5afdd]25#define OPT_SUBJECT_CERT    7
[085f159]26#define OPT_SUBJECT_ROLE    8
27#define OPT_OUT             9 // the world oughta be opt-in only :(
[784a398]28#define OPT_ATTRCERT        10
[ee5afdd]29#define OPT_SUBJECT_ID      11
[0aaa651]30#define OPT_SHOW            12
[461541a]31#define OPT_ATTRRULE        13
[abd7c25]32
[980a7b6]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
[abd7c25]68int main(int argc, char **argv) {
69    options_t options = { 0, };
[00d21a1]70    char *validity_str = NULL;
[abd7c25]71
[461541a]72    libabac_init();
73
[980a7b6]74    subjects = xmalloc(sizeof(subject_t) * 2);
75    subjects_size = 2;
76
77    roles = xmalloc(sizeof(char *) * 2);
78    roles_size = 2;
79
[abd7c25]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 },
[19be896]87        { "version",    0, &options.mode, MODE_VERSION },
[0aaa651]88        { "display",    0, &options.mode, MODE_DISPLAY },
[abd7c25]89
[fd0febd]90        { "cert",       1, 0, OPT_CERT },
91
[abd7c25]92        // generate options
93        { "cn",         1, 0, OPT_CN },
94        { "validity",   1, 0, OPT_VALIDITY },
95
[085f159]96        // attribute options
97        { "issuer",     1, 0, OPT_ISSUER },
98        { "key",        1, 0, OPT_KEY },
99        { "role",       1, 0, OPT_ROLE },
[ee5afdd]100        { "subject-cert", 1, 0, OPT_SUBJECT_CERT },
101        { "subject-id", 1, 0, OPT_SUBJECT_ID },
[ec06cb6]102        { "subject-role", 1, 0, OPT_SUBJECT_ROLE },
[085f159]103        { "out",          1, 0, OPT_OUT },
104
[461541a]105        // attribute_rule option
106        { "attrrule",   1, 0, OPT_ATTRRULE },
107
[784a398]108        // verify option
109        { "attrcert",   1, 0, OPT_ATTRCERT },
110
[0aaa651]111        // display options
112        { "show",       1, 0, OPT_SHOW },
113
[abd7c25]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
[fd0febd]127            case OPT_CERT:
128                options.cert = xstrdup(optarg);
129                break;
130
[abd7c25]131            // generate options
132            case OPT_CN:
133                options.cn = xstrdup(optarg);
134                break;
[085f159]135            case OPT_VALIDITY: // also an attribute option
[00d21a1]136                validity_str = xstrdup(optarg);
[abd7c25]137                break;
138
[085f159]139            // attribute options
140            case OPT_ISSUER:
141                options.issuer = xstrdup(optarg);
142                break;
[9e063cb]143            case OPT_KEY: // also an generate option
[085f159]144                options.key = xstrdup(optarg);
145                break;
146            case OPT_ROLE:
147                options.role = xstrdup(optarg);
148                break;
[ee5afdd]149            case OPT_SUBJECT_CERT:
[980a7b6]150                subject(xstrdup(optarg), 1);
[ee5afdd]151                break;
152            case OPT_SUBJECT_ID:
[980a7b6]153                subject(xstrdup(optarg), 0);
[085f159]154                break;
155            case OPT_SUBJECT_ROLE:
[980a7b6]156                role(xstrdup(optarg));
[085f159]157                break;
158            case OPT_OUT:
159                options.out = xstrdup(optarg);
160                break;
161
[461541a]162            // attribute rule options
163            case OPT_ATTRRULE:
164                options.attrrule = xstrdup(optarg);
165                break;
166
[784a398]167            // verify options
168            case OPT_ATTRCERT:
169                options.attrcert = xstrdup(optarg);
170                break;
171
[0aaa651]172            // display options
173            case OPT_SHOW:
174                options.show = xstrdup(optarg);
175                break;
176
[abd7c25]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
[00d21a1]192    // parse the validity
193    if (validity_str != NULL) {
194        char suffix = 'd'; // default suffix is days
[756011e]195        int multiplier = 1;
[00d21a1]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
[461541a]246    if (options.mode == MODE_ATTRIBUTE && options.attrrule == NULL) {
[980a7b6]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
[9410b51]270    // launch the sub command
[abd7c25]271    switch (options.mode) {
272        case MODE_GENERATE:
[00d21a1]273            if (options.validity == 0) options.validity = 1080 * 86400;
[abd7c25]274            generate_main(&options);
275            break;
276
[fd0febd]277        case MODE_KEYID:
278            keyid_main(&options);
279            break;
280
[085f159]281        case MODE_ATTRIBUTE:
[00d21a1]282            if (options.validity == 0) options.validity = 365 * 86400;
[461541a]283            if(options.attrrule)
284                attribute_rule_main(&options);
285                else attribute_main(&options);
[085f159]286            break;
287
[9410b51]288        case MODE_ROLES:
289            roles_main(&options);
290            break;
291
[784a398]292        case MODE_VERIFY:
293            verify_main(&options);
294            break;
295
[0aaa651]296        case MODE_DISPLAY:
297            display_main(&options);
[adc86c3]298            break;
299
[19be896]300        case MODE_VERSION:
301            printf("ABAC/creddy " ABAC_VERSION "\n");
302            break;
303
[abd7c25]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(
[00d21a1]314            "Usage: creddy --generate --cn <name> [ --validity <time> ] [ --out <dir> ]\n"
[f1e892e]315            "    cert will be in ${name}_ID.der, private key in ${name}_private.pem\n"
[8231b92]316            "    files output to dir if specified\n"
[abd7c25]317            "    default validity: 1080 days\n"
[00d21a1]318            "\n"
319            "    time is specified with optional suffix: s m h d y\n"
320            "    defaults to days if unspecified\n"
[abd7c25]321        );
322
323    else if (opts->mode == MODE_VERIFY)
324        printf(
[91659cb]325            "Usage: creddy --verify --cert <cert> [ --attrcert <cert> ]\n"
[abd7c25]326            "    if attrcert is provided, verify that it was issued by cert\n"
327        );
328
329    else if (opts->mode == MODE_KEYID)
330        printf(
[91659cb]331            "Usage: creddy --keyid --cert <cert>\n"
[abd7c25]332        );
333
334    else if (opts->mode == MODE_ATTRIBUTE)
335        printf(
[91659cb]336            "Usage: creddy --attribute \\\n"
[abd7c25]337            "                --issuer <cert> --key <key> --role <role> \\\n"
[980a7b6]338            "                [ --subject-cert <cert> | --subject-id <sha1> \\\n"
339            "                    [ --subject-role <role> ]  ... ] \\\n"
[00d21a1]340            "                [ --validity <time> ] --out <file>\n"
[abd7c25]341            "    default validity: 365 days\n"
[ee5afdd]342            "    provide exactly one of --subject-cert / --subject-id\n"
[980a7b6]343            "    give multiple --subject-{cert,id} / --subject-role pairs for intersection\n"
[00d21a1]344            "\n"
345            "    time is specified with optional suffix: s m h d y\n"
346            "    defaults to days if unspecified\n"
[abd7c25]347        );
348
349    else if (opts->mode == MODE_ROLES)
350        printf(
[91659cb]351            "Usage: creddy --roles --cert <cert>\n"
[abd7c25]352        );
353
[0aaa651]354    else if (opts->mode == MODE_DISPLAY)
[adc86c3]355        printf(
[405bba3]356            "Usage: creddy --display --show=[issuer,..,all] --cert <cert>\n"
[0aaa651]357            "   values for --show are comma-separated:\n"
358            "       issuer      DN of issuer\n"
[b19d1f0]359            "       subject     DN of subject\n"
[405bba3]360            "       validity    validity period\n"
[08e7235]361            "       roles       attribute cert roles (fails silently on ID certs)\n"
[0aaa651]362            "       all         all of the above\n"
[adc86c3]363            "   cert may be X.509 identity or attribute cert\n"
364        );
365
[abd7c25]366    else
367        printf(
[66462c5]368            "Usage: creddy [ --<mode> ] [ --help ]\n"
[abd7c25]369            "    --generate:  generate X.509 identity cert and private key\n"
[4721618]370            "    --verify:    check validity of X.509 ID or XML attribute cert\n"
[abd7c25]371            "    --keyid:     get fingerprint from X.509 ID cert\n"
[4721618]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"
[19be896]375            "    --version:   display ABAC version\n"
[abd7c25]376        );
377
378
379    exit(1);
380}
381
382void *xmalloc(size_t len) {
383    void *ret = malloc(len);
384    if (ret == NULL)
[1bf0f03]385        err(1, "couldn't malloc %zu bytes\n", len);
[abd7c25]386    return ret;
387}
388
[980a7b6]389void *xrealloc(void *ptr, size_t size) {
390    void *ret = realloc(ptr, size);
391    if (ret == NULL)
[1bf0f03]392        err(1, "couldn't realloc %zu bytes\n", size);
[980a7b6]393    return ret;
394}
395
[abd7c25]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.