source: creddy/attribute.c @ 002b25a

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

first cut at creddy_id object, integrated into attribute

  • Property mode set to 100644
File size: 4.8 KB
Line 
1#define GNU_SOURCE
2#include <credentials/keys/private_key.h>
3
4#include "creddy.h"
5#include "id.h"
6
7#include <termios.h>
8
9#define ROLE_SEPARATOR " <- "
10#define INTERSECTION_SEP " & "
11#define SHA1_LENGTH 40
12
13void attribute_main(options_t *opts) {
14    int i, ret, role_len = 1;
15
16    if (
17        opts->issuer == NULL ||
18        opts->key == NULL ||
19        opts->role == NULL ||
20        opts->out == NULL
21    )
22        usage(opts);
23
24    if (!clean_name(opts->role)) {
25        printf("bad role name %s\n", opts->role);
26        usage(opts);
27    }
28
29    role_len += SHA1_LENGTH + 1 + strlen(opts->role);
30    role_len += strlen(ROLE_SEPARATOR);
31
32    for (i = 0; i < opts->num_subjects; ++i) {
33        subject_t *cur = &opts->subjects[i];
34
35        // if we have an ID, make sure it's SHA1 and lowercase
36        if (cur->id) {
37            int j;
38            char *subject_id = cur->id;
39
40            // hex chars (also convert to lowercase)
41            for (j = 0; subject_id[j]; ++j) {
42                subject_id[j] = tolower(subject_id[j]);
43                if (!isxdigit(subject_id[j])) {
44                    printf("Invalid subject ID %s: must be SHA1\n", subject_id);
45                    usage(opts);
46                }
47            }
48
49            // correct length
50            if (j != SHA1_LENGTH) {
51                printf("Invalid subject ID %s: must be SHA1 (wrong length)\n", subject_id);
52                usage(opts);
53            }
54        }
55
56        // otherwise we have a cert
57        else {
58            creddy_id_t *subject = creddy_id_from_file(cur->cert);
59            if (subject == NULL)
60                errx(1, "Can't load subject cert from %s", cur->cert);
61            cur->id = xstrdup(creddy_id_keyid(subject));
62            creddy_id_free(subject);
63        }
64
65        role_len += SHA1_LENGTH;
66
67        // verify the subject role name if present
68        if (cur->role) {
69            char *role = cur->role;
70            char *start[3];
71            int name_parts = 0, j;
72
73            start[name_parts++] = role;
74
75            for (j = 0; role[j] != '\0'; ++j)
76                if (role[j] == '.') {
77                    if (name_parts == 3) {
78                        printf("bad subject role name (too many dots)\n");
79                        usage(opts);
80                    }
81                    start[name_parts++] = &role[j+1];
82                    role[j] = 0;
83                }
84
85            for (j = 0; j < name_parts; ++j)
86                if (!clean_name(start[j])) {
87                    printf("bad subject role name\n");
88                    usage(opts);
89                }
90
91            for (j = 1; j < name_parts; ++j)
92                *(start[j]-1) = '.'; // replace the dot
93
94            role_len += strlen(cur->role) + 1;
95        }
96
97        role_len += sizeof(INTERSECTION_SEP) - 1;
98    }
99
100    if (opts->validity < 0) {
101        printf("Validity must be >= 1 day\n");
102        usage(opts);
103    }
104
105    // issuer
106    creddy_id_t *issuer = creddy_id_from_file(opts->issuer);
107    if (issuer == NULL)
108        errx(1, "Can't load cert from %s", opts->issuer);
109
110    // private key
111    ret = creddy_id_load_privkey(issuer, opts->key);
112    if (!ret)
113        errx(1, "Can't load private key from %s", opts->key);
114
115    // get the keyids
116    char *issuer_id = creddy_id_keyid(issuer);
117
118    // build the role encoding
119    char *role_encoding = xmalloc(role_len);
120    role_encoding[0] = '\0';
121
122    // role
123    sprintf(role_encoding, "%s.%s" ROLE_SEPARATOR, issuer_id, opts->role);
124
125    // subject(s)
126    for (i = 0; i < opts->num_subjects; ++i) {
127        subject_t *cur = &opts->subjects[i];
128
129        strcat(role_encoding, cur->id);
130        if (cur->role) {
131            strcat(role_encoding, ".");
132            strcat(role_encoding, cur->role);
133        }
134
135        if (i < opts->num_subjects - 1)
136            strcat(role_encoding, INTERSECTION_SEP);
137    }
138
139    // create attribute cert
140    time_t not_before = time(NULL);
141    time_t not_after = not_before + opts->validity * 3600 * 60 * 60;
142    chunk_t serial = generate_serial();
143
144    certificate_t *attr_cert = lib->creds->create(lib->creds,
145        CRED_CERTIFICATE, CERT_X509_AC,
146        BUILD_CERT, creddy_id_cert(issuer),
147        BUILD_NOT_BEFORE_TIME, not_before,
148        BUILD_NOT_AFTER_TIME, not_after,
149        BUILD_SERIAL, serial,
150        BUILD_IETF_GROUP_ATTR, role_encoding,
151        BUILD_SIGNING_CERT, creddy_id_cert(issuer),
152        BUILD_SIGNING_KEY, creddy_id_privkey(issuer),
153        BUILD_END
154    );
155    if (attr_cert == NULL)
156        errx(1, "Couldn't build attribute cert");
157
158    // write to file
159    chunk_t encoding = attr_cert->get_encoding(attr_cert);
160
161    FILE *out = fopen(opts->out, "w");
162    if (out == NULL)
163        err(1, "Can't open attribute cert output file %s", opts->out);
164    fwrite(encoding.ptr, encoding.len, 1, out);
165    fclose(out);
166
167    free(role_encoding);
168    free(serial.ptr);
169    DESTROY_IF(attr_cert);
170    free(encoding.ptr);
171    creddy_id_free(issuer);
172}
Note: See TracBrowser for help on using the repository browser.