Annotation of qemu/libcacard/vscclient.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Tester for VSCARD protocol, client side.
        !             3:  *
        !             4:  * Can be used with ccid-card-passthru.
        !             5:  *
        !             6:  * Copyright (c) 2011 Red Hat.
        !             7:  * Written by Alon Levy.
        !             8:  *
        !             9:  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
        !            10:  * See the COPYING.LIB file in the top-level directory.
        !            11:  */
        !            12: 
        !            13: #include <netdb.h>
        !            14: 
        !            15: #include "qemu-common.h"
        !            16: #include "qemu-thread.h"
        !            17: #include "qemu_socket.h"
        !            18: 
        !            19: #include "vscard_common.h"
        !            20: 
        !            21: #include "vreader.h"
        !            22: #include "vcard_emul.h"
        !            23: #include "vevent.h"
        !            24: 
        !            25: int verbose;
        !            26: 
        !            27: int sock;
        !            28: 
        !            29: static void
        !            30: print_byte_array(
        !            31:     uint8_t *arrBytes,
        !            32:     unsigned int nSize
        !            33: ) {
        !            34:     int i;
        !            35:     for (i = 0; i < nSize; i++) {
        !            36:         printf("%02X ", arrBytes[i]);
        !            37:     }
        !            38:     printf("\n");
        !            39: }
        !            40: 
        !            41: static void
        !            42: print_usage(void) {
        !            43:     printf("vscclient [-c <certname> .. -e <emul_args> -d <level>%s] "
        !            44:             "<host> <port>\n",
        !            45: #ifdef USE_PASSTHRU
        !            46:     " -p");
        !            47:     printf(" -p use passthrough mode\n");
        !            48: #else
        !            49:    "");
        !            50: #endif
        !            51:     vcard_emul_usage();
        !            52: }
        !            53: 
        !            54: static QemuMutex write_lock;
        !            55: 
        !            56: static int
        !            57: send_msg(
        !            58:     VSCMsgType type,
        !            59:     uint32_t reader_id,
        !            60:     const void *msg,
        !            61:     unsigned int length
        !            62: ) {
        !            63:     int rv;
        !            64:     VSCMsgHeader mhHeader;
        !            65: 
        !            66:     qemu_mutex_lock(&write_lock);
        !            67: 
        !            68:     if (verbose > 10) {
        !            69:         printf("sending type=%d id=%d, len =%d (0x%x)\n",
        !            70:                type, reader_id, length, length);
        !            71:     }
        !            72: 
        !            73:     mhHeader.type = htonl(type);
        !            74:     mhHeader.reader_id = 0;
        !            75:     mhHeader.length = htonl(length);
        !            76:     rv = write(sock, &mhHeader, sizeof(mhHeader));
        !            77:     if (rv < 0) {
        !            78:         /* Error */
        !            79:         fprintf(stderr, "write header error\n");
        !            80:         close(sock);
        !            81:         qemu_mutex_unlock(&write_lock);
        !            82:         return 16;
        !            83:     }
        !            84:     rv = write(sock, msg, length);
        !            85:     if (rv < 0) {
        !            86:         /* Error */
        !            87:         fprintf(stderr, "write error\n");
        !            88:         close(sock);
        !            89:         qemu_mutex_unlock(&write_lock);
        !            90:         return 16;
        !            91:     }
        !            92:     qemu_mutex_unlock(&write_lock);
        !            93: 
        !            94:     return 0;
        !            95: }
        !            96: 
        !            97: static VReader *pending_reader;
        !            98: static QemuMutex pending_reader_lock;
        !            99: static QemuCond pending_reader_condition;
        !           100: 
        !           101: #define MAX_ATR_LEN 40
        !           102: static void *
        !           103: event_thread(void *arg)
        !           104: {
        !           105:     unsigned char atr[MAX_ATR_LEN];
        !           106:     int atr_len = MAX_ATR_LEN;
        !           107:     VEvent *event = NULL;
        !           108:     unsigned int reader_id;
        !           109: 
        !           110: 
        !           111:     while (1) {
        !           112:         const char *reader_name;
        !           113: 
        !           114:         event = vevent_wait_next_vevent();
        !           115:         if (event == NULL) {
        !           116:             break;
        !           117:         }
        !           118:         reader_id = vreader_get_id(event->reader);
        !           119:         if (reader_id == VSCARD_UNDEFINED_READER_ID &&
        !           120:             event->type != VEVENT_READER_INSERT) {
        !           121:             /* ignore events from readers qemu has rejected */
        !           122:             /* if qemu is still deciding on this reader, wait to see if need to
        !           123:              * forward this event */
        !           124:             qemu_mutex_lock(&pending_reader_lock);
        !           125:             if (!pending_reader || (pending_reader != event->reader)) {
        !           126:                 /* wasn't for a pending reader, this reader has already been
        !           127:                  * rejected by qemu */
        !           128:                 qemu_mutex_unlock(&pending_reader_lock);
        !           129:                 vevent_delete(event);
        !           130:                 continue;
        !           131:             }
        !           132:             /* this reader hasn't been told it's status from qemu yet, wait for
        !           133:              * that status */
        !           134:             while (pending_reader != NULL) {
        !           135:                 qemu_cond_wait(&pending_reader_condition, &pending_reader_lock);
        !           136:             }
        !           137:             qemu_mutex_unlock(&pending_reader_lock);
        !           138:             /* now recheck the id */
        !           139:             reader_id = vreader_get_id(event->reader);
        !           140:             if (reader_id == VSCARD_UNDEFINED_READER_ID) {
        !           141:                 /* this reader was rejected */
        !           142:                 vevent_delete(event);
        !           143:                 continue;
        !           144:             }
        !           145:             /* reader was accepted, now forward the event */
        !           146:         }
        !           147:         switch (event->type) {
        !           148:         case VEVENT_READER_INSERT:
        !           149:             /* tell qemu to insert a new CCID reader */
        !           150:             /* wait until qemu has responded to our first reader insert
        !           151:              * before we send a second. That way we won't confuse the responses
        !           152:              * */
        !           153:             qemu_mutex_lock(&pending_reader_lock);
        !           154:             while (pending_reader != NULL) {
        !           155:                 qemu_cond_wait(&pending_reader_condition, &pending_reader_lock);
        !           156:             }
        !           157:             pending_reader = vreader_reference(event->reader);
        !           158:             qemu_mutex_unlock(&pending_reader_lock);
        !           159:             reader_name = vreader_get_name(event->reader);
        !           160:             if (verbose > 10) {
        !           161:                 printf(" READER INSERT: %s\n", reader_name);
        !           162:             }
        !           163:             send_msg(VSC_ReaderAdd,
        !           164:                 reader_id, /* currerntly VSCARD_UNDEFINED_READER_ID */
        !           165:                 NULL, 0 /* TODO reader_name, strlen(reader_name) */);
        !           166:             break;
        !           167:         case VEVENT_READER_REMOVE:
        !           168:             /* future, tell qemu that an old CCID reader has been removed */
        !           169:             if (verbose > 10) {
        !           170:                 printf(" READER REMOVE: %d\n", reader_id);
        !           171:             }
        !           172:             send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
        !           173:             break;
        !           174:         case VEVENT_CARD_INSERT:
        !           175:             /* get the ATR (intended as a response to a power on from the
        !           176:              * reader */
        !           177:             atr_len = MAX_ATR_LEN;
        !           178:             vreader_power_on(event->reader, atr, &atr_len);
        !           179:             /* ATR call functions as a Card Insert event */
        !           180:             if (verbose > 10) {
        !           181:                 printf(" CARD INSERT %d: ", reader_id);
        !           182:                 print_byte_array(atr, atr_len);
        !           183:             }
        !           184:             send_msg(VSC_ATR, reader_id, atr, atr_len);
        !           185:             break;
        !           186:         case VEVENT_CARD_REMOVE:
        !           187:             /* Card removed */
        !           188:             if (verbose > 10) {
        !           189:                 printf(" CARD REMOVE %d:\n", reader_id);
        !           190:             }
        !           191:             send_msg(VSC_CardRemove, reader_id, NULL, 0);
        !           192:             break;
        !           193:         default:
        !           194:             break;
        !           195:         }
        !           196:         vevent_delete(event);
        !           197:     }
        !           198:     return NULL;
        !           199: }
        !           200: 
        !           201: 
        !           202: static unsigned int
        !           203: get_id_from_string(char *string, unsigned int default_id)
        !           204: {
        !           205:     unsigned int id = atoi(string);
        !           206: 
        !           207:     /* don't accidentally swith to zero because no numbers have been supplied */
        !           208:     if ((id == 0) && *string != '0') {
        !           209:         return default_id;
        !           210:     }
        !           211:     return id;
        !           212: }
        !           213: 
        !           214: static void
        !           215: do_command(void)
        !           216: {
        !           217:     char inbuf[255];
        !           218:     char *string;
        !           219:     VCardEmulError error;
        !           220:     static unsigned int default_reader_id;
        !           221:     unsigned int reader_id;
        !           222:     VReader *reader = NULL;
        !           223: 
        !           224:     reader_id = default_reader_id;
        !           225:     string = fgets(inbuf, sizeof(inbuf), stdin);
        !           226:     if (string != NULL) {
        !           227:         if (strncmp(string, "exit", 4) == 0) {
        !           228:             /* remove all the readers */
        !           229:             VReaderList *list = vreader_get_reader_list();
        !           230:             VReaderListEntry *reader_entry;
        !           231:             printf("Active Readers:\n");
        !           232:             for (reader_entry = vreader_list_get_first(list); reader_entry;
        !           233:                  reader_entry = vreader_list_get_next(reader_entry)) {
        !           234:                 VReader *reader = vreader_list_get_reader(reader_entry);
        !           235:                 vreader_id_t reader_id;
        !           236:                 reader_id = vreader_get_id(reader);
        !           237:                 if (reader_id == -1) {
        !           238:                     continue;
        !           239:                 }
        !           240:                 /* be nice and signal card removal first (qemu probably should
        !           241:                  * do this itself) */
        !           242:                 if (vreader_card_is_present(reader) == VREADER_OK) {
        !           243:                     send_msg(VSC_CardRemove, reader_id, NULL, 0);
        !           244:                 }
        !           245:                 send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
        !           246:             }
        !           247:             exit(0);
        !           248:         } else if (strncmp(string, "insert", 6) == 0) {
        !           249:             if (string[6] == ' ') {
        !           250:                 reader_id = get_id_from_string(&string[7], reader_id);
        !           251:             }
        !           252:             reader = vreader_get_reader_by_id(reader_id);
        !           253:             if (reader != NULL) {
        !           254:                 error = vcard_emul_force_card_insert(reader);
        !           255:                 printf("insert %s, returned %d\n",
        !           256:                        reader ? vreader_get_name(reader)
        !           257:                        : "invalid reader", error);
        !           258:             } else {
        !           259:                 printf("no reader by id %d found\n", reader_id);
        !           260:             }
        !           261:         } else if (strncmp(string, "remove", 6) == 0) {
        !           262:             if (string[6] == ' ') {
        !           263:                 reader_id = get_id_from_string(&string[7], reader_id);
        !           264:             }
        !           265:             reader = vreader_get_reader_by_id(reader_id);
        !           266:             if (reader != NULL) {
        !           267:                 error = vcard_emul_force_card_remove(reader);
        !           268:                 printf("remove %s, returned %d\n",
        !           269:                         reader ? vreader_get_name(reader)
        !           270:                         : "invalid reader", error);
        !           271:             } else {
        !           272:                 printf("no reader by id %d found\n", reader_id);
        !           273:             }
        !           274:         } else if (strncmp(string, "select", 6) == 0) {
        !           275:             if (string[6] == ' ') {
        !           276:                 reader_id = get_id_from_string(&string[7],
        !           277:                                                VSCARD_UNDEFINED_READER_ID);
        !           278:             }
        !           279:             if (reader_id != VSCARD_UNDEFINED_READER_ID) {
        !           280:                 reader = vreader_get_reader_by_id(reader_id);
        !           281:             }
        !           282:             if (reader) {
        !           283:                 printf("Selecting reader %d, %s\n", reader_id,
        !           284:                         vreader_get_name(reader));
        !           285:                 default_reader_id = reader_id;
        !           286:             } else {
        !           287:                 printf("Reader with id %d not found\n", reader_id);
        !           288:             }
        !           289:         } else if (strncmp(string, "debug", 5) == 0) {
        !           290:             if (string[5] == ' ') {
        !           291:                 verbose = get_id_from_string(&string[6], 0);
        !           292:             }
        !           293:             printf("debug level = %d\n", verbose);
        !           294:         } else if (strncmp(string, "list", 4) == 0) {
        !           295:             VReaderList *list = vreader_get_reader_list();
        !           296:             VReaderListEntry *reader_entry;
        !           297:             printf("Active Readers:\n");
        !           298:             for (reader_entry = vreader_list_get_first(list); reader_entry;
        !           299:                  reader_entry = vreader_list_get_next(reader_entry)) {
        !           300:                 VReader *reader = vreader_list_get_reader(reader_entry);
        !           301:                 vreader_id_t reader_id;
        !           302:                 reader_id = vreader_get_id(reader);
        !           303:                 if (reader_id == -1) {
        !           304:                     continue;
        !           305:                 }
        !           306:                 printf("%3d %s %s\n", reader_id,
        !           307:                        vreader_card_is_present(reader) == VREADER_OK ?
        !           308:                        "CARD_PRESENT" : "            ",
        !           309:                        vreader_get_name(reader));
        !           310:             }
        !           311:             printf("Inactive Readers:\n");
        !           312:             for (reader_entry = vreader_list_get_first(list); reader_entry;
        !           313:                  reader_entry = vreader_list_get_next(reader_entry)) {
        !           314:                 VReader *reader = vreader_list_get_reader(reader_entry);
        !           315:                 vreader_id_t reader_id;
        !           316:                 reader_id = vreader_get_id(reader);
        !           317:                 if (reader_id != -1) {
        !           318:                     continue;
        !           319:                 }
        !           320: 
        !           321:                 printf("INA %s %s\n",
        !           322:                        vreader_card_is_present(reader) == VREADER_OK ?
        !           323:                        "CARD_PRESENT" : "            ",
        !           324:                        vreader_get_name(reader));
        !           325:             }
        !           326:         } else if (*string != 0) {
        !           327:             printf("valid commands:\n");
        !           328:             printf("insert [reader_id]\n");
        !           329:             printf("remove [reader_id]\n");
        !           330:             printf("select reader_id\n");
        !           331:             printf("list\n");
        !           332:             printf("debug [level]\n");
        !           333:             printf("exit\n");
        !           334:         }
        !           335:     }
        !           336:     vreader_free(reader);
        !           337:     printf("> ");
        !           338:     fflush(stdout);
        !           339: }
        !           340: 
        !           341: 
        !           342: #define APDUBufSize 270
        !           343: 
        !           344: /* just for ease of parsing command line arguments. */
        !           345: #define MAX_CERTS 100
        !           346: 
        !           347: static int
        !           348: connect_to_qemu(
        !           349:     const char *host,
        !           350:     const char *port
        !           351: ) {
        !           352:     struct addrinfo hints;
        !           353:     struct addrinfo *server;
        !           354:     int ret;
        !           355: 
        !           356:     sock = qemu_socket(AF_INET, SOCK_STREAM, 0);
        !           357:     if (sock < 0) {
        !           358:         /* Error */
        !           359:         fprintf(stderr, "Error opening socket!\n");
        !           360:     }
        !           361: 
        !           362:     memset(&hints, 0, sizeof(struct addrinfo));
        !           363:     hints.ai_family = AF_UNSPEC;
        !           364:     hints.ai_socktype = SOCK_STREAM;
        !           365:     hints.ai_flags = 0;
        !           366:     hints.ai_protocol = 0;          /* Any protocol */
        !           367: 
        !           368:     ret = getaddrinfo(host, port, &hints, &server);
        !           369: 
        !           370:     if (ret != 0) {
        !           371:         /* Error */
        !           372:         fprintf(stderr, "getaddrinfo failed\n");
        !           373:         return 5;
        !           374:     }
        !           375: 
        !           376:     if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
        !           377:         /* Error */
        !           378:         fprintf(stderr, "Could not connect\n");
        !           379:         return 5;
        !           380:     }
        !           381:     if (verbose) {
        !           382:         printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
        !           383:     }
        !           384:     return sock;
        !           385: }
        !           386: 
        !           387: static int on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
        !           388: {
        !           389:     uint32_t *capabilities = (incoming->capabilities);
        !           390:     int num_capabilities =
        !           391:         1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
        !           392:     int i;
        !           393:     int rv;
        !           394:     pthread_t thread_id;
        !           395: 
        !           396:     incoming->version = ntohl(incoming->version);
        !           397:     if (incoming->version != VSCARD_VERSION) {
        !           398:         if (verbose > 0) {
        !           399:             printf("warning: host has version %d, we have %d\n",
        !           400:                 verbose, VSCARD_VERSION);
        !           401:         }
        !           402:     }
        !           403:     if (incoming->magic != VSCARD_MAGIC) {
        !           404:         printf("unexpected magic: got %d, expected %d\n",
        !           405:             incoming->magic, VSCARD_MAGIC);
        !           406:         return -1;
        !           407:     }
        !           408:     for (i = 0 ; i < num_capabilities; ++i) {
        !           409:         capabilities[i] = ntohl(capabilities[i]);
        !           410:     }
        !           411:     /* Future: check capabilities */
        !           412:     /* remove whatever reader might be left in qemu,
        !           413:      * in case of an unclean previous exit. */
        !           414:     send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
        !           415:     /* launch the event_thread. This will trigger reader adds for all the
        !           416:      * existing readers */
        !           417:     rv = pthread_create(&thread_id, NULL, event_thread, NULL);
        !           418:     if (rv < 0) {
        !           419:         perror("pthread_create");
        !           420:         return rv;
        !           421:     }
        !           422:     return 0;
        !           423: }
        !           424: 
        !           425: int
        !           426: main(
        !           427:     int argc,
        !           428:     char *argv[]
        !           429: ) {
        !           430:     char *qemu_host;
        !           431:     char *qemu_port;
        !           432:     VSCMsgHeader mhHeader;
        !           433:     VSCMsgError *error_msg;
        !           434: 
        !           435:     int rv;
        !           436:     int dwSendLength;
        !           437:     int dwRecvLength;
        !           438:     uint8_t pbRecvBuffer[APDUBufSize];
        !           439:     uint8_t pbSendBuffer[APDUBufSize];
        !           440:      VReaderStatus reader_status;
        !           441:     VReader *reader = NULL;
        !           442:     VCardEmulOptions *command_line_options = NULL;
        !           443: 
        !           444:     char *cert_names[MAX_CERTS];
        !           445:     char *emul_args = NULL;
        !           446:     int cert_count = 0;
        !           447:     int c;
        !           448: 
        !           449:     while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
        !           450:         switch (c) {
        !           451:         case 'c':
        !           452:             if (cert_count >= MAX_CERTS) {
        !           453:                 printf("too many certificates (max = %d)\n", MAX_CERTS);
        !           454:                 exit(5);
        !           455:             }
        !           456:             cert_names[cert_count++] = optarg;
        !           457:             break;
        !           458:         case 'e':
        !           459:             emul_args = optarg;
        !           460:             break;
        !           461:         case 'p':
        !           462:             print_usage();
        !           463:             exit(4);
        !           464:             break;
        !           465:         case 'd':
        !           466:             verbose = get_id_from_string(optarg, 1);
        !           467:             break;
        !           468:         }
        !           469:     }
        !           470: 
        !           471:     if (argc - optind != 2) {
        !           472:         print_usage();
        !           473:         exit(4);
        !           474:     }
        !           475: 
        !           476:     if (cert_count > 0) {
        !           477:         char *new_args;
        !           478:         int len, i;
        !           479:         /* if we've given some -c options, we clearly we want do so some
        !           480:          * software emulation.  add that emulation now. this is NSS Emulator
        !           481:          * specific */
        !           482:         if (emul_args == NULL) {
        !           483:             emul_args = (char *)"db=\"/etc/pki/nssdb\"";
        !           484:         }
        !           485: #define SOFT_STRING ",soft=(,Virtual Reader,CAC,,"
        !           486:              /* 2 == close paren & null */
        !           487:         len = strlen(emul_args) + strlen(SOFT_STRING) + 2;
        !           488:         for (i = 0; i < cert_count; i++) {
        !           489:             len += strlen(cert_names[i])+1; /* 1 == comma */
        !           490:         }
        !           491:         new_args = qemu_malloc(len);
        !           492:         strcpy(new_args, emul_args);
        !           493:         strcat(new_args, SOFT_STRING);
        !           494:         for (i = 0; i < cert_count; i++) {
        !           495:             strcat(new_args, cert_names[i]);
        !           496:             strcat(new_args, ",");
        !           497:         }
        !           498:         strcat(new_args, ")");
        !           499:         emul_args = new_args;
        !           500:     }
        !           501:     if (emul_args) {
        !           502:         command_line_options = vcard_emul_options(emul_args);
        !           503:     }
        !           504: 
        !           505:     qemu_host = strdup(argv[argc - 2]);
        !           506:     qemu_port = strdup(argv[argc - 1]);
        !           507:     sock = connect_to_qemu(qemu_host, qemu_port);
        !           508: 
        !           509:     qemu_mutex_init(&write_lock);
        !           510:     qemu_mutex_init(&pending_reader_lock);
        !           511:     qemu_cond_init(&pending_reader_condition);
        !           512: 
        !           513:     vcard_emul_init(command_line_options);
        !           514: 
        !           515:     printf("> ");
        !           516:     fflush(stdout);
        !           517: 
        !           518:     /* Send init message, Host responds (and then we send reader attachments) */
        !           519:     VSCMsgInit init = {
        !           520:         .version = htonl(VSCARD_VERSION),
        !           521:         .magic = VSCARD_MAGIC,
        !           522:         .capabilities = {0}
        !           523:     };
        !           524:     send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init));
        !           525: 
        !           526:     do {
        !           527:         fd_set fds;
        !           528: 
        !           529:         FD_ZERO(&fds);
        !           530:         FD_SET(1, &fds);
        !           531:         FD_SET(sock, &fds);
        !           532: 
        !           533:         /* waiting on input from the socket */
        !           534:         rv = select(sock+1, &fds, NULL, NULL, NULL);
        !           535:         if (rv < 0) {
        !           536:             /* handle error */
        !           537:             perror("select");
        !           538:             return 7;
        !           539:         }
        !           540:         if (FD_ISSET(1, &fds)) {
        !           541:             do_command();
        !           542:         }
        !           543:         if (!FD_ISSET(sock, &fds)) {
        !           544:             continue;
        !           545:         }
        !           546: 
        !           547:         rv = read(sock, &mhHeader, sizeof(mhHeader));
        !           548:         if (rv < sizeof(mhHeader)) {
        !           549:             /* Error */
        !           550:             if (rv < 0) {
        !           551:                 perror("header read error\n");
        !           552:             } else {
        !           553:                 fprintf(stderr, "header short read %d\n", rv);
        !           554:             }
        !           555:             return 8;
        !           556:         }
        !           557:         mhHeader.type = ntohl(mhHeader.type);
        !           558:         mhHeader.reader_id = ntohl(mhHeader.reader_id);
        !           559:         mhHeader.length = ntohl(mhHeader.length);
        !           560:         if (verbose) {
        !           561:             printf("Header: type=%d, reader_id=%d length=%d (0x%x)\n",
        !           562:                     mhHeader.type, mhHeader.reader_id, mhHeader.length,
        !           563:                                                mhHeader.length);
        !           564:         }
        !           565:         switch (mhHeader.type) {
        !           566:         case VSC_APDU:
        !           567:         case VSC_Flush:
        !           568:         case VSC_Error:
        !           569:         case VSC_Init:
        !           570:             rv = read(sock, pbSendBuffer, mhHeader.length);
        !           571:             break;
        !           572:         default:
        !           573:             fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
        !           574:             return 0;
        !           575:         }
        !           576:         switch (mhHeader.type) {
        !           577:         case VSC_APDU:
        !           578:             if (rv < 0) {
        !           579:                 /* Error */
        !           580:                 fprintf(stderr, "read error\n");
        !           581:                 close(sock);
        !           582:                 return 8;
        !           583:             }
        !           584:             if (verbose) {
        !           585:                 printf(" recv APDU: ");
        !           586:                 print_byte_array(pbSendBuffer, mhHeader.length);
        !           587:             }
        !           588:             /* Transmit recieved APDU */
        !           589:             dwSendLength = mhHeader.length;
        !           590:             dwRecvLength = sizeof(pbRecvBuffer);
        !           591:             reader = vreader_get_reader_by_id(mhHeader.reader_id);
        !           592:             reader_status = vreader_xfr_bytes(reader,
        !           593:                 pbSendBuffer, dwSendLength,
        !           594:                 pbRecvBuffer, &dwRecvLength);
        !           595:             if (reader_status == VREADER_OK) {
        !           596:                 mhHeader.length = dwRecvLength;
        !           597:                 if (verbose) {
        !           598:                     printf(" send response: ");
        !           599:                     print_byte_array(pbRecvBuffer, mhHeader.length);
        !           600:                 }
        !           601:                 send_msg(VSC_APDU, mhHeader.reader_id,
        !           602:                          pbRecvBuffer, dwRecvLength);
        !           603:             } else {
        !           604:                 rv = reader_status; /* warning: not meaningful */
        !           605:                 send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
        !           606:             }
        !           607:             vreader_free(reader);
        !           608:             reader = NULL; /* we've freed it, don't use it by accident
        !           609:                               again */
        !           610:             break;
        !           611:         case VSC_Flush:
        !           612:             /* TODO: actually flush */
        !           613:             send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
        !           614:             break;
        !           615:         case VSC_Error:
        !           616:             error_msg = (VSCMsgError *) pbSendBuffer;
        !           617:             if (error_msg->code == VSC_SUCCESS) {
        !           618:                 qemu_mutex_lock(&pending_reader_lock);
        !           619:                 if (pending_reader) {
        !           620:                     vreader_set_id(pending_reader, mhHeader.reader_id);
        !           621:                     vreader_free(pending_reader);
        !           622:                     pending_reader = NULL;
        !           623:                     qemu_cond_signal(&pending_reader_condition);
        !           624:                 }
        !           625:                 qemu_mutex_unlock(&pending_reader_lock);
        !           626:                 break;
        !           627:             }
        !           628:             printf("warning: qemu refused to add reader\n");
        !           629:             if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
        !           630:                 /* clear pending reader, qemu can't handle any more */
        !           631:                 qemu_mutex_lock(&pending_reader_lock);
        !           632:                 if (pending_reader) {
        !           633:                     pending_reader = NULL;
        !           634:                     /* make sure the event loop doesn't hang */
        !           635:                     qemu_cond_signal(&pending_reader_condition);
        !           636:                 }
        !           637:                 qemu_mutex_unlock(&pending_reader_lock);
        !           638:             }
        !           639:             break;
        !           640:         case VSC_Init:
        !           641:             if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
        !           642:                 return -1;
        !           643:             }
        !           644:             break;
        !           645:         default:
        !           646:             printf("Default\n");
        !           647:             return 0;
        !           648:         }
        !           649:     } while (rv >= 0);
        !           650: 
        !           651:     return 0;
        !           652: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.