source: creddy/attr.c @ b19d1f0

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

allocate enough space for the linked role name when creating a linking
role cert

  • Property mode set to 100644
File size: 6.0 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 = creddy_id_dup(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(linked) + 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    libabac_init();
104
105    char *role_encoding = _get_role_encoding(attr);
106
107    // create attribute cert
108    time_t not_before = time(NULL);
109    time_t not_after = not_before + attr->validity * 3600 * 60 * 60;
110    chunk_t serial = creddy_generate_serial();
111
112    certificate_t *attr_cert = lib->creds->create(lib->creds,
113        CRED_CERTIFICATE, CERT_X509_AC,
114        BUILD_CERT, creddy_id_cert(attr->issuer),
115        BUILD_NOT_BEFORE_TIME, not_before,
116        BUILD_NOT_AFTER_TIME, not_after,
117        BUILD_SERIAL, serial,
118        BUILD_IETF_GROUP_ATTR, role_encoding,
119        BUILD_SIGNING_CERT, creddy_id_cert(attr->issuer),
120        BUILD_SIGNING_KEY, creddy_id_privkey(attr->issuer),
121        BUILD_END
122    );
123    if (attr_cert == NULL)
124        return 0;
125
126    attr->cert = attr_cert;
127
128    free(role_encoding);
129    free(serial.ptr);
130    return 1;
131}
132
133int creddy_attribute_cert_chunk(creddy_attribute_t *attr, abac_chunk_t *chunk) {
134    if (attr->cert == NULL)
135        return 0;
136
137    chunk_t encoding = attr->cert->get_encoding(attr->cert);
138    chunk->ptr = encoding.ptr; chunk->len = encoding.len;
139    return 1;
140}
141
142int creddy_attribute_baked(creddy_attribute_t *attr) {
143    return attr->cert != NULL;
144}
145
146// returns 0 if the cert hasn't been baked
147int creddy_attribute_write(creddy_attribute_t *attr, FILE *out) {
148    assert(attr != NULL);
149
150    if (attr->cert == NULL)
151        return 0;
152
153    // write to file
154    chunk_t encoding = attr->cert->get_encoding(attr->cert);
155    fwrite(encoding.ptr, encoding.len, 1, out);
156    free(encoding.ptr);
157
158    return 1;
159}
160
161void creddy_attribute_free(creddy_attribute_t *attr) {
162    int i;
163
164    if (attr == NULL)
165        return;
166
167    creddy_id_free(attr->issuer);
168    free(attr->role);
169    DESTROY_IF(attr->cert);
170
171    // free all the subjects
172    for (i = 0; i < attr->num_subjects; ++i)
173        free(attr->subject[i]);
174    free(attr->subject);
175
176    free(attr);
177}
178
179//
180// Helper functions below
181//
182
183// validate a princpal's name
184// makes sure it's a valid SHA1 identifier
185// return values:
186//  success: malloc'd copy with all hex digits lowercase
187//  fail: NULL
188static char *_validate_principal(char *keyid) {
189    int i;
190    char *copy = NULL;
191
192    if (strlen(keyid) != SHA1_LENGTH)
193        return NULL;
194
195    copy = creddy_xstrdup(keyid);
196    for (i = 0; i < SHA1_LENGTH; ++i) {
197        copy[i] = tolower(copy[i]);
198        if (!isxdigit(copy[i]))
199            goto error;
200    }
201
202    return copy;
203
204error:
205    free(copy);
206    return NULL;
207}
208
209static void _append(creddy_attribute_t *attr, char *subject) {
210    // expand the array if necessary
211    if (attr->num_subjects == attr->size_subjects) {
212        attr->size_subjects *= 2;
213        attr->subject = creddy_xrealloc(attr->subject, attr->size_subjects * sizeof(creddy_attribute_t));
214    }
215
216    attr->subject[attr->num_subjects++] = subject;
217    attr->total_len += strlen(subject);
218}
219
220char *_get_role_encoding(creddy_attribute_t *attr) {
221    int i, num_subjects;
222
223    num_subjects = attr->num_subjects;
224
225    int len = SHA1_LENGTH + 1 + strlen(attr->role) + strlen(ROLE_SEPARATOR);
226    len += attr->total_len + num_subjects * strlen(INTERSECTION_SEP);
227
228    char *encoding = creddy_xmalloc(len);
229    sprintf(encoding, "%s.%s" ROLE_SEPARATOR, creddy_id_keyid(attr->issuer), attr->role);
230
231    for (i = 0; i < num_subjects; ++i) {
232        strcat(encoding, attr->subject[i]);
233        if (i < num_subjects - 1)
234            strcat(encoding, INTERSECTION_SEP);
235    }
236
237    return encoding;
238}
Note: See TracBrowser for help on using the repository browser.