]> Git Repo - qemu.git/blob - libcacard/vreader.c
scsi: Guard against buflen exceeding req->cmd.xfer in scsi_disk_emulate_command
[qemu.git] / libcacard / vreader.c
1 /*
2  * emulate the reader
3  *
4  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
5  * See the COPYING.LIB file in the top-level directory.
6  */
7
8 #include "qemu-common.h"
9 #include "qemu-thread.h"
10
11 #include "vcard.h"
12 #include "vcard_emul.h"
13 #include "card_7816.h"
14 #include "vreader.h"
15 #include "vevent.h"
16
17 struct VReaderStruct {
18     int    reference_count;
19     VCard *card;
20     char *name;
21     vreader_id_t id;
22     QemuMutex lock;
23     VReaderEmul  *reader_private;
24     VReaderEmulFree reader_private_free;
25 };
26
27 /* manage locking */
28 static inline void
29 vreader_lock(VReader *reader)
30 {
31     qemu_mutex_lock(&reader->lock);
32 }
33
34 static inline void
35 vreader_unlock(VReader *reader)
36 {
37     qemu_mutex_unlock(&reader->lock);
38 }
39
40 /*
41  * vreader constructor
42  */
43 VReader *
44 vreader_new(const char *name, VReaderEmul *private,
45             VReaderEmulFree private_free)
46 {
47     VReader *reader;
48
49     reader = (VReader *)g_malloc(sizeof(VReader));
50     qemu_mutex_init(&reader->lock);
51     reader->reference_count = 1;
52     reader->name = name ? strdup(name) : NULL;
53     reader->card = NULL;
54     reader->id = (vreader_id_t)-1;
55     reader->reader_private = private;
56     reader->reader_private_free = private_free;
57     return reader;
58 }
59
60 /* get a reference */
61 VReader*
62 vreader_reference(VReader *reader)
63 {
64     if (reader == NULL) {
65         return NULL;
66     }
67     vreader_lock(reader);
68     reader->reference_count++;
69     vreader_unlock(reader);
70     return reader;
71 }
72
73 /* free a reference */
74 void
75 vreader_free(VReader *reader)
76 {
77     if (reader == NULL) {
78         return;
79     }
80     vreader_lock(reader);
81     if (reader->reference_count-- > 1) {
82         vreader_unlock(reader);
83         return;
84     }
85     vreader_unlock(reader);
86     if (reader->card) {
87         vcard_free(reader->card);
88     }
89     if (reader->name) {
90         g_free(reader->name);
91     }
92     if (reader->reader_private_free) {
93         reader->reader_private_free(reader->reader_private);
94     }
95     g_free(reader);
96     return;
97 }
98
99 static VCard *
100 vreader_get_card(VReader *reader)
101 {
102     VCard *card;
103
104     vreader_lock(reader);
105     card = vcard_reference(reader->card);
106     vreader_unlock(reader);
107     return card;
108 }
109
110 VReaderStatus
111 vreader_card_is_present(VReader *reader)
112 {
113     VCard *card = vreader_get_card(reader);
114
115     if (card == NULL) {
116         return VREADER_NO_CARD;
117     }
118     vcard_free(card);
119     return VREADER_OK;
120 }
121
122 vreader_id_t
123 vreader_get_id(VReader *reader)
124 {
125     if (reader == NULL) {
126         return (vreader_id_t)-1;
127     }
128     return reader->id;
129 }
130
131 VReaderStatus
132 vreader_set_id(VReader *reader, vreader_id_t id)
133 {
134     if (reader == NULL) {
135         return VREADER_NO_CARD;
136     }
137     reader->id = id;
138     return VREADER_OK;
139 }
140
141 const char *
142 vreader_get_name(VReader *reader)
143 {
144     if (reader == NULL) {
145         return NULL;
146     }
147     return reader->name;
148 }
149
150 VReaderEmul *
151 vreader_get_private(VReader *reader)
152 {
153     return reader->reader_private;
154 }
155
156 static VReaderStatus
157 vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
158 {
159     VCard *card = vreader_get_card(reader);
160
161     if (card == NULL) {
162         return VREADER_NO_CARD;
163     }
164     /*
165      * clean up our state
166      */
167     vcard_reset(card, power);
168     if (atr) {
169         vcard_get_atr(card, atr, len);
170     }
171     vcard_free(card); /* free our reference */
172     return VREADER_OK;
173 }
174
175 VReaderStatus
176 vreader_power_on(VReader *reader, unsigned char *atr, int *len)
177 {
178     return vreader_reset(reader, VCARD_POWER_ON, atr, len);
179 }
180
181 VReaderStatus
182 vreader_power_off(VReader *reader)
183 {
184     return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
185 }
186
187
188 VReaderStatus
189 vreader_xfr_bytes(VReader *reader,
190                   unsigned char *send_buf, int send_buf_len,
191                   unsigned char *receive_buf, int *receive_buf_len)
192 {
193     VCardAPDU *apdu;
194     VCardResponse *response = NULL;
195     VCardStatus card_status;
196     unsigned short status;
197     VCard *card = vreader_get_card(reader);
198
199     if (card == NULL) {
200         return VREADER_NO_CARD;
201     }
202
203     apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
204     if (apdu == NULL) {
205         response = vcard_make_response(status);
206         card_status = VCARD_DONE;
207     } else {
208         card_status = vcard_process_apdu(card, apdu, &response);
209     }
210     assert(card_status == VCARD_DONE);
211     if (card_status == VCARD_DONE) {
212         int size = MIN(*receive_buf_len, response->b_total_len);
213         memcpy(receive_buf, response->b_data, size);
214         *receive_buf_len = size;
215     }
216     vcard_response_delete(response);
217     vcard_apdu_delete(apdu);
218     vcard_free(card); /* free our reference */
219     return VREADER_OK;
220 }
221
222 struct VReaderListStruct {
223     VReaderListEntry *head;
224     VReaderListEntry *tail;
225 };
226
227 struct VReaderListEntryStruct {
228     VReaderListEntry *next;
229     VReaderListEntry *prev;
230     VReader *reader;
231 };
232
233
234 static VReaderListEntry *
235 vreader_list_entry_new(VReader *reader)
236 {
237     VReaderListEntry *new_reader_list_entry;
238
239     new_reader_list_entry = (VReaderListEntry *)
240                                g_malloc(sizeof(VReaderListEntry));
241     new_reader_list_entry->next = NULL;
242     new_reader_list_entry->prev = NULL;
243     new_reader_list_entry->reader = vreader_reference(reader);
244     return new_reader_list_entry;
245 }
246
247 static void
248 vreader_list_entry_delete(VReaderListEntry *entry)
249 {
250     if (entry == NULL) {
251         return;
252     }
253     vreader_free(entry->reader);
254     g_free(entry);
255 }
256
257
258 static VReaderList *
259 vreader_list_new(void)
260 {
261     VReaderList *new_reader_list;
262
263     new_reader_list = (VReaderList *)g_malloc(sizeof(VReaderList));
264     new_reader_list->head = NULL;
265     new_reader_list->tail = NULL;
266     return new_reader_list;
267 }
268
269 void
270 vreader_list_delete(VReaderList *list)
271 {
272     VReaderListEntry *current_entry;
273     VReaderListEntry *next_entry = NULL;
274     for (current_entry = vreader_list_get_first(list); current_entry;
275          current_entry = next_entry) {
276         next_entry = vreader_list_get_next(current_entry);
277         vreader_list_entry_delete(current_entry);
278     }
279     list->head = NULL;
280     list->tail = NULL;
281     g_free(list);
282 }
283
284
285 VReaderListEntry *
286 vreader_list_get_first(VReaderList *list)
287 {
288     return list ? list->head : NULL;
289 }
290
291 VReaderListEntry *
292 vreader_list_get_next(VReaderListEntry *current)
293 {
294     return current ? current->next : NULL;
295 }
296
297 VReader *
298 vreader_list_get_reader(VReaderListEntry *entry)
299 {
300     return entry ? vreader_reference(entry->reader) : NULL;
301 }
302
303 static void
304 vreader_queue(VReaderList *list, VReaderListEntry *entry)
305 {
306     if (entry == NULL) {
307         return;
308     }
309     entry->next = NULL;
310     entry->prev = list->tail;
311     if (list->head) {
312         list->tail->next = entry;
313     } else {
314         list->head = entry;
315     }
316     list->tail = entry;
317 }
318
319 static void
320 vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
321 {
322     if (entry == NULL) {
323         return;
324     }
325     if (entry->next == NULL) {
326         list->tail = entry->prev;
327     } else if (entry->prev == NULL) {
328         list->head = entry->next;
329     } else {
330         entry->prev->next = entry->next;
331         entry->next->prev = entry->prev;
332     }
333     if ((list->tail == NULL) || (list->head == NULL)) {
334         list->head = list->tail = NULL;
335     }
336     entry->next = entry->prev = NULL;
337 }
338
339 static VReaderList *vreader_list;
340 static QemuMutex vreader_list_mutex;
341
342 static void
343 vreader_list_init(void)
344 {
345     vreader_list = vreader_list_new();
346     qemu_mutex_init(&vreader_list_mutex);
347 }
348
349 static void
350 vreader_list_lock(void)
351 {
352     qemu_mutex_lock(&vreader_list_mutex);
353 }
354
355 static void
356 vreader_list_unlock(void)
357 {
358     qemu_mutex_unlock(&vreader_list_mutex);
359 }
360
361 static VReaderList *
362 vreader_copy_list(VReaderList *list)
363 {
364     VReaderList *new_list = NULL;
365     VReaderListEntry *current_entry = NULL;
366
367     new_list = vreader_list_new();
368     if (new_list == NULL) {
369         return NULL;
370     }
371     for (current_entry = vreader_list_get_first(list); current_entry;
372          current_entry = vreader_list_get_next(current_entry)) {
373         VReader *reader = vreader_list_get_reader(current_entry);
374         VReaderListEntry *new_entry = vreader_list_entry_new(reader);
375
376         vreader_free(reader);
377         vreader_queue(new_list, new_entry);
378     }
379     return new_list;
380 }
381
382 VReaderList *
383 vreader_get_reader_list(void)
384 {
385     VReaderList *new_reader_list;
386
387     vreader_list_lock();
388     new_reader_list = vreader_copy_list(vreader_list);
389     vreader_list_unlock();
390     return new_reader_list;
391 }
392
393 VReader *
394 vreader_get_reader_by_id(vreader_id_t id)
395 {
396     VReader *reader = NULL;
397     VReaderListEntry *current_entry = NULL;
398
399     if (id == (vreader_id_t) -1) {
400         return NULL;
401     }
402
403     vreader_list_lock();
404     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
405             current_entry = vreader_list_get_next(current_entry)) {
406         VReader *creader = vreader_list_get_reader(current_entry);
407         if (creader->id == id) {
408             reader = creader;
409             break;
410         }
411         vreader_free(creader);
412     }
413     vreader_list_unlock();
414     return reader;
415 }
416
417 VReader *
418 vreader_get_reader_by_name(const char *name)
419 {
420     VReader *reader = NULL;
421     VReaderListEntry *current_entry = NULL;
422
423     vreader_list_lock();
424     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
425             current_entry = vreader_list_get_next(current_entry)) {
426         VReader *creader = vreader_list_get_reader(current_entry);
427         if (strcmp(creader->name, name) == 0) {
428             reader = creader;
429             break;
430         }
431         vreader_free(creader);
432     }
433     vreader_list_unlock();
434     return reader;
435 }
436
437 /* called from card_emul to initialize the readers */
438 VReaderStatus
439 vreader_add_reader(VReader *reader)
440 {
441     VReaderListEntry *reader_entry;
442
443     reader_entry = vreader_list_entry_new(reader);
444     if (reader_entry == NULL) {
445         return VREADER_OUT_OF_MEMORY;
446     }
447     vreader_list_lock();
448     vreader_queue(vreader_list, reader_entry);
449     vreader_list_unlock();
450     vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
451     return VREADER_OK;
452 }
453
454
455 VReaderStatus
456 vreader_remove_reader(VReader *reader)
457 {
458     VReaderListEntry *current_entry;
459
460     vreader_list_lock();
461     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
462          current_entry = vreader_list_get_next(current_entry)) {
463         if (current_entry->reader == reader) {
464             break;
465         }
466     }
467     vreader_dequeue(vreader_list, current_entry);
468     vreader_list_unlock();
469     vreader_list_entry_delete(current_entry);
470     vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
471     return VREADER_OK;
472 }
473
474 /*
475  * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
476  * state. Separated from vreader_insert_card to allow replaying events
477  * for a given state.
478  */
479 void
480 vreader_queue_card_event(VReader *reader)
481 {
482     vevent_queue_vevent(vevent_new(
483         reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
484         reader->card));
485 }
486
487 /*
488  * insert/remove a new card. for removal, card == NULL
489  */
490 VReaderStatus
491 vreader_insert_card(VReader *reader, VCard *card)
492 {
493     vreader_lock(reader);
494     if (reader->card) {
495         /* decrement reference count */
496         vcard_free(reader->card);
497         reader->card = NULL;
498     }
499     reader->card = vcard_reference(card);
500     vreader_unlock(reader);
501     vreader_queue_card_event(reader);
502     return VREADER_OK;
503 }
504
505 /*
506  * initialize all the static reader structures
507  */
508 void
509 vreader_init(void)
510 {
511     vreader_list_init();
512 }
513
This page took 0.053267 seconds and 4 git commands to generate.