source: libabac/abac_id.c @ 02036f4

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

1) tweak for porting try

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