Statistics
| Branch: | Revision:

root / libcacard / vcard_emul_nss.c @ 44dc0ca3

History | View | Annotate | Download (33.1 kB)

1 111a38b0 Robert Relyea
/*
2 111a38b0 Robert Relyea
 * This is the actual card emulator.
3 111a38b0 Robert Relyea
 *
4 111a38b0 Robert Relyea
 * These functions can be implemented in different ways on different platforms
5 111a38b0 Robert Relyea
 * using the underlying system primitives. For Linux it uses NSS, though direct
6 111a38b0 Robert Relyea
 * to PKCS #11, openssl+pkcs11, or even gnu crypto libraries+pkcs #11 could be
7 111a38b0 Robert Relyea
 * used. On Windows CAPI could be used.
8 111a38b0 Robert Relyea
 *
9 111a38b0 Robert Relyea
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 111a38b0 Robert Relyea
 * See the COPYING.LIB file in the top-level directory.
11 111a38b0 Robert Relyea
 */
12 111a38b0 Robert Relyea
13 111a38b0 Robert Relyea
/*
14 111a38b0 Robert Relyea
 * NSS headers
15 111a38b0 Robert Relyea
 */
16 111a38b0 Robert Relyea
17 111a38b0 Robert Relyea
/* avoid including prototypes.h that redefines uint32 */
18 111a38b0 Robert Relyea
#define NO_NSPR_10_SUPPORT
19 111a38b0 Robert Relyea
20 111a38b0 Robert Relyea
#include <nss.h>
21 111a38b0 Robert Relyea
#include <pk11pub.h>
22 111a38b0 Robert Relyea
#include <cert.h>
23 111a38b0 Robert Relyea
#include <key.h>
24 111a38b0 Robert Relyea
#include <secmod.h>
25 111a38b0 Robert Relyea
#include <prthread.h>
26 111a38b0 Robert Relyea
#include <secerr.h>
27 111a38b0 Robert Relyea
28 111a38b0 Robert Relyea
#include "qemu-common.h"
29 111a38b0 Robert Relyea
30 111a38b0 Robert Relyea
#include "vcard.h"
31 111a38b0 Robert Relyea
#include "card_7816t.h"
32 111a38b0 Robert Relyea
#include "vcard_emul.h"
33 111a38b0 Robert Relyea
#include "vreader.h"
34 111a38b0 Robert Relyea
#include "vevent.h"
35 111a38b0 Robert Relyea
36 111a38b0 Robert Relyea
struct VCardKeyStruct {
37 111a38b0 Robert Relyea
    CERTCertificate *cert;
38 111a38b0 Robert Relyea
    PK11SlotInfo *slot;
39 111a38b0 Robert Relyea
    SECKEYPrivateKey *key;
40 111a38b0 Robert Relyea
};
41 111a38b0 Robert Relyea
42 111a38b0 Robert Relyea
43 111a38b0 Robert Relyea
typedef struct VirtualReaderOptionsStruct VirtualReaderOptions;
44 111a38b0 Robert Relyea
45 111a38b0 Robert Relyea
struct VReaderEmulStruct {
46 111a38b0 Robert Relyea
    PK11SlotInfo *slot;
47 111a38b0 Robert Relyea
    VCardEmulType default_type;
48 111a38b0 Robert Relyea
    char *type_params;
49 111a38b0 Robert Relyea
    PRBool present;
50 111a38b0 Robert Relyea
    int     series;
51 111a38b0 Robert Relyea
    VCard *saved_vcard;
52 111a38b0 Robert Relyea
};
53 111a38b0 Robert Relyea
54 111a38b0 Robert Relyea
/*
55 111a38b0 Robert Relyea
 *  NSS Specific options
56 111a38b0 Robert Relyea
 */
57 111a38b0 Robert Relyea
struct VirtualReaderOptionsStruct {
58 111a38b0 Robert Relyea
    char *name;
59 111a38b0 Robert Relyea
    char *vname;
60 111a38b0 Robert Relyea
    VCardEmulType card_type;
61 111a38b0 Robert Relyea
    char *type_params;
62 111a38b0 Robert Relyea
    char **cert_name;
63 111a38b0 Robert Relyea
    int cert_count;
64 111a38b0 Robert Relyea
};
65 111a38b0 Robert Relyea
66 111a38b0 Robert Relyea
struct VCardEmulOptionsStruct {
67 111a38b0 Robert Relyea
    void *nss_db;
68 111a38b0 Robert Relyea
    VirtualReaderOptions *vreader;
69 111a38b0 Robert Relyea
    int vreader_count;
70 111a38b0 Robert Relyea
    VCardEmulType hw_card_type;
71 111a38b0 Robert Relyea
    const char *hw_type_params;
72 111a38b0 Robert Relyea
    PRBool use_hw;
73 111a38b0 Robert Relyea
};
74 111a38b0 Robert Relyea
75 111a38b0 Robert Relyea
static int nss_emul_init;
76 111a38b0 Robert Relyea
77 111a38b0 Robert Relyea
/* if we have more that just the slot, define
78 111a38b0 Robert Relyea
 * VCardEmulStruct here */
79 111a38b0 Robert Relyea
80 111a38b0 Robert Relyea
/*
81 111a38b0 Robert Relyea
 * allocate the set of arrays for certs, cert_len, key
82 111a38b0 Robert Relyea
 */
83 111a38b0 Robert Relyea
static PRBool
84 111a38b0 Robert Relyea
vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
85 111a38b0 Robert Relyea
                        VCardKey ***keysp, int cert_count)
86 111a38b0 Robert Relyea
{
87 111a38b0 Robert Relyea
    *certsp = NULL;
88 111a38b0 Robert Relyea
    *cert_lenp = NULL;
89 111a38b0 Robert Relyea
    *keysp = NULL;
90 111a38b0 Robert Relyea
    *certsp = (unsigned char **)qemu_malloc(sizeof(unsigned char *)*cert_count);
91 111a38b0 Robert Relyea
    *cert_lenp = (int *)qemu_malloc(sizeof(int)*cert_count);
92 111a38b0 Robert Relyea
    *keysp = (VCardKey **)qemu_malloc(sizeof(VCardKey *)*cert_count);
93 111a38b0 Robert Relyea
    return PR_TRUE;
94 111a38b0 Robert Relyea
}
95 111a38b0 Robert Relyea
96 111a38b0 Robert Relyea
/*
97 111a38b0 Robert Relyea
 * Emulator specific card information
98 111a38b0 Robert Relyea
 */
99 111a38b0 Robert Relyea
typedef struct CardEmulCardStruct CardEmulPrivate;
100 111a38b0 Robert Relyea
101 111a38b0 Robert Relyea
static VCardEmul *
102 111a38b0 Robert Relyea
vcard_emul_new_card(PK11SlotInfo *slot)
103 111a38b0 Robert Relyea
{
104 111a38b0 Robert Relyea
    PK11_ReferenceSlot(slot);
105 111a38b0 Robert Relyea
    /* currently we don't need anything other than the slot */
106 111a38b0 Robert Relyea
    return (VCardEmul *)slot;
107 111a38b0 Robert Relyea
}
108 111a38b0 Robert Relyea
109 111a38b0 Robert Relyea
static void
110 111a38b0 Robert Relyea
vcard_emul_delete_card(VCardEmul *vcard_emul)
111 111a38b0 Robert Relyea
{
112 111a38b0 Robert Relyea
    PK11SlotInfo *slot = (PK11SlotInfo *)vcard_emul;
113 111a38b0 Robert Relyea
    if (slot == NULL) {
114 111a38b0 Robert Relyea
        return;
115 111a38b0 Robert Relyea
    }
116 111a38b0 Robert Relyea
    PK11_FreeSlot(slot);
117 111a38b0 Robert Relyea
}
118 111a38b0 Robert Relyea
119 111a38b0 Robert Relyea
static PK11SlotInfo *
120 111a38b0 Robert Relyea
vcard_emul_card_get_slot(VCard *card)
121 111a38b0 Robert Relyea
{
122 111a38b0 Robert Relyea
    /* note, the card is holding the reference, no need to get another one */
123 111a38b0 Robert Relyea
    return (PK11SlotInfo *)vcard_get_private(card);
124 111a38b0 Robert Relyea
}
125 111a38b0 Robert Relyea
126 111a38b0 Robert Relyea
127 111a38b0 Robert Relyea
/*
128 111a38b0 Robert Relyea
 * key functions
129 111a38b0 Robert Relyea
 */
130 111a38b0 Robert Relyea
/* private constructure */
131 111a38b0 Robert Relyea
static VCardKey *
132 111a38b0 Robert Relyea
vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
133 111a38b0 Robert Relyea
{
134 111a38b0 Robert Relyea
    VCardKey *key;
135 111a38b0 Robert Relyea
136 111a38b0 Robert Relyea
    key = (VCardKey *)qemu_malloc(sizeof(VCardKey));
137 111a38b0 Robert Relyea
    key->slot = PK11_ReferenceSlot(slot);
138 111a38b0 Robert Relyea
    key->cert = CERT_DupCertificate(cert);
139 111a38b0 Robert Relyea
    /* NOTE: if we aren't logged into the token, this could return NULL */
140 111a38b0 Robert Relyea
    /* NOTE: the cert is a temp cert, not necessarily the cert in the token,
141 111a38b0 Robert Relyea
     * use the DER version of this function */
142 111a38b0 Robert Relyea
    key->key = PK11_FindKeyByDERCert(slot, cert, NULL);
143 111a38b0 Robert Relyea
    return key;
144 111a38b0 Robert Relyea
}
145 111a38b0 Robert Relyea
146 111a38b0 Robert Relyea
/* destructor */
147 111a38b0 Robert Relyea
void
148 111a38b0 Robert Relyea
vcard_emul_delete_key(VCardKey *key)
149 111a38b0 Robert Relyea
{
150 111a38b0 Robert Relyea
    if (!nss_emul_init || (key == NULL)) {
151 111a38b0 Robert Relyea
        return;
152 111a38b0 Robert Relyea
    }
153 111a38b0 Robert Relyea
    if (key->key) {
154 111a38b0 Robert Relyea
        SECKEY_DestroyPrivateKey(key->key);
155 111a38b0 Robert Relyea
        key->key = NULL;
156 111a38b0 Robert Relyea
    }
157 111a38b0 Robert Relyea
    if (key->cert) {
158 111a38b0 Robert Relyea
        CERT_DestroyCertificate(key->cert);
159 111a38b0 Robert Relyea
    }
160 111a38b0 Robert Relyea
    if (key->slot) {
161 111a38b0 Robert Relyea
        PK11_FreeSlot(key->slot);
162 111a38b0 Robert Relyea
    }
163 111a38b0 Robert Relyea
    return;
164 111a38b0 Robert Relyea
}
165 111a38b0 Robert Relyea
166 111a38b0 Robert Relyea
/*
167 111a38b0 Robert Relyea
 * grab the nss key from a VCardKey. If it doesn't exist, try to look it up
168 111a38b0 Robert Relyea
 */
169 111a38b0 Robert Relyea
static SECKEYPrivateKey *
170 111a38b0 Robert Relyea
vcard_emul_get_nss_key(VCardKey *key)
171 111a38b0 Robert Relyea
{
172 111a38b0 Robert Relyea
    if (key->key) {
173 111a38b0 Robert Relyea
        return key->key;
174 111a38b0 Robert Relyea
    }
175 111a38b0 Robert Relyea
    /* NOTE: if we aren't logged into the token, this could return NULL */
176 111a38b0 Robert Relyea
    key->key = PK11_FindPrivateKeyFromCert(key->slot, key->cert, NULL);
177 111a38b0 Robert Relyea
    return key->key;
178 111a38b0 Robert Relyea
}
179 111a38b0 Robert Relyea
180 111a38b0 Robert Relyea
/*
181 111a38b0 Robert Relyea
 * Map NSS errors to 7816 errors
182 111a38b0 Robert Relyea
 */
183 111a38b0 Robert Relyea
static vcard_7816_status_t
184 111a38b0 Robert Relyea
vcard_emul_map_error(int error)
185 111a38b0 Robert Relyea
{
186 111a38b0 Robert Relyea
    switch (error) {
187 111a38b0 Robert Relyea
    case SEC_ERROR_TOKEN_NOT_LOGGED_IN:
188 111a38b0 Robert Relyea
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
189 111a38b0 Robert Relyea
    case SEC_ERROR_BAD_DATA:
190 111a38b0 Robert Relyea
    case SEC_ERROR_OUTPUT_LEN:
191 111a38b0 Robert Relyea
    case SEC_ERROR_INPUT_LEN:
192 111a38b0 Robert Relyea
    case SEC_ERROR_INVALID_ARGS:
193 111a38b0 Robert Relyea
    case SEC_ERROR_INVALID_ALGORITHM:
194 111a38b0 Robert Relyea
    case SEC_ERROR_NO_KEY:
195 111a38b0 Robert Relyea
    case SEC_ERROR_INVALID_KEY:
196 111a38b0 Robert Relyea
    case SEC_ERROR_DECRYPTION_DISALLOWED:
197 111a38b0 Robert Relyea
        return VCARD7816_STATUS_ERROR_DATA_INVALID;
198 111a38b0 Robert Relyea
    case SEC_ERROR_NO_MEMORY:
199 111a38b0 Robert Relyea
        return VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
200 111a38b0 Robert Relyea
    }
201 111a38b0 Robert Relyea
    return VCARD7816_STATUS_EXC_ERROR_CHANGE;
202 111a38b0 Robert Relyea
}
203 111a38b0 Robert Relyea
204 111a38b0 Robert Relyea
/* RSA sign/decrypt with the key, signature happens 'in place' */
205 111a38b0 Robert Relyea
vcard_7816_status_t
206 111a38b0 Robert Relyea
vcard_emul_rsa_op(VCard *card, VCardKey *key,
207 111a38b0 Robert Relyea
                  unsigned char *buffer, int buffer_size)
208 111a38b0 Robert Relyea
{
209 111a38b0 Robert Relyea
    SECKEYPrivateKey *priv_key;
210 111a38b0 Robert Relyea
    unsigned signature_len;
211 111a38b0 Robert Relyea
    SECStatus rv;
212 111a38b0 Robert Relyea
213 111a38b0 Robert Relyea
    if ((!nss_emul_init) || (key == NULL)) {
214 111a38b0 Robert Relyea
        /* couldn't get the key, indicate that we aren't logged in */
215 111a38b0 Robert Relyea
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
216 111a38b0 Robert Relyea
    }
217 111a38b0 Robert Relyea
    priv_key = vcard_emul_get_nss_key(key);
218 111a38b0 Robert Relyea
219 111a38b0 Robert Relyea
    /*
220 111a38b0 Robert Relyea
     * this is only true of the rsa signature
221 111a38b0 Robert Relyea
     */
222 111a38b0 Robert Relyea
    signature_len = PK11_SignatureLen(priv_key);
223 111a38b0 Robert Relyea
    if (buffer_size != signature_len) {
224 111a38b0 Robert Relyea
        return  VCARD7816_STATUS_ERROR_DATA_INVALID;
225 111a38b0 Robert Relyea
    }
226 111a38b0 Robert Relyea
    rv = PK11_PrivDecryptRaw(priv_key, buffer, &signature_len, signature_len,
227 111a38b0 Robert Relyea
                             buffer, buffer_size);
228 111a38b0 Robert Relyea
    if (rv != SECSuccess) {
229 111a38b0 Robert Relyea
        return vcard_emul_map_error(PORT_GetError());
230 111a38b0 Robert Relyea
    }
231 111a38b0 Robert Relyea
    assert(buffer_size == signature_len);
232 111a38b0 Robert Relyea
    return VCARD7816_STATUS_SUCCESS;
233 111a38b0 Robert Relyea
}
234 111a38b0 Robert Relyea
235 111a38b0 Robert Relyea
/*
236 111a38b0 Robert Relyea
 * Login functions
237 111a38b0 Robert Relyea
 */
238 111a38b0 Robert Relyea
/* return the number of login attempts still possible on the card. if unknown,
239 111a38b0 Robert Relyea
 * return -1 */
240 111a38b0 Robert Relyea
int
241 111a38b0 Robert Relyea
vcard_emul_get_login_count(VCard *card)
242 111a38b0 Robert Relyea
{
243 111a38b0 Robert Relyea
    return -1;
244 111a38b0 Robert Relyea
}
245 111a38b0 Robert Relyea
246 111a38b0 Robert Relyea
/* login into the card, return the 7816 status word (sw2 || sw1) */
247 111a38b0 Robert Relyea
vcard_7816_status_t
248 111a38b0 Robert Relyea
vcard_emul_login(VCard *card, unsigned char *pin, int pin_len)
249 111a38b0 Robert Relyea
{
250 111a38b0 Robert Relyea
    PK11SlotInfo *slot;
251 111a38b0 Robert Relyea
    unsigned char *pin_string = NULL;
252 111a38b0 Robert Relyea
    int i;
253 111a38b0 Robert Relyea
    SECStatus rv;
254 111a38b0 Robert Relyea
255 111a38b0 Robert Relyea
    if (!nss_emul_init) {
256 111a38b0 Robert Relyea
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
257 111a38b0 Robert Relyea
    }
258 111a38b0 Robert Relyea
    slot = vcard_emul_card_get_slot(card);
259 111a38b0 Robert Relyea
     /* We depend on the PKCS #11 module internal login state here because we
260 111a38b0 Robert Relyea
      * create a separate process to handle each guest instance. If we needed
261 111a38b0 Robert Relyea
      * to handle multiple guests from one process, then we would need to keep
262 111a38b0 Robert Relyea
      * a lot of extra state in our card structure
263 111a38b0 Robert Relyea
      * */
264 111a38b0 Robert Relyea
    pin_string = qemu_malloc(pin_len+1);
265 111a38b0 Robert Relyea
    memcpy(pin_string, pin, pin_len);
266 111a38b0 Robert Relyea
    pin_string[pin_len] = 0;
267 111a38b0 Robert Relyea
268 111a38b0 Robert Relyea
    /* handle CAC expanded pins correctly */
269 111a38b0 Robert Relyea
    for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) {
270 111a38b0 Robert Relyea
        pin_string[i] = 0;
271 111a38b0 Robert Relyea
    }
272 111a38b0 Robert Relyea
273 111a38b0 Robert Relyea
    rv = PK11_Authenticate(slot, PR_FALSE, pin_string);
274 111a38b0 Robert Relyea
    memset(pin_string, 0, pin_len);  /* don't let the pin hang around in memory
275 111a38b0 Robert Relyea
                                        to be snooped */
276 111a38b0 Robert Relyea
    qemu_free(pin_string);
277 111a38b0 Robert Relyea
    if (rv == SECSuccess) {
278 111a38b0 Robert Relyea
        return VCARD7816_STATUS_SUCCESS;
279 111a38b0 Robert Relyea
    }
280 111a38b0 Robert Relyea
    /* map the error from port get error */
281 111a38b0 Robert Relyea
    return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
282 111a38b0 Robert Relyea
}
283 111a38b0 Robert Relyea
284 111a38b0 Robert Relyea
void
285 111a38b0 Robert Relyea
vcard_emul_reset(VCard *card, VCardPower power)
286 111a38b0 Robert Relyea
{
287 111a38b0 Robert Relyea
    PK11SlotInfo *slot;
288 111a38b0 Robert Relyea
289 111a38b0 Robert Relyea
    if (!nss_emul_init) {
290 111a38b0 Robert Relyea
        return;
291 111a38b0 Robert Relyea
    }
292 111a38b0 Robert Relyea
293 111a38b0 Robert Relyea
    /*
294 111a38b0 Robert Relyea
     * if we reset the card (either power on or power off), we lose our login
295 111a38b0 Robert Relyea
     * state
296 111a38b0 Robert Relyea
     */
297 111a38b0 Robert Relyea
    /* TODO: we may also need to send insertion/removal events? */
298 111a38b0 Robert Relyea
    slot = vcard_emul_card_get_slot(card);
299 111a38b0 Robert Relyea
    PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
300 111a38b0 Robert Relyea
    return;
301 111a38b0 Robert Relyea
}
302 111a38b0 Robert Relyea
303 111a38b0 Robert Relyea
304 111a38b0 Robert Relyea
static VReader *
305 111a38b0 Robert Relyea
vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)
306 111a38b0 Robert Relyea
{
307 111a38b0 Robert Relyea
    VReaderList *reader_list = vreader_get_reader_list();
308 111a38b0 Robert Relyea
    VReaderListEntry *current_entry = NULL;
309 111a38b0 Robert Relyea
310 111a38b0 Robert Relyea
    if (reader_list == NULL) {
311 111a38b0 Robert Relyea
        return NULL;
312 111a38b0 Robert Relyea
    }
313 111a38b0 Robert Relyea
    for (current_entry = vreader_list_get_first(reader_list); current_entry;
314 111a38b0 Robert Relyea
                        current_entry = vreader_list_get_next(current_entry)) {
315 111a38b0 Robert Relyea
        VReader *reader = vreader_list_get_reader(current_entry);
316 111a38b0 Robert Relyea
        VReaderEmul *reader_emul = vreader_get_private(reader);
317 111a38b0 Robert Relyea
        if (reader_emul->slot == slot) {
318 111a38b0 Robert Relyea
            return reader;
319 111a38b0 Robert Relyea
        }
320 111a38b0 Robert Relyea
        vreader_free(reader);
321 111a38b0 Robert Relyea
    }
322 111a38b0 Robert Relyea
323 111a38b0 Robert Relyea
    return NULL;
324 111a38b0 Robert Relyea
}
325 111a38b0 Robert Relyea
326 111a38b0 Robert Relyea
/*
327 111a38b0 Robert Relyea
 * create a new reader emul
328 111a38b0 Robert Relyea
 */
329 111a38b0 Robert Relyea
static VReaderEmul *
330 111a38b0 Robert Relyea
vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params)
331 111a38b0 Robert Relyea
{
332 111a38b0 Robert Relyea
    VReaderEmul *new_reader_emul;
333 111a38b0 Robert Relyea
334 111a38b0 Robert Relyea
    new_reader_emul = (VReaderEmul *)qemu_malloc(sizeof(VReaderEmul));
335 111a38b0 Robert Relyea
336 111a38b0 Robert Relyea
    new_reader_emul->slot = PK11_ReferenceSlot(slot);
337 111a38b0 Robert Relyea
    new_reader_emul->default_type = type;
338 111a38b0 Robert Relyea
    new_reader_emul->type_params = strdup(params);
339 111a38b0 Robert Relyea
    new_reader_emul->present = PR_FALSE;
340 111a38b0 Robert Relyea
    new_reader_emul->series = 0;
341 111a38b0 Robert Relyea
    new_reader_emul->saved_vcard = NULL;
342 111a38b0 Robert Relyea
    return new_reader_emul;
343 111a38b0 Robert Relyea
}
344 111a38b0 Robert Relyea
345 111a38b0 Robert Relyea
static void
346 111a38b0 Robert Relyea
vreader_emul_delete(VReaderEmul *vreader_emul)
347 111a38b0 Robert Relyea
{
348 111a38b0 Robert Relyea
    if (vreader_emul == NULL) {
349 111a38b0 Robert Relyea
        return;
350 111a38b0 Robert Relyea
    }
351 111a38b0 Robert Relyea
    if (vreader_emul->slot) {
352 111a38b0 Robert Relyea
        PK11_FreeSlot(vreader_emul->slot);
353 111a38b0 Robert Relyea
    }
354 111a38b0 Robert Relyea
    if (vreader_emul->type_params) {
355 111a38b0 Robert Relyea
        qemu_free(vreader_emul->type_params);
356 111a38b0 Robert Relyea
    }
357 111a38b0 Robert Relyea
    qemu_free(vreader_emul);
358 111a38b0 Robert Relyea
}
359 111a38b0 Robert Relyea
360 111a38b0 Robert Relyea
/*
361 111a38b0 Robert Relyea
 *  TODO: move this to emulater non-specific file
362 111a38b0 Robert Relyea
 */
363 111a38b0 Robert Relyea
static VCardEmulType
364 111a38b0 Robert Relyea
vcard_emul_get_type(VReader *vreader)
365 111a38b0 Robert Relyea
{
366 111a38b0 Robert Relyea
    VReaderEmul *vreader_emul;
367 111a38b0 Robert Relyea
368 111a38b0 Robert Relyea
    vreader_emul = vreader_get_private(vreader);
369 111a38b0 Robert Relyea
    if (vreader_emul && vreader_emul->default_type != VCARD_EMUL_NONE) {
370 111a38b0 Robert Relyea
        return vreader_emul->default_type;
371 111a38b0 Robert Relyea
    }
372 111a38b0 Robert Relyea
373 111a38b0 Robert Relyea
    return vcard_emul_type_select(vreader);
374 111a38b0 Robert Relyea
}
375 111a38b0 Robert Relyea
/*
376 111a38b0 Robert Relyea
 *  TODO: move this to emulater non-specific file
377 111a38b0 Robert Relyea
 */
378 111a38b0 Robert Relyea
static const char *
379 111a38b0 Robert Relyea
vcard_emul_get_type_params(VReader *vreader)
380 111a38b0 Robert Relyea
{
381 111a38b0 Robert Relyea
    VReaderEmul *vreader_emul;
382 111a38b0 Robert Relyea
383 111a38b0 Robert Relyea
    vreader_emul = vreader_get_private(vreader);
384 111a38b0 Robert Relyea
    if (vreader_emul && vreader_emul->type_params) {
385 111a38b0 Robert Relyea
        return vreader_emul->type_params;
386 111a38b0 Robert Relyea
    }
387 111a38b0 Robert Relyea
388 111a38b0 Robert Relyea
    return "";
389 111a38b0 Robert Relyea
}
390 111a38b0 Robert Relyea
391 111a38b0 Robert Relyea
/* pull the slot out of the reader private data */
392 111a38b0 Robert Relyea
static PK11SlotInfo *
393 111a38b0 Robert Relyea
vcard_emul_reader_get_slot(VReader *vreader)
394 111a38b0 Robert Relyea
{
395 111a38b0 Robert Relyea
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
396 111a38b0 Robert Relyea
    if (vreader_emul == NULL) {
397 111a38b0 Robert Relyea
        return NULL;
398 111a38b0 Robert Relyea
    }
399 111a38b0 Robert Relyea
    return vreader_emul->slot;
400 111a38b0 Robert Relyea
}
401 111a38b0 Robert Relyea
402 111a38b0 Robert Relyea
/*
403 111a38b0 Robert Relyea
 *  Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate
404 111a38b0 Robert Relyea
 *  historical bytes for any software emulated card. The remaining bytes can be
405 111a38b0 Robert Relyea
 *  used to indicate the actual emulator
406 111a38b0 Robert Relyea
 */
407 111a38b0 Robert Relyea
static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' };
408 111a38b0 Robert Relyea
409 111a38b0 Robert Relyea
void
410 111a38b0 Robert Relyea
vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
411 111a38b0 Robert Relyea
{
412 111a38b0 Robert Relyea
    int len = MIN(sizeof(nss_atr), *atr_len);
413 111a38b0 Robert Relyea
    assert(atr != NULL);
414 111a38b0 Robert Relyea
415 111a38b0 Robert Relyea
    memcpy(atr, nss_atr, len);
416 111a38b0 Robert Relyea
    *atr_len = len;
417 111a38b0 Robert Relyea
    return;
418 111a38b0 Robert Relyea
}
419 111a38b0 Robert Relyea
420 111a38b0 Robert Relyea
/*
421 111a38b0 Robert Relyea
 * create a new card from certs and keys
422 111a38b0 Robert Relyea
 */
423 111a38b0 Robert Relyea
static VCard *
424 111a38b0 Robert Relyea
vcard_emul_make_card(VReader *reader,
425 111a38b0 Robert Relyea
                     unsigned char * const *certs, int *cert_len,
426 111a38b0 Robert Relyea
                     VCardKey *keys[], int cert_count)
427 111a38b0 Robert Relyea
{
428 111a38b0 Robert Relyea
    VCardEmul *vcard_emul;
429 111a38b0 Robert Relyea
    VCard *vcard;
430 111a38b0 Robert Relyea
    PK11SlotInfo *slot;
431 111a38b0 Robert Relyea
    VCardEmulType type;
432 111a38b0 Robert Relyea
    const char *params;
433 111a38b0 Robert Relyea
434 111a38b0 Robert Relyea
    type = vcard_emul_get_type(reader);
435 111a38b0 Robert Relyea
436 111a38b0 Robert Relyea
    /* ignore the inserted card */
437 111a38b0 Robert Relyea
    if (type == VCARD_EMUL_NONE) {
438 111a38b0 Robert Relyea
        return NULL;
439 111a38b0 Robert Relyea
    }
440 111a38b0 Robert Relyea
    slot = vcard_emul_reader_get_slot(reader);
441 111a38b0 Robert Relyea
    if (slot == NULL) {
442 111a38b0 Robert Relyea
        return NULL;
443 111a38b0 Robert Relyea
    }
444 111a38b0 Robert Relyea
445 111a38b0 Robert Relyea
    params = vcard_emul_get_type_params(reader);
446 111a38b0 Robert Relyea
    /* params these can be NULL */
447 111a38b0 Robert Relyea
448 111a38b0 Robert Relyea
    vcard_emul = vcard_emul_new_card(slot);
449 111a38b0 Robert Relyea
    if (vcard_emul == NULL) {
450 111a38b0 Robert Relyea
        return NULL;
451 111a38b0 Robert Relyea
    }
452 111a38b0 Robert Relyea
    vcard = vcard_new(vcard_emul, vcard_emul_delete_card);
453 111a38b0 Robert Relyea
    if (vcard == NULL) {
454 111a38b0 Robert Relyea
        vcard_emul_delete_card(vcard_emul);
455 111a38b0 Robert Relyea
        return NULL;
456 111a38b0 Robert Relyea
    }
457 111a38b0 Robert Relyea
    vcard_init(reader, vcard, type, params, certs, cert_len, keys, cert_count);
458 111a38b0 Robert Relyea
    return vcard;
459 111a38b0 Robert Relyea
}
460 111a38b0 Robert Relyea
461 111a38b0 Robert Relyea
462 111a38b0 Robert Relyea
/*
463 111a38b0 Robert Relyea
 * 'clone' a physical card as a virtual card
464 111a38b0 Robert Relyea
 */
465 111a38b0 Robert Relyea
static VCard *
466 111a38b0 Robert Relyea
vcard_emul_mirror_card(VReader *vreader)
467 111a38b0 Robert Relyea
{
468 111a38b0 Robert Relyea
    /*
469 111a38b0 Robert Relyea
     * lookup certs using the C_FindObjects. The Stan Cert handle won't give
470 111a38b0 Robert Relyea
     * us the real certs until we log in.
471 111a38b0 Robert Relyea
     */
472 111a38b0 Robert Relyea
    PK11GenericObject *firstObj, *thisObj;
473 111a38b0 Robert Relyea
    int cert_count;
474 111a38b0 Robert Relyea
    unsigned char **certs;
475 111a38b0 Robert Relyea
    int *cert_len;
476 111a38b0 Robert Relyea
    VCardKey **keys;
477 111a38b0 Robert Relyea
    PK11SlotInfo *slot;
478 111a38b0 Robert Relyea
    PRBool ret;
479 111a38b0 Robert Relyea
480 111a38b0 Robert Relyea
    slot = vcard_emul_reader_get_slot(vreader);
481 111a38b0 Robert Relyea
    if (slot == NULL) {
482 111a38b0 Robert Relyea
        return NULL;
483 111a38b0 Robert Relyea
    }
484 111a38b0 Robert Relyea
485 111a38b0 Robert Relyea
    firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
486 111a38b0 Robert Relyea
    if (firstObj == NULL) {
487 111a38b0 Robert Relyea
        return NULL;
488 111a38b0 Robert Relyea
    }
489 111a38b0 Robert Relyea
490 111a38b0 Robert Relyea
    /* count the certs */
491 111a38b0 Robert Relyea
    cert_count = 0;
492 111a38b0 Robert Relyea
    for (thisObj = firstObj; thisObj;
493 111a38b0 Robert Relyea
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
494 111a38b0 Robert Relyea
        cert_count++;
495 111a38b0 Robert Relyea
    }
496 111a38b0 Robert Relyea
497 111a38b0 Robert Relyea
    if (cert_count == 0) {
498 111a38b0 Robert Relyea
        PK11_DestroyGenericObjects(firstObj);
499 111a38b0 Robert Relyea
        return NULL;
500 111a38b0 Robert Relyea
    }
501 111a38b0 Robert Relyea
502 111a38b0 Robert Relyea
    /* allocate the arrays */
503 111a38b0 Robert Relyea
    ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
504 111a38b0 Robert Relyea
    if (ret == PR_FALSE) {
505 111a38b0 Robert Relyea
        return NULL;
506 111a38b0 Robert Relyea
    }
507 111a38b0 Robert Relyea
508 111a38b0 Robert Relyea
    /* fill in the arrays */
509 111a38b0 Robert Relyea
    cert_count = 0;
510 111a38b0 Robert Relyea
    for (thisObj = firstObj; thisObj;
511 111a38b0 Robert Relyea
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
512 111a38b0 Robert Relyea
        SECItem derCert;
513 111a38b0 Robert Relyea
        CERTCertificate *cert;
514 111a38b0 Robert Relyea
        SECStatus rv;
515 111a38b0 Robert Relyea
516 111a38b0 Robert Relyea
        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
517 111a38b0 Robert Relyea
                                   CKA_VALUE, &derCert);
518 111a38b0 Robert Relyea
        if (rv != SECSuccess) {
519 111a38b0 Robert Relyea
            continue;
520 111a38b0 Robert Relyea
        }
521 111a38b0 Robert Relyea
        /* create floating temp cert. This gives us a cert structure even if
522 111a38b0 Robert Relyea
         * the token isn't logged in */
523 111a38b0 Robert Relyea
        cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
524 111a38b0 Robert Relyea
                                       NULL, PR_FALSE, PR_TRUE);
525 111a38b0 Robert Relyea
        SECITEM_FreeItem(&derCert, PR_FALSE);
526 111a38b0 Robert Relyea
        if (cert == NULL) {
527 111a38b0 Robert Relyea
            continue;
528 111a38b0 Robert Relyea
        }
529 111a38b0 Robert Relyea
530 111a38b0 Robert Relyea
        certs[cert_count] = cert->derCert.data;
531 111a38b0 Robert Relyea
        cert_len[cert_count] = cert->derCert.len;
532 111a38b0 Robert Relyea
        keys[cert_count] = vcard_emul_make_key(slot, cert);
533 111a38b0 Robert Relyea
        cert_count++;
534 111a38b0 Robert Relyea
        CERT_DestroyCertificate(cert); /* key obj still has a reference */
535 111a38b0 Robert Relyea
    }
536 111a38b0 Robert Relyea
537 111a38b0 Robert Relyea
    /* now create the card */
538 111a38b0 Robert Relyea
    return vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
539 111a38b0 Robert Relyea
}
540 111a38b0 Robert Relyea
541 111a38b0 Robert Relyea
static VCardEmulType default_card_type = VCARD_EMUL_NONE;
542 111a38b0 Robert Relyea
static const char *default_type_params = "";
543 111a38b0 Robert Relyea
544 111a38b0 Robert Relyea
/*
545 111a38b0 Robert Relyea
 * This thread looks for card and reader insertions and puts events on the
546 111a38b0 Robert Relyea
 * event queue
547 111a38b0 Robert Relyea
 */
548 111a38b0 Robert Relyea
static void
549 111a38b0 Robert Relyea
vcard_emul_event_thread(void *arg)
550 111a38b0 Robert Relyea
{
551 111a38b0 Robert Relyea
    PK11SlotInfo *slot;
552 111a38b0 Robert Relyea
    VReader *vreader;
553 111a38b0 Robert Relyea
    VReaderEmul *vreader_emul;
554 111a38b0 Robert Relyea
    VCard *vcard;
555 111a38b0 Robert Relyea
    SECMODModule *module = (SECMODModule *)arg;
556 111a38b0 Robert Relyea
557 111a38b0 Robert Relyea
    do {
558 111a38b0 Robert Relyea
        slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
559 111a38b0 Robert Relyea
        if (slot == NULL) {
560 111a38b0 Robert Relyea
            break;
561 111a38b0 Robert Relyea
        }
562 111a38b0 Robert Relyea
        vreader = vcard_emul_find_vreader_from_slot(slot);
563 111a38b0 Robert Relyea
        if (vreader == NULL) {
564 111a38b0 Robert Relyea
            /* new vreader */
565 111a38b0 Robert Relyea
            vreader_emul = vreader_emul_new(slot, default_card_type,
566 111a38b0 Robert Relyea
                                            default_type_params);
567 111a38b0 Robert Relyea
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
568 111a38b0 Robert Relyea
                                  vreader_emul_delete);
569 111a38b0 Robert Relyea
            PK11_FreeSlot(slot);
570 111a38b0 Robert Relyea
            slot = NULL;
571 111a38b0 Robert Relyea
            vreader_add_reader(vreader);
572 111a38b0 Robert Relyea
            vreader_free(vreader);
573 111a38b0 Robert Relyea
            continue;
574 111a38b0 Robert Relyea
        }
575 111a38b0 Robert Relyea
        /* card remove/insert */
576 111a38b0 Robert Relyea
        vreader_emul = vreader_get_private(vreader);
577 111a38b0 Robert Relyea
        if (PK11_IsPresent(slot)) {
578 111a38b0 Robert Relyea
            int series = PK11_GetSlotSeries(slot);
579 111a38b0 Robert Relyea
            if (series != vreader_emul->series) {
580 111a38b0 Robert Relyea
                if (vreader_emul->present) {
581 111a38b0 Robert Relyea
                    vreader_insert_card(vreader, NULL);
582 111a38b0 Robert Relyea
                }
583 111a38b0 Robert Relyea
                vcard = vcard_emul_mirror_card(vreader);
584 111a38b0 Robert Relyea
                vreader_insert_card(vreader, vcard);
585 111a38b0 Robert Relyea
                vcard_free(vcard);
586 111a38b0 Robert Relyea
            }
587 111a38b0 Robert Relyea
            vreader_emul->series = series;
588 111a38b0 Robert Relyea
            vreader_emul->present = 1;
589 111a38b0 Robert Relyea
            vreader_free(vreader);
590 111a38b0 Robert Relyea
            PK11_FreeSlot(slot);
591 111a38b0 Robert Relyea
            continue;
592 111a38b0 Robert Relyea
        }
593 111a38b0 Robert Relyea
        if (vreader_emul->present) {
594 111a38b0 Robert Relyea
            vreader_insert_card(vreader, NULL);
595 111a38b0 Robert Relyea
        }
596 111a38b0 Robert Relyea
        vreader_emul->series = 0;
597 111a38b0 Robert Relyea
        vreader_emul->present = 0;
598 111a38b0 Robert Relyea
        PK11_FreeSlot(slot);
599 111a38b0 Robert Relyea
        vreader_free(vreader);
600 111a38b0 Robert Relyea
    } while (1);
601 111a38b0 Robert Relyea
}
602 111a38b0 Robert Relyea
603 111a38b0 Robert Relyea
/* if the card is inserted when we start up, make sure our state is correct */
604 111a38b0 Robert Relyea
static void
605 111a38b0 Robert Relyea
vcard_emul_init_series(VReader *vreader, VCard *vcard)
606 111a38b0 Robert Relyea
{
607 111a38b0 Robert Relyea
    VReaderEmul *vreader_emul = vreader_get_private(vreader);
608 111a38b0 Robert Relyea
    PK11SlotInfo *slot = vreader_emul->slot;
609 111a38b0 Robert Relyea
610 111a38b0 Robert Relyea
    vreader_emul->present = PK11_IsPresent(slot);
611 111a38b0 Robert Relyea
    vreader_emul->series = PK11_GetSlotSeries(slot);
612 111a38b0 Robert Relyea
    if (vreader_emul->present == 0) {
613 111a38b0 Robert Relyea
        vreader_insert_card(vreader, NULL);
614 111a38b0 Robert Relyea
    }
615 111a38b0 Robert Relyea
}
616 111a38b0 Robert Relyea
617 111a38b0 Robert Relyea
/*
618 111a38b0 Robert Relyea
 * each module has a separate wait call, create a thread for each module that
619 111a38b0 Robert Relyea
 * we are using.
620 111a38b0 Robert Relyea
 */
621 111a38b0 Robert Relyea
static void
622 111a38b0 Robert Relyea
vcard_emul_new_event_thread(SECMODModule *module)
623 111a38b0 Robert Relyea
{
624 111a38b0 Robert Relyea
    PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
625 111a38b0 Robert Relyea
                     module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
626 111a38b0 Robert Relyea
                     PR_UNJOINABLE_THREAD, 0);
627 111a38b0 Robert Relyea
}
628 111a38b0 Robert Relyea
629 111a38b0 Robert Relyea
static const VCardEmulOptions default_options = {
630 111a38b0 Robert Relyea
    .nss_db = NULL,
631 111a38b0 Robert Relyea
    .vreader = NULL,
632 111a38b0 Robert Relyea
    .vreader_count = 0,
633 111a38b0 Robert Relyea
    .hw_card_type = VCARD_EMUL_CAC,
634 111a38b0 Robert Relyea
    .hw_type_params = "",
635 111a38b0 Robert Relyea
    .use_hw = PR_TRUE
636 111a38b0 Robert Relyea
};
637 111a38b0 Robert Relyea
638 111a38b0 Robert Relyea
639 111a38b0 Robert Relyea
/*
640 111a38b0 Robert Relyea
 *  NSS needs the app to supply a password prompt. In our case the only time
641 111a38b0 Robert Relyea
 *  the password is supplied is as part of the Login APDU. The actual password
642 111a38b0 Robert Relyea
 *  is passed in the pw_arg in that case. In all other cases pw_arg should be
643 111a38b0 Robert Relyea
 *  NULL.
644 111a38b0 Robert Relyea
 */
645 111a38b0 Robert Relyea
static char *
646 111a38b0 Robert Relyea
vcard_emul_get_password(PK11SlotInfo *slot, PRBool retries, void *pw_arg)
647 111a38b0 Robert Relyea
{
648 111a38b0 Robert Relyea
    /* if it didn't work the first time, don't keep trying */
649 111a38b0 Robert Relyea
    if (retries) {
650 111a38b0 Robert Relyea
        return NULL;
651 111a38b0 Robert Relyea
    }
652 111a38b0 Robert Relyea
    /* we are looking up a password when we don't have one in hand */
653 111a38b0 Robert Relyea
    if (pw_arg == NULL) {
654 111a38b0 Robert Relyea
        return NULL;
655 111a38b0 Robert Relyea
    }
656 111a38b0 Robert Relyea
    /* TODO: we really should verify that were are using the right slot */
657 111a38b0 Robert Relyea
    return PORT_Strdup(pw_arg);
658 111a38b0 Robert Relyea
}
659 111a38b0 Robert Relyea
660 111a38b0 Robert Relyea
/* Force a card removal even if the card is not physically removed */
661 111a38b0 Robert Relyea
VCardEmulError
662 111a38b0 Robert Relyea
vcard_emul_force_card_remove(VReader *vreader)
663 111a38b0 Robert Relyea
{
664 111a38b0 Robert Relyea
    if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
665 111a38b0 Robert Relyea
        return VCARD_EMUL_FAIL; /* card is already removed */
666 111a38b0 Robert Relyea
    }
667 111a38b0 Robert Relyea
668 111a38b0 Robert Relyea
    /* OK, remove it */
669 111a38b0 Robert Relyea
    vreader_insert_card(vreader, NULL);
670 111a38b0 Robert Relyea
    return VCARD_EMUL_OK;
671 111a38b0 Robert Relyea
}
672 111a38b0 Robert Relyea
673 111a38b0 Robert Relyea
/* Re-insert of a card that has been removed by force removal */
674 111a38b0 Robert Relyea
VCardEmulError
675 111a38b0 Robert Relyea
vcard_emul_force_card_insert(VReader *vreader)
676 111a38b0 Robert Relyea
{
677 111a38b0 Robert Relyea
    VReaderEmul *vreader_emul;
678 111a38b0 Robert Relyea
    VCard *vcard;
679 111a38b0 Robert Relyea
680 111a38b0 Robert Relyea
    if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
681 111a38b0 Robert Relyea
        return VCARD_EMUL_FAIL; /* card is already removed */
682 111a38b0 Robert Relyea
    }
683 111a38b0 Robert Relyea
    vreader_emul = vreader_get_private(vreader);
684 111a38b0 Robert Relyea
685 111a38b0 Robert Relyea
    /* if it's a softcard, get the saved vcard from the reader emul structure */
686 111a38b0 Robert Relyea
    if (vreader_emul->saved_vcard) {
687 111a38b0 Robert Relyea
        vcard = vcard_reference(vreader_emul->saved_vcard);
688 111a38b0 Robert Relyea
    } else {
689 111a38b0 Robert Relyea
        /* it must be a physical card, rebuild it */
690 111a38b0 Robert Relyea
        if (!PK11_IsPresent(vreader_emul->slot)) {
691 111a38b0 Robert Relyea
            /* physical card has been removed, not way to reinsert it */
692 111a38b0 Robert Relyea
            return VCARD_EMUL_FAIL;
693 111a38b0 Robert Relyea
        }
694 111a38b0 Robert Relyea
        vcard = vcard_emul_mirror_card(vreader);
695 111a38b0 Robert Relyea
    }
696 111a38b0 Robert Relyea
    vreader_insert_card(vreader, vcard);
697 111a38b0 Robert Relyea
    vcard_free(vcard);
698 111a38b0 Robert Relyea
699 111a38b0 Robert Relyea
    return VCARD_EMUL_OK;
700 111a38b0 Robert Relyea
}
701 111a38b0 Robert Relyea
702 111a38b0 Robert Relyea
703 111a38b0 Robert Relyea
static PRBool
704 111a38b0 Robert Relyea
module_has_removable_hw_slots(SECMODModule *mod)
705 111a38b0 Robert Relyea
{
706 111a38b0 Robert Relyea
    int i;
707 111a38b0 Robert Relyea
    PRBool ret = PR_FALSE;
708 111a38b0 Robert Relyea
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
709 111a38b0 Robert Relyea
710 111a38b0 Robert Relyea
    if (!moduleLock) {
711 111a38b0 Robert Relyea
        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
712 111a38b0 Robert Relyea
        return ret;
713 111a38b0 Robert Relyea
    }
714 111a38b0 Robert Relyea
    SECMOD_GetReadLock(moduleLock);
715 111a38b0 Robert Relyea
    for (i = 0; i < mod->slotCount; i++) {
716 111a38b0 Robert Relyea
        PK11SlotInfo *slot = mod->slots[i];
717 111a38b0 Robert Relyea
        if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) {
718 111a38b0 Robert Relyea
            ret = PR_TRUE;
719 111a38b0 Robert Relyea
            break;
720 111a38b0 Robert Relyea
        }
721 111a38b0 Robert Relyea
    }
722 111a38b0 Robert Relyea
    SECMOD_ReleaseReadLock(moduleLock);
723 111a38b0 Robert Relyea
    return ret;
724 111a38b0 Robert Relyea
}
725 111a38b0 Robert Relyea
726 111a38b0 Robert Relyea
/* Previously we returned FAIL if no readers found. This makes
727 111a38b0 Robert Relyea
 * no sense when using hardware, since there may be no readers connected
728 111a38b0 Robert Relyea
 * at the time vcard_emul_init is called, but they will be properly
729 111a38b0 Robert Relyea
 * recognized later. So Instead return FAIL only if no_hw==1 and no
730 111a38b0 Robert Relyea
 * vcards can be created (indicates error with certificates provided
731 111a38b0 Robert Relyea
 * or db), or if any other higher level error (NSS error, missing coolkey). */
732 111a38b0 Robert Relyea
static int vcard_emul_init_called;
733 111a38b0 Robert Relyea
734 111a38b0 Robert Relyea
VCardEmulError
735 111a38b0 Robert Relyea
vcard_emul_init(const VCardEmulOptions *options)
736 111a38b0 Robert Relyea
{
737 111a38b0 Robert Relyea
    SECStatus rv;
738 111a38b0 Robert Relyea
    PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
739 111a38b0 Robert Relyea
    VReader *vreader;
740 111a38b0 Robert Relyea
    VReaderEmul *vreader_emul;
741 111a38b0 Robert Relyea
    SECMODListLock *module_lock;
742 111a38b0 Robert Relyea
    SECMODModuleList *module_list;
743 111a38b0 Robert Relyea
    SECMODModuleList *mlp;
744 111a38b0 Robert Relyea
    int i;
745 111a38b0 Robert Relyea
746 111a38b0 Robert Relyea
    if (vcard_emul_init_called) {
747 111a38b0 Robert Relyea
        return VCARD_EMUL_INIT_ALREADY_INITED;
748 111a38b0 Robert Relyea
    }
749 111a38b0 Robert Relyea
    vcard_emul_init_called = 1;
750 111a38b0 Robert Relyea
    vreader_init();
751 111a38b0 Robert Relyea
    vevent_queue_init();
752 111a38b0 Robert Relyea
753 111a38b0 Robert Relyea
    if (options == NULL) {
754 111a38b0 Robert Relyea
        options = &default_options;
755 111a38b0 Robert Relyea
    }
756 111a38b0 Robert Relyea
757 111a38b0 Robert Relyea
    /* first initialize NSS */
758 111a38b0 Robert Relyea
    if (options->nss_db) {
759 111a38b0 Robert Relyea
        rv = NSS_Init(options->nss_db);
760 111a38b0 Robert Relyea
    } else {
761 111a38b0 Robert Relyea
        rv = NSS_Init("sql:/etc/pki/nssdb");
762 111a38b0 Robert Relyea
    }
763 111a38b0 Robert Relyea
    if (rv != SECSuccess) {
764 111a38b0 Robert Relyea
        return VCARD_EMUL_FAIL;
765 111a38b0 Robert Relyea
    }
766 111a38b0 Robert Relyea
    /* Set password callback function */
767 111a38b0 Robert Relyea
    PK11_SetPasswordFunc(vcard_emul_get_password);
768 111a38b0 Robert Relyea
769 111a38b0 Robert Relyea
    /* set up soft cards emulated by software certs rather than physical cards
770 111a38b0 Robert Relyea
     * */
771 111a38b0 Robert Relyea
    for (i = 0; i < options->vreader_count; i++) {
772 111a38b0 Robert Relyea
        int j;
773 111a38b0 Robert Relyea
        int cert_count;
774 111a38b0 Robert Relyea
        unsigned char **certs;
775 111a38b0 Robert Relyea
        int *cert_len;
776 111a38b0 Robert Relyea
        VCardKey **keys;
777 111a38b0 Robert Relyea
        PK11SlotInfo *slot;
778 111a38b0 Robert Relyea
779 111a38b0 Robert Relyea
        slot = PK11_FindSlotByName(options->vreader[i].name);
780 111a38b0 Robert Relyea
        if (slot == NULL) {
781 111a38b0 Robert Relyea
            continue;
782 111a38b0 Robert Relyea
        }
783 111a38b0 Robert Relyea
        vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
784 111a38b0 Robert Relyea
                                        options->vreader[i].type_params);
785 111a38b0 Robert Relyea
        vreader = vreader_new(options->vreader[i].vname, vreader_emul,
786 111a38b0 Robert Relyea
                              vreader_emul_delete);
787 111a38b0 Robert Relyea
        vreader_add_reader(vreader);
788 111a38b0 Robert Relyea
        cert_count = options->vreader[i].cert_count;
789 111a38b0 Robert Relyea
790 111a38b0 Robert Relyea
        ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
791 111a38b0 Robert Relyea
                                      options->vreader[i].cert_count);
792 111a38b0 Robert Relyea
        if (ret == PR_FALSE) {
793 111a38b0 Robert Relyea
            continue;
794 111a38b0 Robert Relyea
        }
795 111a38b0 Robert Relyea
        cert_count = 0;
796 111a38b0 Robert Relyea
        for (j = 0; j < options->vreader[i].cert_count; j++) {
797 111a38b0 Robert Relyea
            /* we should have a better way of identifying certs than by
798 111a38b0 Robert Relyea
             * nickname here */
799 111a38b0 Robert Relyea
            CERTCertificate *cert = PK11_FindCertFromNickname(
800 111a38b0 Robert Relyea
                                        options->vreader[i].cert_name[j],
801 111a38b0 Robert Relyea
                                        NULL);
802 111a38b0 Robert Relyea
            if (cert == NULL) {
803 111a38b0 Robert Relyea
                continue;
804 111a38b0 Robert Relyea
            }
805 111a38b0 Robert Relyea
            certs[cert_count] = cert->derCert.data;
806 111a38b0 Robert Relyea
            cert_len[cert_count] = cert->derCert.len;
807 111a38b0 Robert Relyea
            keys[cert_count] = vcard_emul_make_key(slot, cert);
808 111a38b0 Robert Relyea
            /* this is safe because the key is still holding a cert reference */
809 111a38b0 Robert Relyea
            CERT_DestroyCertificate(cert);
810 111a38b0 Robert Relyea
            cert_count++;
811 111a38b0 Robert Relyea
        }
812 111a38b0 Robert Relyea
        if (cert_count) {
813 111a38b0 Robert Relyea
            VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len,
814 111a38b0 Robert Relyea
                                                keys, cert_count);
815 111a38b0 Robert Relyea
            vreader_insert_card(vreader, vcard);
816 111a38b0 Robert Relyea
            vcard_emul_init_series(vreader, vcard);
817 111a38b0 Robert Relyea
            /* allow insertion and removal of soft cards */
818 111a38b0 Robert Relyea
            vreader_emul->saved_vcard = vcard_reference(vcard);
819 111a38b0 Robert Relyea
            vcard_free(vcard);
820 111a38b0 Robert Relyea
            vreader_free(vreader);
821 111a38b0 Robert Relyea
            has_readers = PR_TRUE;
822 111a38b0 Robert Relyea
        }
823 111a38b0 Robert Relyea
    }
824 111a38b0 Robert Relyea
825 111a38b0 Robert Relyea
    /* if we aren't suppose to use hw, skip looking up hardware tokens */
826 111a38b0 Robert Relyea
    if (!options->use_hw) {
827 111a38b0 Robert Relyea
        nss_emul_init = has_readers;
828 111a38b0 Robert Relyea
        return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
829 111a38b0 Robert Relyea
    }
830 111a38b0 Robert Relyea
831 111a38b0 Robert Relyea
    /* make sure we have some PKCS #11 module loaded */
832 111a38b0 Robert Relyea
    module_lock = SECMOD_GetDefaultModuleListLock();
833 111a38b0 Robert Relyea
    module_list = SECMOD_GetDefaultModuleList();
834 111a38b0 Robert Relyea
    need_coolkey_module = !has_readers;
835 111a38b0 Robert Relyea
    SECMOD_GetReadLock(module_lock);
836 111a38b0 Robert Relyea
    for (mlp = module_list; mlp; mlp = mlp->next) {
837 111a38b0 Robert Relyea
        SECMODModule *module = mlp->module;
838 111a38b0 Robert Relyea
        if (module_has_removable_hw_slots(module)) {
839 111a38b0 Robert Relyea
            need_coolkey_module = PR_FALSE;
840 111a38b0 Robert Relyea
            break;
841 111a38b0 Robert Relyea
        }
842 111a38b0 Robert Relyea
    }
843 111a38b0 Robert Relyea
    SECMOD_ReleaseReadLock(module_lock);
844 111a38b0 Robert Relyea
845 111a38b0 Robert Relyea
    if (need_coolkey_module) {
846 111a38b0 Robert Relyea
        SECMODModule *module;
847 111a38b0 Robert Relyea
        module = SECMOD_LoadUserModule(
848 111a38b0 Robert Relyea
                    (char *)"library=libcoolkeypk11.so name=Coolkey",
849 111a38b0 Robert Relyea
                    NULL, PR_FALSE);
850 111a38b0 Robert Relyea
        if (module == NULL) {
851 111a38b0 Robert Relyea
            return VCARD_EMUL_FAIL;
852 111a38b0 Robert Relyea
        }
853 111a38b0 Robert Relyea
        SECMOD_DestroyModule(module); /* free our reference, Module will still
854 111a38b0 Robert Relyea
                                       * be on the list.
855 111a38b0 Robert Relyea
                                       * until we destroy it */
856 111a38b0 Robert Relyea
    }
857 111a38b0 Robert Relyea
858 111a38b0 Robert Relyea
    /* now examine all the slots, finding which should be readers */
859 111a38b0 Robert Relyea
    /* We should control this with options. For now we mirror out any
860 111a38b0 Robert Relyea
     * removable hardware slot */
861 111a38b0 Robert Relyea
    default_card_type = options->hw_card_type;
862 111a38b0 Robert Relyea
    default_type_params = strdup(options->hw_type_params);
863 111a38b0 Robert Relyea
864 111a38b0 Robert Relyea
    SECMOD_GetReadLock(module_lock);
865 111a38b0 Robert Relyea
    for (mlp = module_list; mlp; mlp = mlp->next) {
866 111a38b0 Robert Relyea
        SECMODModule *module = mlp->module;
867 111a38b0 Robert Relyea
        PRBool has_emul_slots = PR_FALSE;
868 111a38b0 Robert Relyea
869 111a38b0 Robert Relyea
        if (module == NULL) {
870 111a38b0 Robert Relyea
                continue;
871 111a38b0 Robert Relyea
        }
872 111a38b0 Robert Relyea
873 111a38b0 Robert Relyea
        for (i = 0; i < module->slotCount; i++) {
874 111a38b0 Robert Relyea
            PK11SlotInfo *slot = module->slots[i];
875 111a38b0 Robert Relyea
876 111a38b0 Robert Relyea
            /* only map removable HW slots */
877 111a38b0 Robert Relyea
            if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
878 111a38b0 Robert Relyea
                continue;
879 111a38b0 Robert Relyea
            }
880 111a38b0 Robert Relyea
            vreader_emul = vreader_emul_new(slot, options->hw_card_type,
881 111a38b0 Robert Relyea
                                            options->hw_type_params);
882 111a38b0 Robert Relyea
            vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
883 111a38b0 Robert Relyea
                                  vreader_emul_delete);
884 111a38b0 Robert Relyea
            vreader_add_reader(vreader);
885 111a38b0 Robert Relyea
886 111a38b0 Robert Relyea
            has_readers = PR_TRUE;
887 111a38b0 Robert Relyea
            has_emul_slots = PR_TRUE;
888 111a38b0 Robert Relyea
889 111a38b0 Robert Relyea
            if (PK11_IsPresent(slot)) {
890 111a38b0 Robert Relyea
                VCard *vcard;
891 111a38b0 Robert Relyea
                vcard = vcard_emul_mirror_card(vreader);
892 111a38b0 Robert Relyea
                vreader_insert_card(vreader, vcard);
893 111a38b0 Robert Relyea
                vcard_emul_init_series(vreader, vcard);
894 111a38b0 Robert Relyea
                vcard_free(vcard);
895 111a38b0 Robert Relyea
            }
896 111a38b0 Robert Relyea
        }
897 111a38b0 Robert Relyea
        if (has_emul_slots) {
898 111a38b0 Robert Relyea
            vcard_emul_new_event_thread(module);
899 111a38b0 Robert Relyea
        }
900 111a38b0 Robert Relyea
    }
901 111a38b0 Robert Relyea
    SECMOD_ReleaseReadLock(module_lock);
902 111a38b0 Robert Relyea
    nss_emul_init = has_readers;
903 111a38b0 Robert Relyea
904 111a38b0 Robert Relyea
    return VCARD_EMUL_OK;
905 111a38b0 Robert Relyea
}
906 111a38b0 Robert Relyea
907 111a38b0 Robert Relyea
/* Recreate card insert events for all readers (user should
908 111a38b0 Robert Relyea
 * deduce implied reader insert. perhaps do a reader insert as well?)
909 111a38b0 Robert Relyea
 */
910 111a38b0 Robert Relyea
void
911 111a38b0 Robert Relyea
vcard_emul_replay_insertion_events(void)
912 111a38b0 Robert Relyea
{
913 111a38b0 Robert Relyea
    VReaderListEntry *current_entry;
914 111a38b0 Robert Relyea
    VReaderListEntry *next_entry = NULL;
915 111a38b0 Robert Relyea
    VReaderList *list = vreader_get_reader_list();
916 111a38b0 Robert Relyea
917 111a38b0 Robert Relyea
    for (current_entry = vreader_list_get_first(list); current_entry;
918 111a38b0 Robert Relyea
            current_entry = next_entry) {
919 111a38b0 Robert Relyea
        VReader *vreader = vreader_list_get_reader(current_entry);
920 111a38b0 Robert Relyea
        next_entry = vreader_list_get_next(current_entry);
921 111a38b0 Robert Relyea
        vreader_queue_card_event(vreader);
922 111a38b0 Robert Relyea
    }
923 111a38b0 Robert Relyea
}
924 111a38b0 Robert Relyea
925 111a38b0 Robert Relyea
/*
926 111a38b0 Robert Relyea
 *  Silly little functions to help parsing our argument string
927 111a38b0 Robert Relyea
 */
928 111a38b0 Robert Relyea
static char *
929 111a38b0 Robert Relyea
copy_string(const char *str, int str_len)
930 111a38b0 Robert Relyea
{
931 111a38b0 Robert Relyea
    char *new_str;
932 111a38b0 Robert Relyea
933 111a38b0 Robert Relyea
    new_str = qemu_malloc(str_len+1);
934 111a38b0 Robert Relyea
    memcpy(new_str, str, str_len);
935 111a38b0 Robert Relyea
    new_str[str_len] = 0;
936 111a38b0 Robert Relyea
    return new_str;
937 111a38b0 Robert Relyea
}
938 111a38b0 Robert Relyea
939 111a38b0 Robert Relyea
static int
940 111a38b0 Robert Relyea
count_tokens(const char *str, char token, char token_end)
941 111a38b0 Robert Relyea
{
942 111a38b0 Robert Relyea
    int count = 0;
943 111a38b0 Robert Relyea
944 111a38b0 Robert Relyea
    for (; *str; str++) {
945 111a38b0 Robert Relyea
        if (*str == token) {
946 111a38b0 Robert Relyea
            count++;
947 111a38b0 Robert Relyea
        }
948 111a38b0 Robert Relyea
        if (*str == token_end) {
949 111a38b0 Robert Relyea
            break;
950 111a38b0 Robert Relyea
        }
951 111a38b0 Robert Relyea
    }
952 111a38b0 Robert Relyea
    return count;
953 111a38b0 Robert Relyea
}
954 111a38b0 Robert Relyea
955 111a38b0 Robert Relyea
static const char *
956 111a38b0 Robert Relyea
strip(const char *str)
957 111a38b0 Robert Relyea
{
958 685ff50f Alon Levy
    for (; *str && isspace(*str); str++) {
959 111a38b0 Robert Relyea
    }
960 111a38b0 Robert Relyea
    return str;
961 111a38b0 Robert Relyea
}
962 111a38b0 Robert Relyea
963 111a38b0 Robert Relyea
static const char *
964 111a38b0 Robert Relyea
find_blank(const char *str)
965 111a38b0 Robert Relyea
{
966 685ff50f Alon Levy
    for (; *str && !isspace(*str); str++) {
967 111a38b0 Robert Relyea
    }
968 111a38b0 Robert Relyea
    return str;
969 111a38b0 Robert Relyea
}
970 111a38b0 Robert Relyea
971 111a38b0 Robert Relyea
972 111a38b0 Robert Relyea
/*
973 111a38b0 Robert Relyea
 *  We really want to use some existing argument parsing library here. That
974 fc27eefe Stefan Weil
 *  would give us a consistent look */
975 111a38b0 Robert Relyea
static VCardEmulOptions options;
976 111a38b0 Robert Relyea
#define READER_STEP 4
977 111a38b0 Robert Relyea
978 111a38b0 Robert Relyea
VCardEmulOptions *
979 111a38b0 Robert Relyea
vcard_emul_options(const char *args)
980 111a38b0 Robert Relyea
{
981 111a38b0 Robert Relyea
    int reader_count = 0;
982 111a38b0 Robert Relyea
    VCardEmulOptions *opts;
983 111a38b0 Robert Relyea
    char type_str[100];
984 111a38b0 Robert Relyea
    int type_len;
985 111a38b0 Robert Relyea
986 111a38b0 Robert Relyea
    /* Allow the future use of allocating the options structure on the fly */
987 111a38b0 Robert Relyea
    memcpy(&options, &default_options, sizeof(options));
988 111a38b0 Robert Relyea
    opts = &options;
989 111a38b0 Robert Relyea
990 111a38b0 Robert Relyea
    do {
991 111a38b0 Robert Relyea
        args = strip(args); /* strip off the leading spaces */
992 111a38b0 Robert Relyea
        if (*args == ',') {
993 111a38b0 Robert Relyea
            continue;
994 111a38b0 Robert Relyea
        }
995 111a38b0 Robert Relyea
        /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
996 111a38b0 Robert Relyea
         *       cert_2,cert_3...) */
997 111a38b0 Robert Relyea
        if (strncmp(args, "soft=", 5) == 0) {
998 111a38b0 Robert Relyea
            const char *name;
999 111a38b0 Robert Relyea
            const char *vname;
1000 111a38b0 Robert Relyea
            const char *type_params;
1001 111a38b0 Robert Relyea
            VCardEmulType type;
1002 111a38b0 Robert Relyea
            int name_length, vname_length, type_params_length, count, i;
1003 111a38b0 Robert Relyea
            VirtualReaderOptions *vreaderOpt = NULL;
1004 111a38b0 Robert Relyea
1005 111a38b0 Robert Relyea
            args = strip(args + 5);
1006 111a38b0 Robert Relyea
            if (*args != '(') {
1007 111a38b0 Robert Relyea
                continue;
1008 111a38b0 Robert Relyea
            }
1009 111a38b0 Robert Relyea
            name = args;
1010 111a38b0 Robert Relyea
            args = strpbrk(args + 1, ",)");
1011 111a38b0 Robert Relyea
            if (*args == 0) {
1012 111a38b0 Robert Relyea
                break;
1013 111a38b0 Robert Relyea
            }
1014 111a38b0 Robert Relyea
            if (*args == ')') {
1015 111a38b0 Robert Relyea
                args++;
1016 111a38b0 Robert Relyea
                continue;
1017 111a38b0 Robert Relyea
            }
1018 111a38b0 Robert Relyea
            args = strip(args+1);
1019 111a38b0 Robert Relyea
            name_length = args - name - 2;
1020 111a38b0 Robert Relyea
            vname = args;
1021 111a38b0 Robert Relyea
            args = strpbrk(args + 1, ",)");
1022 111a38b0 Robert Relyea
            if (*args == 0) {
1023 111a38b0 Robert Relyea
                break;
1024 111a38b0 Robert Relyea
            }
1025 111a38b0 Robert Relyea
            if (*args == ')') {
1026 111a38b0 Robert Relyea
                args++;
1027 111a38b0 Robert Relyea
                continue;
1028 111a38b0 Robert Relyea
            }
1029 111a38b0 Robert Relyea
            vname_length = args - name - 2;
1030 111a38b0 Robert Relyea
            args = strip(args+1);
1031 111a38b0 Robert Relyea
            type_len = strpbrk(args, ",)") - args;
1032 111a38b0 Robert Relyea
            assert(sizeof(type_str) > type_len);
1033 111a38b0 Robert Relyea
            strncpy(type_str, args, type_len);
1034 111a38b0 Robert Relyea
            type_str[type_len] = 0;
1035 111a38b0 Robert Relyea
            type = vcard_emul_type_from_string(type_str);
1036 111a38b0 Robert Relyea
            args = strpbrk(args, ",)");
1037 111a38b0 Robert Relyea
            if (*args == 0) {
1038 111a38b0 Robert Relyea
                break;
1039 111a38b0 Robert Relyea
            }
1040 111a38b0 Robert Relyea
            if (*args == ')') {
1041 111a38b0 Robert Relyea
                args++;
1042 111a38b0 Robert Relyea
                continue;
1043 111a38b0 Robert Relyea
            }
1044 111a38b0 Robert Relyea
            args = strip(args++);
1045 111a38b0 Robert Relyea
            type_params = args;
1046 111a38b0 Robert Relyea
            args = strpbrk(args + 1, ",)");
1047 111a38b0 Robert Relyea
            if (*args == 0) {
1048 111a38b0 Robert Relyea
                break;
1049 111a38b0 Robert Relyea
            }
1050 111a38b0 Robert Relyea
            if (*args == ')') {
1051 111a38b0 Robert Relyea
                args++;
1052 111a38b0 Robert Relyea
                continue;
1053 111a38b0 Robert Relyea
            }
1054 111a38b0 Robert Relyea
            type_params_length = args - name;
1055 111a38b0 Robert Relyea
            args = strip(args++);
1056 111a38b0 Robert Relyea
            if (*args == 0) {
1057 111a38b0 Robert Relyea
                break;
1058 111a38b0 Robert Relyea
            }
1059 111a38b0 Robert Relyea
1060 111a38b0 Robert Relyea
            if (opts->vreader_count >= reader_count) {
1061 111a38b0 Robert Relyea
                reader_count += READER_STEP;
1062 111a38b0 Robert Relyea
                vreaderOpt = realloc(opts->vreader,
1063 111a38b0 Robert Relyea
                                reader_count * sizeof(*vreaderOpt));
1064 111a38b0 Robert Relyea
                if (vreaderOpt == NULL) {
1065 111a38b0 Robert Relyea
                    return opts; /* we're done */
1066 111a38b0 Robert Relyea
                }
1067 111a38b0 Robert Relyea
            }
1068 111a38b0 Robert Relyea
            opts->vreader = vreaderOpt;
1069 111a38b0 Robert Relyea
            vreaderOpt = &vreaderOpt[opts->vreader_count];
1070 111a38b0 Robert Relyea
            vreaderOpt->name = copy_string(name, name_length);
1071 111a38b0 Robert Relyea
            vreaderOpt->vname = copy_string(vname, vname_length);
1072 111a38b0 Robert Relyea
            vreaderOpt->card_type = type;
1073 111a38b0 Robert Relyea
            vreaderOpt->type_params =
1074 111a38b0 Robert Relyea
                copy_string(type_params, type_params_length);
1075 111a38b0 Robert Relyea
            count = count_tokens(args, ',', ')');
1076 111a38b0 Robert Relyea
            vreaderOpt->cert_count = count;
1077 111a38b0 Robert Relyea
            vreaderOpt->cert_name = (char **)qemu_malloc(count*sizeof(char *));
1078 111a38b0 Robert Relyea
            for (i = 0; i < count; i++) {
1079 111a38b0 Robert Relyea
                const char *cert = args + 1;
1080 111a38b0 Robert Relyea
                args = strpbrk(args + 1, ",)");
1081 111a38b0 Robert Relyea
                vreaderOpt->cert_name[i] = copy_string(cert, args - cert);
1082 111a38b0 Robert Relyea
            }
1083 111a38b0 Robert Relyea
            if (*args == ')') {
1084 111a38b0 Robert Relyea
                args++;
1085 111a38b0 Robert Relyea
            }
1086 111a38b0 Robert Relyea
            opts->vreader_count++;
1087 111a38b0 Robert Relyea
        /* use_hw= */
1088 111a38b0 Robert Relyea
        } else if (strncmp(args, "use_hw=", 7) == 0) {
1089 111a38b0 Robert Relyea
            args = strip(args+7);
1090 111a38b0 Robert Relyea
            if (*args == '0' || *args == 'N' || *args == 'n' || *args == 'F') {
1091 111a38b0 Robert Relyea
                opts->use_hw = PR_FALSE;
1092 111a38b0 Robert Relyea
            } else {
1093 111a38b0 Robert Relyea
                opts->use_hw = PR_TRUE;
1094 111a38b0 Robert Relyea
            }
1095 111a38b0 Robert Relyea
            args = find_blank(args);
1096 111a38b0 Robert Relyea
        /* hw_type= */
1097 111a38b0 Robert Relyea
        } else if (strncmp(args, "hw_type=", 8) == 0) {
1098 111a38b0 Robert Relyea
            args = strip(args+8);
1099 111a38b0 Robert Relyea
            opts->hw_card_type = vcard_emul_type_from_string(args);
1100 111a38b0 Robert Relyea
            args = find_blank(args);
1101 111a38b0 Robert Relyea
        /* hw_params= */
1102 111a38b0 Robert Relyea
        } else if (strncmp(args, "hw_params=", 10) == 0) {
1103 111a38b0 Robert Relyea
            const char *params;
1104 111a38b0 Robert Relyea
            args = strip(args+10);
1105 111a38b0 Robert Relyea
            params = args;
1106 111a38b0 Robert Relyea
            args = find_blank(args);
1107 111a38b0 Robert Relyea
            opts->hw_type_params = copy_string(params, args-params);
1108 111a38b0 Robert Relyea
        /* db="/data/base/path" */
1109 111a38b0 Robert Relyea
        } else if (strncmp(args, "db=", 3) == 0) {
1110 111a38b0 Robert Relyea
            const char *db;
1111 111a38b0 Robert Relyea
            args = strip(args+3);
1112 111a38b0 Robert Relyea
            if (*args != '"') {
1113 111a38b0 Robert Relyea
                continue;
1114 111a38b0 Robert Relyea
            }
1115 111a38b0 Robert Relyea
            args++;
1116 111a38b0 Robert Relyea
            db = args;
1117 111a38b0 Robert Relyea
            args = strpbrk(args, "\"\n");
1118 111a38b0 Robert Relyea
            opts->nss_db = copy_string(db, args-db);
1119 111a38b0 Robert Relyea
            if (*args != 0) {
1120 111a38b0 Robert Relyea
                args++;
1121 111a38b0 Robert Relyea
            }
1122 111a38b0 Robert Relyea
        } else {
1123 111a38b0 Robert Relyea
            args = find_blank(args);
1124 111a38b0 Robert Relyea
        }
1125 111a38b0 Robert Relyea
    } while (*args != 0);
1126 111a38b0 Robert Relyea
1127 111a38b0 Robert Relyea
    return opts;
1128 111a38b0 Robert Relyea
}
1129 111a38b0 Robert Relyea
1130 111a38b0 Robert Relyea
void
1131 111a38b0 Robert Relyea
vcard_emul_usage(void)
1132 111a38b0 Robert Relyea
{
1133 111a38b0 Robert Relyea
   fprintf(stderr,
1134 111a38b0 Robert Relyea
"emul args: comma separated list of the following arguments\n"
1135 111a38b0 Robert Relyea
" db={nss_database}               (default sql:/etc/pki/nssdb)\n"
1136 111a38b0 Robert Relyea
" use_hw=[yes|no]                 (default yes)\n"
1137 111a38b0 Robert Relyea
" hw_type={card_type_to_emulate}  (default CAC)\n"
1138 111a38b0 Robert Relyea
" hw_param={param_for_card}       (default \"\")\n"
1139 111a38b0 Robert Relyea
" soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
1140 111a38b0 Robert Relyea
"       {cert1},{cert2},{cert3}    (default none)\n"
1141 111a38b0 Robert Relyea
"\n"
1142 111a38b0 Robert Relyea
"  {nss_database}          The location of the NSS cert & key database\n"
1143 111a38b0 Robert Relyea
"  {card_type_to_emulate}  What card interface to present to the guest\n"
1144 111a38b0 Robert Relyea
"  {param_for_card}        Card interface specific parameters\n"
1145 111a38b0 Robert Relyea
"  {slot_name}             NSS slot that contains the certs\n"
1146 111a38b0 Robert Relyea
"  {vreader_name}          Virutal reader name to present to the guest\n"
1147 111a38b0 Robert Relyea
"  {certN}                 Nickname of the certificate n on the virtual card\n"
1148 111a38b0 Robert Relyea
"\n"
1149 111a38b0 Robert Relyea
"These parameters come as a single string separated by blanks or newlines."
1150 111a38b0 Robert Relyea
"\n"
1151 111a38b0 Robert Relyea
"Unless use_hw is set to no, all tokens that look like removable hardware\n"
1152 111a38b0 Robert Relyea
"tokens will be presented to the guest using the emulator specified by\n"
1153 111a38b0 Robert Relyea
"hw_type, and parameters of hw_param.\n"
1154 111a38b0 Robert Relyea
"\n"
1155 111a38b0 Robert Relyea
"If more one or more soft= parameters are specified, these readers will be\n"
1156 111a38b0 Robert Relyea
"presented to the guest\n");
1157 111a38b0 Robert Relyea
}