source: creddy/attr.c @ aa33ad9

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

pull out attribute object

  • Property mode set to 100644
File size: 5.5 KB
Line 
1#include <assert.h>
2#include <ctype.h>
3#include <string.h>
4#include <time.h>
5
6#include "creddy.h"
7#include "id.h"
8#include "libcreddy.h"
9
10#define ROLE_SEPARATOR " <- "
11#define INTERSECTION_SEP " & "
12#define SHA1_LENGTH 40
13
14struct _creddy_attribute_t {
15    creddy_id_t *issuer;
16    char *role;
17    int validity;
18
19    char **subject;
20    int num_subjects;
21    int size_subjects;
22    int total_len; // total length of all subject strings
23
24    certificate_t *cert; // NULL until baked
25};
26
27static char *_validate_principal(char *keyid);
28static void _append(creddy_attribute_t *attr, char *subject);
29char *_get_role_encoding(creddy_attribute_t *attr);
30
31int creddy_attribute_create(creddy_attribute_t **ret, creddy_id_t *issuer, char *role, int validity) {
32    if (creddy_id_privkey(issuer) == NULL)
33        return CREDDY_ATTRIBUTE_ISSUER_NOKEY;
34    if (!clean_name(role))
35        return CREDDY_ATTRIBUTE_INVALID_ROLE;
36    if (validity < 0)
37        return CREDDY_ATTRIBUTE_INVALID_VALIDITY;
38
39    creddy_attribute_t *attr = xmalloc(sizeof(creddy_attribute_t));
40    attr->issuer = issuer;
41    attr->role = xstrdup(role);
42    attr->validity = validity;
43
44    attr->num_subjects = 0;
45    attr->size_subjects = 4;
46    attr->subject = xmalloc(sizeof(char *) * attr->size_subjects);
47    attr->total_len = 0;
48
49    // NULL until baked
50    attr->cert = NULL;
51
52    *ret = attr;
53    return CREDDY_SUCCESS;
54}
55
56int creddy_attribute_principal(creddy_attribute_t *attr, char *keyid) {
57    char *copy = _validate_principal(keyid);
58    if (copy == NULL)
59        return 0;
60
61    _append(attr, copy);
62    return 1;
63}
64
65int creddy_attribute_role(creddy_attribute_t *attr, char *keyid, char *role) {
66    if (!clean_name(role))
67        return 0;
68
69    char *copy = _validate_principal(keyid);
70    if (copy == NULL)
71        return 0;
72
73    int len = strlen(copy) + strlen(role) + strlen(ROLE_SEPARATOR) + 1;
74    copy = xrealloc(copy, len);
75    strcat(copy, ".");
76    strcat(copy, role);
77
78    _append(attr, copy);
79    return 1;
80}
81
82int creddy_attribute_linking_role(creddy_attribute_t *attr, char *keyid, char *role, char *linked) {
83    if (!clean_name(role) || !clean_name(linked))
84        return 0;
85
86    char *copy = _validate_principal(keyid);
87    if (copy == NULL)
88        return 0;
89
90    int len = strlen(copy) + strlen(role) + strlen(ROLE_SEPARATOR) + 2;
91    copy = xrealloc(copy, len);
92    strcat(copy, ".");
93    strcat(copy, role);
94    strcat(copy, ".");
95    strcat(copy, linked);
96
97    _append(attr, copy);
98    return 1;
99}
100
101int creddy_attribute_bake(creddy_attribute_t *attr) {
102    if (attr->num_subjects == 0)
103        return 0;
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 1 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 = 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 = 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 = 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.