source: libabac/abac_id.c @ f30b1e9

abac0-leakabac0-meimei-idmei-rt0-nmei_rt0tvf-new-xml
Last change on this file since f30b1e9 was f30b1e9, checked in by Mei <mei@…>, 11 years ago

1) update some do

  • Property mode set to 100644
File size: 9.3 KB
Line 
1
2/* abac_id.c */
3
4// include the GNU extension of asprintf
5#define _GNU_SOURCE
6#include <stdio.h>
7#include <string.h>
8
9#include <assert.h>
10#include <err.h>
11#include <time.h>
12
13#include "libabac_common.h"
14#include "abac_util.h"
15#include "abac_openssl.h"
16
17#define KEY_SUFFIX  "_private.pem"
18#define CERT_SUFFIX "_ID.pem"
19
20static int debug=0;
21
22// ID object
23//
24struct _abac_id_t {
25    char *keyid;
26    char *cn;
27    X509 *cert;
28    EVP_PKEY *key;
29
30    int refcount;
31};
32
33/**************************************************************/
34/**
35 * Helper function for building a ID from a cert. Used by
36 * abac_id_from_*
37 */
38abac_id_t *_id_from_cert(X509 *cert) {
39    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
40    id->cert = cert;
41    id->key = NULL;
42
43    id->keyid = abac_xstrdup(abac_get_keyid(cert));
44    id->cn = abac_xstrdup(abac_get_cn(cert));
45
46    id->refcount = 1;
47    return id;
48}
49
50/**
51 * Load an ID cert from a file.
52 */
53abac_id_t *abac_id_from_file(char *filename) {
54
55    FILE *fp=fopen(filename,"r");
56    if(fp==NULL)
57        return NULL;
58
59    X509 *cert = abac_load_id_from_fp(fp);
60    fclose(fp);
61
62    if (cert == NULL)
63        return NULL;
64
65    return _id_from_cert(cert);
66}
67
68/* for some reason, there might be beginning and trailing spaces
69in pem, zap the end with \0 and skip the spaces at the start*/
70char *zap_spaces(char *string)
71{
72   int space=0;
73   int total=strlen(string);
74   int i=0;
75   char *ptr=string;
76   while(string[i]==' ' && i<total) {
77       i++;
78       ptr++;
79   }
80   for(;i<total; i++) {
81       if(string[i]==' ') {
82         space++;
83         string[i]='\0';
84       } 
85   }
86   return ptr;
87}
88
89/* return a void ptr to the x509 structure made from the
90   naked pem structure */
91void *abac_get_sha_from_nake_pem(char *npem, char **sha1) {
92    abac_chunk_t chunk;
93    char *start="-----BEGIN CERTIFICATE-----";
94    char *end="-----END CERTIFICATE-----";
95    char *pem=NULL;
96    char *ptr=zap_spaces(npem);
97    asprintf(&pem,"%s%s%s",start,ptr,end);
98    chunk.ptr=(unsigned char *)pem;
99    chunk.len=strlen(pem);
100    X509 *cert=abac_load_id_from_chunk(chunk.ptr,chunk.len);
101    *sha1=NULL;
102    if(cert) {
103        *sha1 = abac_xstrdup(abac_get_keyid(cert));
104        if(debug) fprintf(stderr,"sha1 found is %s\n", *sha1);
105        } else {
106            *sha1=NULL;
107            fprintf(stderr,"can not make cert from pem blob!!\n");
108    }
109    return (void *) cert;
110}
111
112/**
113 * Load an ID cert from a chunk.
114 */
115abac_id_t *abac_id_from_chunk(abac_chunk_t chunk) {
116
117    X509 *cert= abac_load_id_from_chunk(chunk.ptr, chunk.len);
118
119    if (cert == NULL)
120        return NULL;
121
122    return _id_from_cert(cert);
123}
124
125static EVP_PKEY *_load_privkey_from_file(char *filename)
126{
127    FILE *fp=fopen(filename,"r");
128    if(fp==NULL) return NULL;
129    EVP_PKEY *key=abac_load_privkey_from_fp(fp);
130    fclose(fp);
131    return key;
132}
133
134/**
135 * Load private key for a cert.
136 */
137int abac_id_privkey_from_file(abac_id_t *id, char *filename) {
138    assert(id != NULL);
139
140    EVP_PKEY *key=_load_privkey_from_file(filename);
141    if (key == NULL) return ABAC_FAILURE;
142
143/* needs to make sure that the key matches up with the id */
144    /* extract the pub key from the id */
145    EVP_PKEY *pubkey=extract_pubkey_from_cert(id->cert);
146    /* cmp will just compare the pub key part of the key to see
147       if they are the same */
148    if(!EVP_PKEY_cmp(pubkey, key)) {
149        fprintf(stderr,"wrong private key for the cert!!\n");
150        return ABAC_FAILURE;
151    }
152
153    id->key = key;
154    return ABAC_SUCCESS;
155}
156
157/**
158 * Generate an ID with the specified CN and validity.
159 *
160 * validity is measured in seconds (as of 0.2.0)
161 */
162int abac_id_generate(abac_id_t **ret, char *cn, long validity) {
163    if (cn == NULL || !abac_clean_name(cn))
164        return ABAC_GENERATE_INVALID_CN;
165
166    if (validity < 0)
167        return ABAC_GENERATE_INVALID_VALIDITY;
168
169    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
170
171    id->cn = abac_xstrdup(cn);
172    id->key = abac_generate_key();
173    id->cert = abac_generate_cert(id->key, cn, validity);
174    id->keyid = abac_xstrdup(abac_get_keyid(id->cert));
175
176    id->refcount = 1;
177
178    *ret = id;
179    return ABAC_SUCCESS;
180}
181
182/**
183 * Generate an ID with the specified CN and validity.
184 *
185 * validity is measured in seconds (as of 0.2.0)
186 */
187int abac_id_generate_with_key(abac_id_t **ret, char *cn, long validity, char *keyfile) {
188    if (cn == NULL || !abac_clean_name(cn))
189        return ABAC_GENERATE_INVALID_CN;
190
191    if (validity < 0)
192        return ABAC_GENERATE_INVALID_VALIDITY;
193
194    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
195
196    id->cn = abac_xstrdup(cn);
197    id->key = _load_privkey_from_file(keyfile);
198    id->cert = abac_generate_cert(id->key, cn, validity);
199    id->keyid = abac_xstrdup(abac_get_keyid(id->cert));
200    id->refcount = 1;
201
202    *ret = id;
203    return ABAC_SUCCESS;
204}
205
206char *abac_id_keyid(abac_id_t *id) {
207    if(id) return id->keyid;
208        return NULL;
209}
210
211/**
212 * Get the issuer of an ID cert.
213 * Returns a malloc'd string that must be free'd.
214 */
215char *abac_id_issuer(abac_id_t *id) {
216    if(id) return abac_get_issuer(id->cert);
217        else return NULL;
218}
219
220/**
221 * Gets the subject DN of an ID cert.
222 * Returns a malloc'd string that must be free'd.
223 */
224char *abac_id_subject(abac_id_t *id) {
225    if(id) return abac_get_subject(id->cert);
226        else return NULL;
227}
228
229/**
230 * Get the validity period.
231 */
232int abac_id_validity(abac_id_t *id,struct tm *not_before,struct tm *not_after) {
233    assert(id);
234    if(abac_check_validity(id->cert, not_before, not_after)==0)
235        return ABAC_SUCCESS;
236    return ABAC_FAILURE;
237}
238
239X509 *abac_id_cert(abac_id_t *id) {
240    assert(id);
241    return id->cert;
242}
243
244// get the private key from the ID
245// will return NULL if no key has been loaded
246EVP_PKEY *abac_id_privkey(abac_id_t *id) {
247    assert(id);
248    return id->key;
249}
250
251int abac_id_has_privkey(abac_id_t *id) {
252    if(id && (id->key !=NULL))
253        return 1;
254    return 0;
255}
256
257// see if keyid is the same as id's
258int abac_id_has_keyid(abac_id_t *id, char *keyid)
259{
260    assert(id); assert(keyid);
261    if(strcmp(id->keyid, keyid) == 0)
262        return 1;
263    return 0;
264}
265
266/*
267   return a chunk with both id and key info,
268   err if missing privkey
269*/
270int abac_id_PEM(abac_id_t *id, abac_chunk_t *chunk) {
271    if(id==NULL)
272        return ABAC_CERT_MISSING_ISSUER;
273    if(id->key == NULL)
274        return ABAC_CERT_SIGNER_NOKEY;
275
276    unsigned char *kptr=NULL;
277    unsigned char *ptr=abac_string_cert(id->cert);
278    if(id->key)
279        kptr=abac_string_privkey(id->key);
280    int len=0;
281   
282    char *tmp=NULL;
283    if(kptr)  {
284        asprintf(&tmp,"%s%s", ptr,kptr);
285        free(ptr);
286        free(kptr);
287        } else {
288            tmp=(char *)ptr;
289    }
290    len=strlen(tmp);
291
292    chunk->ptr=(unsigned char *)tmp;
293    chunk->len=len;
294    return ABAC_CERT_SUCCESS;
295}
296
297abac_chunk_t abac_id_in_PEM(abac_id_t *id) {
298    assert(id);
299    unsigned char *ptr=abac_string_cert(id->cert);
300    int len=0;
301    if(ptr)
302        len=strlen((char *)ptr);
303    abac_chunk_t ret = {ptr, len };
304    return ret;
305}
306
307
308int abac_id_still_valid(abac_id_t *id) {
309    assert(id);
310    return abac_still_valid(id->cert);
311}
312
313/**
314 * Get the default filename for the cert. Value must be freed by caller.
315 */
316char *abac_id_cert_filename(abac_id_t *id) {
317    assert(id != NULL);
318    assert(id->cn != NULL);
319
320    // malloc the filename
321    int len = strlen(id->cn) + strlen(CERT_SUFFIX) + 1;
322    char *filename = abac_xmalloc(len);
323    sprintf(filename, "%s" CERT_SUFFIX, id->cn);
324
325    return filename;
326}
327
328/**
329 * Write the ID cert to an open file pointer.
330 * pem format
331 */
332int abac_id_write_cert(abac_id_t *id, FILE *out) {
333    assert(id != NULL);
334
335    int ret=abac_write_id_to_fp(id->cert, out);
336    if(ret) return ABAC_FAILURE; 
337    return ABAC_SUCCESS;
338}
339
340/**
341 * Default private key filename. Value must be freed by caller.
342 */
343char *abac_id_privkey_filename(abac_id_t *id) {
344    assert(id != NULL);
345    assert(id->cn != NULL);
346
347    // malloc the filename
348    int len = strlen(id->cn) + strlen(KEY_SUFFIX) + 1;
349    char *filename = abac_xmalloc(len);
350    sprintf(filename, "%s" KEY_SUFFIX, id->cn);
351
352    return filename;
353}
354
355/**
356 * Write the private key to a file.
357 * Returns false if there's no private key loaded
358 * PEM format
359 */
360int abac_id_write_privkey(abac_id_t *id, FILE *out) {
361    assert(id != NULL);
362    if (id->key == NULL)
363        return ABAC_FAILURE;
364
365    int ret=abac_write_privkey_to_fp(id->key, out);
366    if (ret)
367        return ABAC_FAILURE;
368
369    return ABAC_SUCCESS;
370}
371
372/**
373 * Get a abac_chunk representing the id cert.
374 */
375abac_chunk_t abac_id_cert_chunk(abac_id_t *id) {
376
377    assert(id); assert(id->cert);
378    unsigned char *ptr=abac_string_cert(id->cert);
379    int len=0;
380    if(ptr) len=strlen( (char *)ptr);
381
382    abac_chunk_t ret = { ptr, len };
383    return ret;
384}
385
386/**
387 * Get a abac_chunk representing the privkey cert.
388 */
389abac_chunk_t abac_id_privkey_chunk(abac_id_t *id) {
390
391    assert(id); assert(id->key);
392    unsigned char *ptr=abac_string_privkey(id->key);
393    int len=0;
394    if(ptr) len=strlen( (char *)ptr);
395
396    abac_chunk_t ret = { ptr, len };
397    return ret;
398}
399
400
401/**
402 * Copy a ID. Actually just increases its reference count.
403 */
404abac_id_t *abac_id_dup(abac_id_t *id) {
405    assert(id);
406    ++id->refcount;
407    return id;
408}
409
410void abac_id_free(abac_id_t *id) {
411    if (id == NULL)
412        return;
413
414    --id->refcount;
415    if (id->refcount > 0)
416        return;
417
418    // free once the reference count reaches 0
419    X509_free(id->cert);
420    EVP_PKEY_free(id->key);
421
422    free(id->keyid);
423    free(id);
424}
425
Note: See TracBrowser for help on using the repository browser.