source: libabac/abac_id.c @ 9ac7fb4

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

1) work around some compilation warnings

  • Property mode set to 100644
File size: 7.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
20// ID object
21//
22struct _abac_id_t {
23    char *keyid;
24    char *cn;
25    X509 *cert;
26    EVP_PKEY *key;
27
28    int refcount;
29};
30
31/**************************************************************/
32/**
33 * Helper function for building a ID from a cert. Used by
34 * abac_id_from_*
35 */
36abac_id_t *_id_from_cert(X509 *cert) {
37    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
38    id->keyid = NULL;
39    id->cn = NULL;
40    id->cert = cert;
41    id->key = NULL;
42
43    id->keyid = abac_get_keyid(id->cert);
44    id->cn = abac_get_cn(cert);
45
46    id->refcount = 1;
47
48    return id;
49}
50
51/**
52 * Load an ID cert from a file.
53 */
54abac_id_t *abac_id_from_file(char *filename) {
55
56    FILE *fp=fopen(filename,"r");
57    if(fp==NULL)
58        return NULL;
59
60    X509 *cert = abac_load_id_from_fp(fp);
61    fclose(fp);
62
63    if (cert == NULL)
64        return NULL;
65
66    return _id_from_cert(cert);
67}
68
69/**
70 * Load an ID cert from a chunk.
71 */
72abac_id_t *abac_id_from_chunk(abac_chunk_t chunk) {
73
74    X509 *cert= abac_load_id_from_chunk(chunk.ptr, chunk.len);
75
76    if (cert == NULL)
77        return NULL;
78
79    return _id_from_cert(cert);
80}
81
82/**
83 * Load private key for a cert.
84 */
85int abac_id_privkey_from_file(abac_id_t *id, char *filename) {
86    assert(id != NULL);
87
88    FILE *fp=fopen(filename,"r");
89    if(fp==NULL) return ABAC_FAILURE;
90
91    EVP_PKEY *key=abac_load_privkey_from_fp(fp);
92    fclose(fp);
93
94    if (key == NULL) return ABAC_FAILURE;
95
96/* needs to make sure that the key matches up with the id */
97    /* extract the pub key from the id */
98    EVP_PKEY *pubkey=extract_pubkey_from_cert(id->cert);
99    /* cmp will just compare the pub key part of the key to see
100       if they are the same */
101    if(!EVP_PKEY_cmp(pubkey, key)) {
102        fprintf(stderr,"wrong private key for the cert!!\n");
103        return ABAC_FAILURE;
104    }
105
106    id->key = key;
107    return ABAC_SUCCESS;
108}
109
110/**
111 * Generate an ID with the specified CN and validity.
112 *
113 * validity is measured in seconds (as of 0.2.0)
114 */
115int abac_id_generate(abac_id_t **ret, char *cn, long validity) {
116    if (cn == NULL || !abac_clean_name(cn))
117        return ABAC_GENERATE_INVALID_CN;
118
119    if (validity < 0)
120        return ABAC_GENERATE_INVALID_VALIDITY;
121
122    abac_id_t *id = abac_xmalloc(sizeof(abac_id_t));
123
124    id->cn = abac_xstrdup(cn);
125    id->key = abac_generate_key();
126    id->cert = abac_generate_cert(id->key, cn, validity);
127    id->keyid = abac_get_keyid(id->cert);
128
129    id->refcount = 1;
130
131    *ret = id;
132    return ABAC_SUCCESS;
133}
134
135char *abac_id_keyid(abac_id_t *id) {
136    if(id) return id->keyid;
137        return NULL;
138}
139
140/**
141 * Get the issuer of an ID cert.
142 * Returns a malloc'd string that must be free'd.
143 */
144char *abac_id_issuer(abac_id_t *id) {
145    if(id) return abac_get_issuer(id->cert);
146        else return NULL;
147}
148
149/**
150 * Gets the subject DN of an ID cert.
151 * Returns a malloc'd string that must be free'd.
152 */
153char *abac_id_subject(abac_id_t *id) {
154    if(id) return abac_get_subject(id->cert);
155        else return NULL;
156}
157
158/**
159 * Get the validity period.
160 */
161int abac_id_validity(abac_id_t *id,struct tm *not_before,struct tm *not_after) {
162    assert(id);
163    if(abac_check_validity(id->cert, not_before, not_after)==0)
164        return ABAC_SUCCESS;
165    return ABAC_FAILURE;
166}
167
168X509 *abac_id_cert(abac_id_t *id) {
169    assert(id);
170    return id->cert;
171}
172
173// get the private key from the ID
174// will return NULL if no key has been loaded
175EVP_PKEY *abac_id_privkey(abac_id_t *id) {
176    assert(id);
177    return id->key;
178}
179
180int abac_id_has_privkey(abac_id_t *id) {
181    if(id && (id->key !=NULL))
182        return 1;
183    return 0;
184}
185
186// see if keyid is the same as id's
187int abac_id_has_keyid(abac_id_t *id, char *keyid)
188{
189    assert(id); assert(keyid);
190    if(strcmp(id->keyid, keyid) == 0)
191        return 1;
192    return 0;
193}
194
195/*
196   return a chunk with both id and key info,
197   err if missing privkey
198*/
199int abac_id_PEM(abac_id_t *id, abac_chunk_t *chunk) {
200    if(id==NULL)
201        return ABAC_CERT_MISSING_ISSUER;
202    if(id->key == NULL)
203        return ABAC_CERT_SIGNER_NOKEY;
204
205    unsigned char *kptr=NULL;
206    unsigned char *ptr=abac_string_cert(id->cert);
207    if(id->key)
208        kptr=abac_string_privkey(id->key);
209    int len=0;
210   
211    char *tmp=NULL;
212    if(kptr)  {
213        asprintf(&tmp,"%s%s", ptr,kptr);
214        free(ptr);
215        free(kptr);
216        } else {
217            tmp=(char *)ptr;
218    }
219    len=strlen(tmp);
220
221    chunk->ptr=(unsigned char *)tmp;
222    chunk->len=len;
223    return ABAC_CERT_SUCCESS;
224}
225
226abac_chunk_t abac_id_in_PEM(abac_id_t *id) {
227    assert(id);
228    unsigned char *ptr=abac_string_cert(id->cert);
229    int len=0;
230    if(ptr)
231        len=strlen((char *)ptr);
232    abac_chunk_t ret = {ptr, len };
233    return ret;
234}
235
236
237int abac_id_still_valid(abac_id_t *id) {
238    assert(id);
239    return abac_still_valid(id->cert);
240}
241
242/**
243 * Get the default filename for the cert. Value must be freed by caller.
244 */
245char *abac_id_cert_filename(abac_id_t *id) {
246    assert(id != NULL);
247    assert(id->cn != NULL);
248
249    // malloc the filename
250    int len = strlen(id->cn) + strlen(CERT_SUFFIX) + 1;
251    char *filename = abac_xmalloc(len);
252    sprintf(filename, "%s" CERT_SUFFIX, id->cn);
253
254    return filename;
255}
256
257/**
258 * Write the ID cert to an open file pointer.
259 * pem format
260 */
261int abac_id_write_cert(abac_id_t *id, FILE *out) {
262    assert(id != NULL);
263
264    int ret=abac_write_id_to_fp(id->cert, out);
265    if(ret) return ABAC_FAILURE; 
266    return ABAC_SUCCESS;
267}
268
269/**
270 * Default private key filename. Value must be freed by caller.
271 */
272char *abac_id_privkey_filename(abac_id_t *id) {
273    assert(id != NULL);
274    assert(id->cn != NULL);
275
276    // malloc the filename
277    int len = strlen(id->cn) + strlen(KEY_SUFFIX) + 1;
278    char *filename = abac_xmalloc(len);
279    sprintf(filename, "%s" KEY_SUFFIX, id->cn);
280
281    return filename;
282}
283
284/**
285 * Write the private key to a file.
286 * Returns false if there's no private key loaded
287 * PEM format
288 */
289int abac_id_write_privkey(abac_id_t *id, FILE *out) {
290    assert(id != NULL);
291    if (id->key == NULL)
292        return ABAC_FAILURE;
293
294    int ret=abac_write_privkey_to_fp(id->key, out);
295    if (ret)
296        return ABAC_FAILURE;
297
298    return ABAC_SUCCESS;
299}
300
301/**
302 * Get a abac_chunk representing the id cert.
303 */
304abac_chunk_t abac_id_cert_chunk(abac_id_t *id) {
305
306    assert(id); assert(id->cert);
307    unsigned char *ptr=abac_string_cert(id->cert);
308    int len=0;
309    if(ptr) len=strlen( (char *)ptr);
310
311    abac_chunk_t ret = { ptr, len };
312    return ret;
313}
314
315/**
316 * Get a abac_chunk representing the privkey cert.
317 */
318abac_chunk_t abac_id_privkey_chunk(abac_id_t *id) {
319
320    assert(id); assert(id->key);
321    unsigned char *ptr=abac_string_privkey(id->key);
322    int len=0;
323    if(ptr) len=strlen( (char *)ptr);
324
325    abac_chunk_t ret = { ptr, len };
326    return ret;
327}
328
329
330/**
331 * Copy a ID. Actually just increases its reference count.
332 */
333abac_id_t *abac_id_dup(abac_id_t *id) {
334    assert(id);
335    ++id->refcount;
336    return id;
337}
338
339void abac_id_free(abac_id_t *id) {
340    if (id == NULL)
341        return;
342
343    --id->refcount;
344    if (id->refcount > 0)
345        return;
346
347    // free once the reference count reaches 0
348    X509_free(id->cert);
349    EVP_PKEY_free(id->key);
350
351    free(id->keyid);
352    free(id);
353}
354
Note: See TracBrowser for help on using the repository browser.