source: creddy/id.c @ 3131b19

abac0-leakabac0-meicompt_changesgec13mei-idmei-rt0-nmei_rt0mei_rt2mei_rt2_fix_1meiyap-rt1meiyap1rt2tvf-new-xml
Last change on this file since 3131b19 was 002b25a, checked in by Mike Ryan <mikeryan@…>, 14 years ago

first cut at creddy_id object, integrated into attribute

  • Property mode set to 100644
File size: 4.5 KB
Line 
1#include <assert.h>
2#include <termios.h>
3
4#include "creddy.h"
5#include "id.h"
6
7/* Size of password memory allocation */
8#define PWLEN 128
9
10//
11// ID object
12//
13struct _creddy_id_t {
14    char *keyid;
15    char *cn;
16    certificate_t *cert;
17    private_key_t *key;
18}; 
19
20/* Callback configuration */
21struct cb_opts {
22    bool use_prompt;    /* Print a prompt to stderr */
23    bool use_echo;      /* If true, turn off input echo on stdin */
24    unsigned int tries; /* Number of attempts allowed */
25    char prompt[20];    /* The prompt to display if use_echo is true */
26};
27
28static chunk_t _passphrase_callback(void *user, int try);
29
30/**
31 * Load an ID cert from a file.
32 */
33creddy_id_t *creddy_id_from_file(char *filename) {
34    certificate_t *cert = lib->creds->create(lib->creds,
35        CRED_CERTIFICATE, CERT_X509,
36        BUILD_FROM_FILE, filename,
37        BUILD_X509_FLAG, X509_AA,
38        BUILD_END
39    );
40
41    if (cert == NULL)
42        return NULL;
43
44    creddy_id_t *id = xmalloc(sizeof(creddy_id_t));
45    id->keyid = NULL;
46    id->cn = NULL;
47    id->cert = cert;
48    id->key = NULL;
49
50    // get the keyid
51    x509_t *x509 = (x509_t *)cert;
52    chunk_t keyid = x509->get_subjectKeyIdentifier(x509);
53    chunk_t string = chunk_to_hex(keyid, NULL, 0);
54    id->keyid = string.ptr;
55
56    // TODO get CN
57
58    return id;
59}
60
61int creddy_id_load_privkey(creddy_id_t *id, char *filename) {
62    struct cb_opts c_opts = { 1, 0, 3, "Key password:" };
63
64    assert(id != NULL);
65
66    // load signer key
67    private_key_t *key = lib->creds->create(lib->creds,
68        CRED_PRIVATE_KEY, KEY_RSA,
69        BUILD_FROM_FILE, filename,
70        /* Ask for password if the key's encrypted */
71        BUILD_PASSPHRASE_CALLBACK, _passphrase_callback, &c_opts, 
72        BUILD_END
73    );
74    if (key == NULL)
75        return 0;
76
77    id->key = key;
78}
79
80char *creddy_id_keyid(creddy_id_t *id) {
81    assert(id != NULL);
82
83    return id->keyid;
84}
85
86certificate_t *creddy_id_cert(creddy_id_t *id) {
87    assert(id != NULL);
88
89    return id->cert;
90}
91
92private_key_t *creddy_id_privkey(creddy_id_t *id) {
93    assert(id != NULL);
94
95    return id->key;
96}
97
98void creddy_id_free(creddy_id_t *id) {
99    if (id == NULL)
100        return;
101
102    DESTROY_IF(id->cert);
103    DESTROY_IF(id->key);
104
105    free(id->keyid);
106    free(id);
107}
108
109//
110// Helper functions below
111//
112
113static chunk_t _passphrase_callback(void *user, int try) {
114    /* Get a password from stdin and return it as a chunk_t.  If too many tries
115     * have occurred or there is any other problem, return an empty chunk_t,
116     * which libstrongswan takes as giving up.  The chunk is alloated here
117     * (inside getline), and presumably freed by libstrongswan. User points to
118     * a cb_opts struct, which affects this routine in the obvious ways.
119     */
120    /* Configuration options */
121    struct cb_opts *opts = (struct cb_opts *) user;
122    chunk_t rv = chunk_empty;   /* Return value, starts empty */
123
124    if (try -1 < opts->tries ) {
125        struct termios t;   /* Terminal settings */
126        size_t len = 0;     /* Length of string from getline */
127        tcflag_t orig = 0;  /* Holds the original local flags (echo in here) */
128
129        if (!opts->use_echo) {
130            /* Use tc{get,set}attr to turn echo off and restore the intial
131             * echo settings */
132            if (!tcgetattr(0, &t)) { 
133                orig = t.c_lflag;
134
135                t.c_lflag &= ~ECHO;
136                if ( tcsetattr(0, TCSANOW, &t) ) { 
137                    perror("Cannot turn off echo"); 
138                    return rv;
139                }
140            }
141            else {
142                perror("Cannot turn get attributes to off echo"); 
143                return rv;
144            }
145        }
146        if (opts->use_prompt) printf("%s", opts->prompt);
147
148        /* Because rv.ptr starts as NULL, getline allocates memory.  The size
149         * of the allocation returns in rv.len and the size of the string
150         * (including newline and NUL) is in len.  */
151        if ((rv.ptr = (u_char *) malloc(rv.len = PWLEN))) {
152            if ( fgets(rv.ptr, rv.len, stdin) ) {
153                /* Readjust the chunk_t's len field to the size of the string
154                 * w/o the newline or NUL */
155                /* would prefer strnlen, but no such luck in FBSD7 or earlier*/
156                size_t len = strlen(rv.ptr);
157
158                if (rv.ptr[len-2] == '\n') rv.len = len-2;
159                else rv.len = len -1;
160            }
161            else {
162                /* Read failed.  Deallocate and clear rv */
163                free(rv.ptr);
164                rv = chunk_empty;
165            }
166        }
167        else {
168            /* Failed malloc.  Restore rv to empty and return it */
169            perror("malloc");
170            rv = chunk_empty;
171            return rv;
172        }
173
174        if (!opts->use_echo ) {
175            /* Pop echo beck to its original setting. */
176            t.c_lflag = orig;
177
178            if ( tcsetattr(0, TCSANOW, &t) ) 
179                perror("Cannot restore echo setting?"); 
180
181            if (opts->use_prompt) printf("\n");
182        }
183    }
184    else fprintf(stderr, "Too many tries (%d)", try-1);
185    return rv;
186}
Note: See TracBrowser for help on using the repository browser.