source: creddy/attr.c @ 78358ab

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

fix comment and put creddy_attribute_write into the header

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