source: creddy/attr.c @ e02c742

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

method to explicitly test if the cert's been baked

  • Property mode set to 100644
File size: 5.7 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    creddy_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_baked(creddy_attribute_t *attr) {
134    return attr->cert != NULL;
135}
136
137// returns 0 if the cert hasn't been baked
138int creddy_attribute_write(creddy_attribute_t *attr, FILE *out) {
139    assert(attr != NULL);
140
141    if (attr->cert == NULL)
142        return 0;
143
144    // write to file
145    chunk_t encoding = attr->cert->get_encoding(attr->cert);
146    fwrite(encoding.ptr, encoding.len, 1, out);
147    free(encoding.ptr);
148
149    return 1;
150}
151
152void creddy_attribute_free(creddy_attribute_t *attr) {
153    int i;
154
155    if (attr == NULL)
156        return;
157
158    creddy_id_free(attr->issuer);
159    free(attr->role);
160    DESTROY_IF(attr->cert);
161
162    // free all the subjects
163    for (i = 0; i < attr->num_subjects; ++i)
164        free(attr->subject[i]);
165    free(attr->subject);
166
167    free(attr);
168}
169
170//
171// Helper functions below
172//
173
174// validate a princpal's name
175// makes sure it's a valid SHA1 identifier
176// return values:
177//  success: malloc'd copy with all hex digits lowercase
178//  fail: NULL
179static char *_validate_principal(char *keyid) {
180    int i;
181    char *copy = NULL;
182
183    if (strlen(keyid) != SHA1_LENGTH)
184        return NULL;
185
186    copy = creddy_xstrdup(keyid);
187    for (i = 0; i < SHA1_LENGTH; ++i) {
188        copy[i] = tolower(copy[i]);
189        if (!isxdigit(copy[i]))
190            goto error;
191    }
192
193    return copy;
194
195error:
196    free(copy);
197    return NULL;
198}
199
200static void _append(creddy_attribute_t *attr, char *subject) {
201    // expand the array if necessary
202    if (attr->num_subjects == attr->size_subjects) {
203        attr->size_subjects *= 2;
204        attr->subject = creddy_xrealloc(attr->subject, attr->size_subjects * sizeof(creddy_attribute_t));
205    }
206
207    attr->subject[attr->num_subjects++] = subject;
208    attr->total_len += strlen(subject);
209}
210
211char *_get_role_encoding(creddy_attribute_t *attr) {
212    int i, num_subjects;
213
214    num_subjects = attr->num_subjects;
215
216    int len = SHA1_LENGTH + 1 + strlen(attr->role) + strlen(ROLE_SEPARATOR);
217    len += attr->total_len + num_subjects * strlen(INTERSECTION_SEP);
218
219    char *encoding = creddy_xmalloc(len);
220    sprintf(encoding, "%s.%s" ROLE_SEPARATOR, creddy_id_keyid(attr->issuer), attr->role);
221
222    for (i = 0; i < num_subjects; ++i) {
223        strcat(encoding, attr->subject[i]);
224        if (i < num_subjects - 1)
225            strcat(encoding, INTERSECTION_SEP);
226    }
227
228    return encoding;
229}
Note: See TracBrowser for help on using the repository browser.