source: libabac/abac_id.c @ c0fd8bc

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

1) add some strcpy for keyid assignments in abac_id

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