source: creddy/attr.c @ 8f58012

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

finer granularity over validity periods

API: ID and attr certs take seconds for validity period
command line: validity option takes a suffix for time period

fixes #20

this is an API-breaking change, so a bump to 0.2.0 is necessary

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