source: creddy/creddy.c @ aa33ad9

abac0-leakabac0-meicompt_changesgec13mei-idmei-rt0-nmei_rt0mei_rt2mei_rt2_fix_1meiyap-rt1meiyap1rt2tvf-new-xml
Last change on this file since aa33ad9 was 39fed7c, checked in by Mike Ryan <mikeryan@…>, 14 years ago

generate ID moved into creddy_id

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