source: libabac/abac_id.c @ 2a73357

mei_rt2mei_rt2_fix_1
Last change on this file since 2a73357 was 94a4dd2, checked in by Mei <mei@…>, 12 years ago

1) save a set of performance jpegs into examples/scaling_tests/plotting dir

  • Property mode set to 100644
File size: 13.4 KB
Line 
1
2/**
3**  abac_id.c
4**/
5
6#include <assert.h>
7#include <err.h>
8#include <time.h>
9
10// include the GNU extension of asprintf
11#define _GNU_SOURCE
12#include <stdio.h>
13#include <err.h>
14
15#include "abac_internal.h"
16#include "abac_util.h"
17
18static int debug=0;
19
20#define KEY_SUFFIX  "_private.pem"
21#define CERT_SUFFIX "_ID.pem"
22
23extern private_key_t *abac_key_private_key(abac_key_t *ptr);
24extern abac_key_t *abac_key_file_new(char *filename, chunk_t potato);
25extern abac_key_t *abac_key_chunk_new(chunk_t keyblob, chunk_t potato);
26extern chunk_t abac_key_chunk(abac_key_t *);
27
28//
29// abac_id object
30//
31struct _abac_id_t {
32    int idtype;    /* default to string 'keyid' for now */
33
34    char *keyid; /* sha */
35    char *cn;
36
37    certificate_t *cert;
38    abac_key_t *key;
39
40    int refcount;
41};
42
43/****************************************************************/
44//
45// Helper functions below
46//
47static char *_get_keyid(certificate_t *cert) {
48    // get the keyid
49    x509_t *x509 = (x509_t *)cert;
50    chunk_t keyid = x509->get_subjectKeyIdentifier(x509);
51    chunk_t string = chunk_to_hex(keyid, NULL, 0);
52    return (char *)string.ptr;
53}
54
55static char *_create_dn(char *cn) {
56
57#define DN "cn="
58
59    char *dn = abac_xmalloc(sizeof(DN) + strlen(cn));
60    memcpy(dn, DN, sizeof(DN));
61    strcat(dn, cn);
62
63    return dn;
64}
65
66/**
67 * Generate ID certificate.
68 *
69 * validity is measured in seconds (as of 0.2.0)
70 */
71static certificate_t *_generate_cert(abac_key_t *keyptr, char *cn, int validity) {
72    // build the DN
73    char *dn_string = _create_dn(cn);
74    libabac_init();
75
76    identification_t *id = identification_create_from_string(dn_string);
77    if (id == NULL)
78        errx(1, "couldn't create ID from DN %s", dn_string);
79    free(dn_string);
80
81    // get the private key
82    private_key_t *private = abac_key_private_key(keyptr);
83    if(private == NULL)
84        errx(1, "couldn't create ID without private key");
85
86    public_key_t *public = private->get_public_key(private);
87    if (public == NULL)
88        errx(1, "couldn't get public key from private key");
89
90    // create a serial (stolen from strongswan pki)
91    rng_t *rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
92    if (!rng)
93        errx(1, "no random number generator");
94
95    // random serial
96    chunk_t serial = abac_generate_serial();
97
98    // validity period
99    time_t not_before = time(NULL);
100    time_t not_after = not_before + validity;
101
102    // create!
103    certificate_t *cert = lib->creds->create(lib->creds,
104        CRED_CERTIFICATE, CERT_X509,
105        BUILD_SIGNING_KEY, private,
106        BUILD_PUBLIC_KEY, public,
107        BUILD_SUBJECT, id,
108        BUILD_NOT_BEFORE_TIME, not_before,
109        BUILD_NOT_AFTER_TIME, not_after,
110        BUILD_SERIAL, serial,
111        BUILD_DIGEST_ALG, HASH_SHA1,
112        BUILD_X509_FLAG, X509_CA,
113        BUILD_PATHLEN, X509_NO_CONSTRAINT,
114        BUILD_END
115    );
116    if (cert == NULL)
117        errx(1, "couldn't build cert :(");
118
119    DESTROY_IF(id);
120    DESTROY_IF(public);
121    DESTROY_IF(private);
122    free(serial.ptr);
123
124    return cert;
125}
126
127#define BYTES_PER_LINE 64
128
129// thx libstrongswan
130static void _encode_base64(FILE *out, chunk_t encoding) {
131    int start;
132
133    chunk_t b64 = chunk_to_base64(encoding, NULL);
134
135    fprintf(out, "-----BEGIN CERTIFICATE-----\n");
136
137    for (start = 0; start < b64.len; start += BYTES_PER_LINE) {
138        int left = b64.len - start;
139        int len = left < BYTES_PER_LINE ? left : BYTES_PER_LINE;
140        fwrite(b64.ptr + start, len, 1, out);
141        fprintf(out, "\n");
142    }
143
144    fprintf(out, "-----END CERTIFICATE-----\n");
145
146    free(b64.ptr);
147}
148/****************************************************************/
149int abac_id_idtype(abac_id_t *id)
150{
151    assert(id != NULL);
152    return id->idtype;
153}
154
155char* abac_id_idtype_string(abac_id_t *id)
156{
157    assert(id != NULL);
158    return abac_idtype_string(id->idtype);
159}
160
161char *abac_id_keyid(abac_id_t *id) {
162    assert(id != NULL);
163    return id->keyid;
164}
165
166char *abac_id_cn(abac_id_t *id) {
167    assert(id != NULL);
168    return id->cn;
169}
170
171
172char *abac_id_name(abac_id_t *id)
173{
174    assert(id != NULL);
175    if(USE("ABAC_CN"))
176        return abac_id_cn(id);
177    else return abac_id_keyid(id);
178}
179
180char *abac_id_string(abac_id_t *id) 
181{
182    char *tmp=NULL;
183    if(abac_id_has_privkey(id)) 
184        asprintf(&tmp,"(%s,%s,y)",abac_id_name(id),abac_id_idtype_string(id));
185        else asprintf(&tmp,"(%s,%s,n)",abac_id_name(id),abac_id_idtype_string(id));
186    return tmp;
187}
188
189/**
190 * Get the issuer of an ID cert.
191 * Returns a malloc'd string that must be free'd.
192 */
193char *abac_id_issuer(abac_id_t *id) {
194    char *ret;
195    int rv = asprintf(&ret, "%Y", id->cert->get_issuer(id->cert));
196
197    if (rv < 0)
198        err(1, "couldn't malloc string for issuer\n");
199
200    return ret;
201}
202
203int abac_id_lastone(abac_id_t *ptr)
204{
205    assert(ptr);
206    if(ptr->refcount == 1)
207        return 1;
208    return 0;
209}
210
211
212/**
213 * Gets the subject DN of an ID cert.
214 * Returns a malloc'd string that must be free'd.
215 */
216char *abac_id_subject(abac_id_t *id) {
217    char *ret;
218    int rv = asprintf(&ret, "%Y", id->cert->get_subject(id->cert));
219
220    if (rv < 0)
221        err(1, "couldn't malloc string for subject\n");
222
223    return ret;
224}
225
226/**
227 * Get the validity period.
228 */
229void abac_id_validity(abac_id_t *id, time_t *not_before, time_t *not_after) {
230    id->cert->get_validity(id->cert, NULL, not_before, not_after);
231}
232
233certificate_t *abac_id_cert(abac_id_t *id) {
234    assert(id != NULL);
235    return id->cert;
236}
237
238private_key_t *abac_id_privkey(abac_id_t *id) {
239    assert(id != NULL);
240    if(id->key !=0)
241        return abac_key_private_key(id->key);
242    return NULL;
243}
244
245abac_key_t *abac_id_keyptr(abac_id_t *id)
246{
247    return id->key;
248}
249
250int abac_id_has_privkey(abac_id_t *id) {
251    if(id->key !=0)
252       return 1;
253    return 0;
254}
255
256
257/**
258 * Write the ID cert to an open file pointer.
259 */
260void abac_id_write_cert(abac_id_t *id, FILE *out) {
261    assert(id != NULL);
262
263    chunk_t encoding = chunk_empty;
264    int rc=id->cert->get_encoding(id->cert,CERT_ASN1_DER,&encoding);
265    if(rc) {
266        _encode_base64(out, encoding);
267        free(encoding.ptr);
268    }
269}
270
271/**
272 * Write the private key to a file.
273 * Returns false if there's no private key loaded
274 */
275int abac_id_write_privkey(abac_id_t *id, FILE *out)
276{
277    return abac_key_write_privkey(id->key, out);
278}
279
280/**
281 * Get a DER-encoded chunk representing the cert.
282 */
283abac_chunk_t abac_id_cert_chunk(abac_id_t *id) {
284    assert(id->cert);
285
286    chunk_t encoding = chunk_empty;
287    int rc= id->cert->get_encoding(id->cert, CERT_ASN1_DER, &encoding);
288    abac_chunk_t ret = { encoding.ptr, encoding.len };
289
290    return ret;
291}
292
293/**
294 * Get a PEM-encoded chunk representing the private key
295 */
296abac_chunk_t abac_id_privkey_chunk(abac_id_t *id) 
297{
298    chunk_t tmp=chunk_empty;
299    if(id->key) {
300         tmp=abac_key_chunk(id->key);
301    }
302            if(debug)
303        fprintf(stderr,"abac_id_privkey_chunk tmp ptr, loc(%d)(%d)\n", (int)tmp.ptr, tmp.len);
304
305    abac_chunk_t ret= {tmp.ptr, tmp.len}; 
306    if(debug)
307        fprintf(stderr,"abac_id_privkey_chunk ptr, loc(%d)(%d)\n", (int)ret.ptr, ret.len);
308    return ret;
309}
310
311void abac_id_print_key_chunk(abac_id_t *id)
312{
313   if(id->key)
314       print_abac_key("abac_id_print_key_chunk",id->key);
315}
316
317/**
318 * Copy an abac ID. Actually just increases its reference count.
319 */
320abac_id_t *abac_id_dup(abac_id_t *id) {
321    if(id)
322        ++id->refcount;
323    return id;
324}
325
326void abac_id_free(abac_id_t *id) {
327    if (id == NULL)
328        return;
329
330    --id->refcount;
331    if (id->refcount > 0)
332        return;
333
334    if(debug)
335        fprintf(stderr,"making abac_id_free call on (%s)!!!\n", id->cn);
336    // free once the reference count reaches 0
337    DESTROY_IF(id->cert);
338
339    if(id->key) abac_key_free(id->key);
340
341    free(id->keyid);
342    free(id->cn);
343    free(id);
344}
345
346/****************************************************************/
347/**
348 * Default private key filename. Value must be freed by caller.
349 */
350char *abac_id_privkey_filename(abac_id_t *id) {
351    assert(id != NULL);
352    assert(id->cn != NULL);
353
354    /* this cn has pCN attached to it */
355    char *filename = NULL;
356    char* ptr=id->cn;
357    asprintf(&filename, "%s%s",(ptr+1),KEY_SUFFIX);
358    return filename;
359}
360
361/**
362 * Get the default filename for the cert. Value must be freed by caller.
363 */
364char *abac_id_cert_filename(abac_id_t *id) {
365    assert(id != NULL);
366    assert(id->cn != NULL);
367
368    /* this cn has pCN attached to it */
369    char *filename = NULL;
370    char* ptr=id->cn;
371    asprintf(&filename, "%s%s",(ptr+1),CERT_SUFFIX);
372    return filename;
373}
374
375/****************************************************************/
376abac_id_t *abac_id_new(int idtype,char *keyid, char *cn, 
377certificate_t *cert)
378{
379    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
380    id->idtype = idtype;
381    id->keyid = abac_xstrdup(keyid);
382    id->cn = abac_xstrdup(cn);
383    id->cert = cert;
384    id->key = NULL;
385    id->refcount = 1;
386    if(debug) fprintf(stderr,"abac_id_new: made a new id, %ld\n",(long) id);
387    return id;
388}
389
390abac_id_t *abac_id_keyid_new(char *keyid, char *cn, certificate_t *cert)
391{
392    return abac_id_new(e_KEYID,keyid,cn,cert); 
393}
394
395static abac_id_t *_abac_id_from_cert(certificate_t *cert) {
396    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
397    id->idtype = e_KEYID;
398    id->keyid = NULL;
399    id->cn = NULL;
400    id->cert = cert;
401    id->key = NULL;
402
403    id->keyid = _get_keyid(id->cert);
404
405    // get the CN from the cert
406    id_part_t type;
407    chunk_t data;
408
409    identification_t *cert_id = id->cert->get_subject(id->cert);
410    enumerator_t *id_enum = cert_id->create_part_enumerator(cert_id);
411    while (id_enum->enumerate(id_enum, &type, &data))
412        if (type == ID_PART_RDN_CN) {
413            id->cn = abac_xmalloc(data.len + 1);
414            memcpy(id->cn, data.ptr, data.len);
415            id->cn[data.len] = 0;
416        }
417    id_enum->destroy(id_enum);
418
419    id->refcount = 1;
420
421    return id;
422}
423
424/**
425 * Load an ID cert from a file.
426 * this one does not add id into id hash list
427 */
428abac_id_t *abac_id_from_file(char *filename) {
429
430    /* make sure file exists */
431    if(!file_exist(filename)) return NULL;
432
433    libabac_init();
434    certificate_t *cert = lib->creds->create(lib->creds,
435        CRED_CERTIFICATE, CERT_X509,
436        BUILD_FROM_FILE, filename,
437        BUILD_X509_FLAG, X509_AA,
438        BUILD_END
439    );
440
441    if (cert == NULL)
442        return NULL;
443
444    return _abac_id_from_cert(cert);
445}
446
447/**
448 * Load an ID cert from a chunk.
449 */
450abac_id_t *abac_id_from_chunk(abac_chunk_t achunk) {
451    chunk_t chunk = { .ptr = achunk.ptr, .len = achunk.len };
452
453    certificate_t *cert = lib->creds->create(lib->creds,
454        CRED_CERTIFICATE, CERT_X509,
455        BUILD_BLOB_ASN1_DER, chunk,
456        BUILD_X509_FLAG, X509_AA,
457        BUILD_END
458    );
459
460    if (cert == NULL)
461        return NULL;
462
463    return _abac_id_from_cert(cert);
464}
465
466/**
467 * Generate an ID with the specified CN and validity.
468 *
469 * validity is measured in seconds (as of 0.2.0)
470 */
471int abac_id_generate(abac_id_t **ret, char *cn, int validity)
472{
473    if (cn == NULL || !abac_validate_clean_name(cn))
474        return ABAC_ID_GENERATE_INVALID_CN;
475
476    if(debug) fprintf(stderr,"abac_id_generate: generating id with cn(%s)\n",cn);
477
478    if (validity < 0)
479        return ABAC_ID_GENERATE_INVALID_VALIDITY;
480
481    if (validity == 0) validity = 1080 * 86400;
482
483    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
484
485    char *tmp=NULL;
486    asprintf(&tmp,"p%s",cn);
487    id->idtype = e_KEYID;
488    id->cn = tmp;
489    id->key = abac_key_generate();
490    id->cert = _generate_cert(id->key, cn, validity);
491    id->keyid = _get_keyid(id->cert);
492
493    id->refcount = 1;
494
495    *ret = id;
496    return ABAC_ID_SUCCESS;
497}
498
499
500/**
501 * Generate an ID with the specified CN and validity and a passphrase.
502 *
503 * validity is measured in seconds (as of 0.2.0)
504 */
505int abac_id_generate_with_key(abac_id_t **ret, char *cn, int validity, char *filename, char *pfile) {
506    if (cn == NULL || !abac_validate_clean_name(cn))
507        return ABAC_ID_GENERATE_INVALID_CN;
508
509    if(debug) {
510        fprintf(stderr,"abac_id_generate: generating id with cn(%s) and privkey(%s)",
511                                                    cn, filename);
512        if(pfile) fprintf(stderr,"pfile(%s)\n",pfile);
513            else fprintf(stderr,"\n");
514    }
515
516    if (validity < 0)
517        return ABAC_ID_GENERATE_INVALID_VALIDITY;
518
519    if (validity == 0) validity = 1080 * 86400;
520
521    chunk_t pp=chunk_empty;
522    if(pfile && strlen(pfile)!=0) {
523        if(!file_exist(pfile))
524            errx(1, "passphrase file does not exist!!\n");
525        pp=extract_potato(filename,pfile);
526    }
527
528    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
529    char *tmp=NULL;
530    asprintf(&tmp,"p%s",cn);
531    id->idtype = e_KEYID;
532    id->cn = tmp;
533    id->key = abac_key_file_new(filename,pp);
534    id->cert = _generate_cert(id->key, cn, validity);
535    id->keyid = _get_keyid(id->cert);
536
537    id->refcount = 1;
538
539    *ret = id;
540    return ABAC_ID_SUCCESS;
541}
542
543int abac_id_load_privkey_file(abac_id_t *ptr, char *keyfile)
544{
545    assert(ptr);
546    ptr->key=abac_key_file_new(keyfile, chunk_empty);
547    return 1;
548}
549
550int abac_id_load_enc_privkey_file(abac_id_t *ptr, char *keyfile, char *pfile)
551{
552    assert(ptr);
553    chunk_t pp=extract_potato(keyfile,pfile);
554    ptr->key=abac_key_file_new(keyfile, pp);
555    return 1;
556}
557
558int abac_id_load_privkey_chunk(abac_id_t *ptr, chunk_t keychunk)
559{
560    assert(ptr);
561    ptr->key=abac_key_chunk_new(keychunk, chunk_empty);
562    if(debug)
563        print_abac_key("after abac_id_load_privkey_chunk", ptr->key);
564    return 1;
565}
566
567int abac_id_load_enc_privkey_chunk(abac_id_t *ptr, chunk_t keychunk, char *pfile)
568{
569    assert(ptr);
570    chunk_t pp=extract_potato(NULL,pfile);
571    ptr->key=abac_key_chunk_new(keychunk, pp);
572    return 1;
573}
574
Note: See TracBrowser for help on using the repository browser.