source: creddy/attr.c @ 04f5da1

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

extract -lcreddy

  • Property mode set to 100644
File size: 5.6 KB
Line 
1#include <assert.h>
2#include <ctype.h>
3#include <string.h>
4#include <time.h>
5
6#include "libcreddy_common.h"
7
8#define ROLE_SEPARATOR " <- "
9#define INTERSECTION_SEP " & "
10#define SHA1_LENGTH 40
11
12struct _creddy_attribute_t {
13    creddy_id_t *issuer;
14    char *role;
15    int validity;
16
17    char **subject;
18    int num_subjects;
19    int size_subjects;
20    int total_len; // total length of all subject strings
21
22    certificate_t *cert; // NULL until baked
23};
24
25static char *_validate_principal(char *keyid);
26static void _append(creddy_attribute_t *attr, char *subject);
27char *_get_role_encoding(creddy_attribute_t *attr);
28
29int creddy_attribute_create(creddy_attribute_t **ret, creddy_id_t *issuer, char *role, int validity) {
30    if (creddy_id_privkey(issuer) == NULL)
31        return CREDDY_ATTRIBUTE_ISSUER_NOKEY;
32    if (!creddy_clean_name(role))
33        return CREDDY_ATTRIBUTE_INVALID_ROLE;
34    if (validity < 0)
35        return CREDDY_ATTRIBUTE_INVALID_VALIDITY;
36
37    creddy_attribute_t *attr = creddy_xmalloc(sizeof(creddy_attribute_t));
38    attr->issuer = issuer;
39    attr->role = creddy_xstrdup(role);
40    attr->validity = validity;
41
42    attr->num_subjects = 0;
43    attr->size_subjects = 4;
44    attr->subject = creddy_xmalloc(sizeof(char *) * attr->size_subjects);
45    attr->total_len = 0;
46
47    // NULL until baked
48    attr->cert = NULL;
49
50    *ret = attr;
51    return CREDDY_SUCCESS;
52}
53
54int creddy_attribute_principal(creddy_attribute_t *attr, char *keyid) {
55    char *copy = _validate_principal(keyid);
56    if (copy == NULL)
57        return 0;
58
59    _append(attr, copy);
60    return 1;
61}
62
63int creddy_attribute_role(creddy_attribute_t *attr, char *keyid, char *role) {
64    if (!creddy_clean_name(role))
65        return 0;
66
67    char *copy = _validate_principal(keyid);
68    if (copy == NULL)
69        return 0;
70
71    int len = strlen(copy) + strlen(role) + strlen(ROLE_SEPARATOR) + 1;
72    copy = creddy_xrealloc(copy, len);
73    strcat(copy, ".");
74    strcat(copy, role);
75
76    _append(attr, copy);
77    return 1;
78}
79
80int creddy_attribute_linking_role(creddy_attribute_t *attr, char *keyid, char *role, char *linked) {
81    if (!creddy_clean_name(role) || !creddy_clean_name(linked))
82        return 0;
83
84    char *copy = _validate_principal(keyid);
85    if (copy == NULL)
86        return 0;
87
88    int len = strlen(copy) + strlen(role) + strlen(ROLE_SEPARATOR) + 2;
89    copy = creddy_xrealloc(copy, len);
90    strcat(copy, ".");
91    strcat(copy, role);
92    strcat(copy, ".");
93    strcat(copy, linked);
94
95    _append(attr, copy);
96    return 1;
97}
98
99int creddy_attribute_bake(creddy_attribute_t *attr) {
100    if (attr->num_subjects == 0)
101        return 0;
102
103    char *role_encoding = _get_role_encoding(attr);
104
105    // create attribute cert
106    time_t not_before = time(NULL);
107    time_t not_after = not_before + attr->validity * 3600 * 60 * 60;
108    chunk_t serial = creddy_generate_serial();
109
110    certificate_t *attr_cert = lib->creds->create(lib->creds,
111        CRED_CERTIFICATE, CERT_X509_AC,
112        BUILD_CERT, creddy_id_cert(attr->issuer),
113        BUILD_NOT_BEFORE_TIME, not_before,
114        BUILD_NOT_AFTER_TIME, not_after,
115        BUILD_SERIAL, serial,
116        BUILD_IETF_GROUP_ATTR, role_encoding,
117        BUILD_SIGNING_CERT, creddy_id_cert(attr->issuer),
118        BUILD_SIGNING_KEY, creddy_id_privkey(attr->issuer),
119        BUILD_END
120    );
121    if (attr_cert == NULL)
122        return 0;
123
124    attr->cert = attr_cert;
125
126    free(role_encoding);
127    free(serial.ptr);
128    return 1;
129}
130
131// returns 1 if the cert hasn't been baked
132int creddy_attribute_write(creddy_attribute_t *attr, FILE *out) {
133    assert(attr != NULL);
134
135    if (attr->cert == NULL)
136        return 0;
137
138    // write to file
139    chunk_t encoding = attr->cert->get_encoding(attr->cert);
140    fwrite(encoding.ptr, encoding.len, 1, out);
141    free(encoding.ptr);
142
143    return 1;
144}
145
146void creddy_attribute_free(creddy_attribute_t *attr) {
147    int i;
148
149    if (attr == NULL)
150        return;
151
152    creddy_id_free(attr->issuer);
153    free(attr->role);
154    DESTROY_IF(attr->cert);
155
156    // free all the subjects
157    for (i = 0; i < attr->num_subjects; ++i)
158        free(attr->subject[i]);
159    free(attr->subject);
160
161    free(attr);
162}
163
164//
165// Helper functions below
166//
167
168// validate a princpal's name
169// makes sure it's a valid SHA1 identifier
170// return values:
171//  success: malloc'd copy with all hex digits lowercase
172//  fail: NULL
173static char *_validate_principal(char *keyid) {
174    int i;
175    char *copy = NULL;
176
177    if (strlen(keyid) != SHA1_LENGTH)
178        return NULL;
179
180    copy = creddy_xstrdup(keyid);
181    for (i = 0; i < SHA1_LENGTH; ++i) {
182        copy[i] = tolower(copy[i]);
183        if (!isxdigit(copy[i]))
184            goto error;
185    }
186
187    return copy;
188
189error:
190    free(copy);
191    return NULL;
192}
193
194static void _append(creddy_attribute_t *attr, char *subject) {
195    // expand the array if necessary
196    if (attr->num_subjects == attr->size_subjects) {
197        attr->size_subjects *= 2;
198        attr->subject = creddy_xrealloc(attr->subject, attr->size_subjects * sizeof(creddy_attribute_t));
199    }
200
201    attr->subject[attr->num_subjects++] = subject;
202    attr->total_len += strlen(subject);
203}
204
205char *_get_role_encoding(creddy_attribute_t *attr) {
206    int i, num_subjects;
207
208    num_subjects = attr->num_subjects;
209
210    int len = SHA1_LENGTH + 1 + strlen(attr->role) + strlen(ROLE_SEPARATOR);
211    len += attr->total_len + num_subjects * strlen(INTERSECTION_SEP);
212
213    char *encoding = creddy_xmalloc(len);
214    sprintf(encoding, "%s.%s" ROLE_SEPARATOR, creddy_id_keyid(attr->issuer), attr->role);
215
216    for (i = 0; i < num_subjects; ++i) {
217        strcat(encoding, attr->subject[i]);
218        if (i < num_subjects - 1)
219            strcat(encoding, INTERSECTION_SEP);
220    }
221
222    return encoding;
223}
Note: See TracBrowser for help on using the repository browser.