/* * Initialize the device */ static int eg_open(ifd_reader_t * reader, const char *device_name) { ifd_device_t *dev; ifd_device_params_t params; ifd_debug(1, "device=%s", device_name); reader->name = "Schlumberger E-Gate"; reader->nslots = 1; if (!(dev = ifd_device_open(device_name))) return -1; if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { ct_error("egate: device %s is not a USB device", device_name); ifd_device_close(dev); return -1; } params = dev->settings; params.usb.interface = 0; if (ifd_device_set_parameters(dev, ¶ms) < 0) { ct_error("egate: setting parameters failed", device_name); ifd_device_close(dev); return -1; } reader->device = dev; return 0; }
/* * Initialize the device */ static int epass3k_open(ifd_reader_t * reader, const char *device_name) { ifd_device_t *dev; ifd_device_params_t params; ifd_debug(1, "%s:%d epass3k_open()", __FILE__, __LINE__); reader->name = "FT SCR2000A"; /* ePass3000 reader name */ reader->nslots = 1; if (!(dev = ifd_device_open(device_name))) return -1; if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { ct_error("ePass3000: device %s is not a USB device", device_name); ifd_device_close(dev); return -1; } params = dev->settings; params.usb.ep_o = USB_BULK_OUT; params.usb.ep_i = USB_BULK_IN; if (ifd_device_set_parameters(dev, ¶ms) < 0) { ct_error("ePass3000: setting parameters failed", device_name); ifd_device_close(dev); return -1; } reader->device = dev; dev->timeout = TIMEOUT; return 0; }
/* * Initialize a reader and open the device */ ifd_reader_t *ifd_open(const char *driver_name, const char *device_name) { const ifd_driver_t *driver; ifd_reader_t *reader; ifd_debug(1, "trying to open %s@%s", driver_name, device_name); driver = ifd_driver_get(driver_name); if (driver == NULL) { ct_error("%s: driver not available", driver_name); return NULL; } reader = (ifd_reader_t *) calloc(1, sizeof(*reader)); if (!reader) { ct_error("out of memory"); return NULL; } reader->driver = driver; if (driver->ops->open && driver->ops->open(reader, device_name) < 0) { ct_error("%s: initialization failed (driver %s)", device_name, driver->name); free(reader); return NULL; } return reader; }
static int ifd_recv_atr(ifd_device_t * dev, ct_buf_t * bp, unsigned int count, int revert_bits) { unsigned char *buf; unsigned int n; if (count > ct_buf_tailroom(bp)) { ct_error("ATR buffer too small"); return -1; } buf = (unsigned char *)ct_buf_tail(bp); for (n = 0; n < count; n++) { if (ifd_device_recv(dev, buf + n, 1, 1000) < 0) { ct_error("failed to receive ATR"); return -1; } } if (revert_bits) ifd_revert_bits(buf, count); /* Advance tail pointer */ ct_buf_put(bp, NULL, count); return count; }
/* * Initialize the device */ static int starkey_open(ifd_reader_t * reader, const char *device_name) { ifd_device_t *dev; ifd_device_params_t params; reader->name = "G&D Starkey 100"; reader->nslots = 1; if (!(dev = ifd_device_open(device_name))) return -1; if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) { ct_error("starkey: device %s is not a USB device", device_name); ifd_device_close(dev); return -1; } params = dev->settings; params.usb.interface = 0; if (ifd_device_set_parameters(dev, ¶ms) < 0) { ct_error("starkey: setting parameters failed", device_name); ifd_device_close(dev); return -1; } reader->device = dev; return 0; }
/* * Open device control status interface */ static int open_cntrl0stat(char *name) { /* Open cntrl0stat to retrieve control pipe status. */ if (!cntrl0stat_fd) { char *cntrl0stat; if ((cntrl0stat = calloc(1, strlen(name) + 5)) == NULL) { ct_error("out of memory"); return -1; } strcpy(cntrl0stat, name); strcat(cntrl0stat, "stat"); ifd_debug(6, "open_cntrl0stat: open control pipe status: \"%s\"", cntrl0stat); if ((cntrl0stat_fd = open(cntrl0stat, O_RDONLY | O_EXCL)) < 0) { ifd_debug(6, "open_cntrl0stat: Error opening \"%s\": %s", cntrl0stat, strerror(errno)); free(cntrl0stat); return 0; } free(cntrl0stat); ifd_debug(6, "open_cntrl0stat: cntrl0stat_fd=%d", cntrl0stat_fd); } return 1; }
/* * Send/receive block */ static int t1_xcv(t1_state_t * t1, unsigned char *block, size_t slen, size_t rmax) { ifd_protocol_t *prot = &t1->base; unsigned int rlen, timeout; int n, m; if (ct_config.debug >= 3) ifd_debug(3, "sending %s", ct_hexdump(block, slen)); n = ifd_send_command(prot, block, slen); if (n < 0) return n; /* Maximum amount of data we'll receive - some devices * such as the eToken need this. If you request more, it'll * just barf */ rlen = 3 + t1->ifsd + t1->rc_bytes; /* timeout. For now our WTX treatment is very dumb */ timeout = t1->timeout + 1000 * t1->wtx; t1->wtx = 0; if (t1->block_oriented) { /* Note - Linux USB seems to have an off by one error, you * actually need the + 1 to get the RC byte */ rlen++; if (rlen < rmax) rmax = rlen; /* Get the response en bloc */ n = ifd_recv_response(prot, block, rmax, timeout); if (n >= 0) { m = block[2] + 3 + t1->rc_bytes; if (m < n) n = m; } } else { /* Get the header */ if (ifd_recv_response(prot, block, 3, timeout) < 0) return -1; n = block[2] + t1->rc_bytes; if (n + 3 > rmax || block[2] >= 254) { ct_error("receive buffer too small"); return -1; } /* Now get the rest */ if (ifd_recv_response(prot, block + 3, n, t1->timeout) < 0) return -1; n += 3; } if (n >= 0 && ct_config.debug >= 3) ifd_debug(3, "received %s", ct_hexdump(block, n)); return n; }
/* * Get/set parmaters for T1 protocol */ static int t1_set_param(ifd_protocol_t * prot, int type, long value) { t1_state_t *t1 = (t1_state_t *) prot; switch (type) { case IFD_PROTOCOL_RECV_TIMEOUT: t1->timeout = value; break; case IFD_PROTOCOL_BLOCK_ORIENTED: t1->block_oriented = value; break; case IFD_PROTOCOL_T1_CHECKSUM_LRC: case IFD_PROTOCOL_T1_CHECKSUM_CRC: t1_set_checksum(t1, type); break; case IFD_PROTOCOL_T1_IFSC: t1->ifsc = value; break; case IFD_PROTOCOL_T1_IFSD: t1->ifsd = value; break; default: ct_error("Unsupported parameter %d", type); return -1; } return 0; }
/* * Eat initial white space from buffer */ static int skipws(void) { unsigned int m, n, in_comment = 0; char *s; again: s = (char *)ct_buf_head(&config_buf); n = ct_buf_avail(&config_buf); for (m = 0; m < n; m++, s++) { if (*s == '#') { in_comment = 1; } else if (!in_comment && !isspace((int)*s)) { break; } else if (*s == '\n') { config_line++; in_comment = 0; } } ct_buf_get(&config_buf, NULL, m); if (in_comment) { if (ct_buf_read(&config_buf, config_fd) < 0) { ct_error("%s: error while reading file: %m", config_filename); return -1; } goto again; } return 0; }
/* * Send/receive APDU to the ICC */ int ifd_card_command(ifd_reader_t * reader, unsigned int idx, const void *sbuf, size_t slen, void *rbuf, size_t rlen) { ifd_slot_t *slot; if (idx > reader->nslots) return -1; /* XXX handle driver specific methods of transmitting * commands */ slot = &reader->slot[idx]; if (slot->proto == NULL) { ct_error("No communication protocol selected"); return -1; } /* An application is talking to the card. Prevent * automatic card status updates from slowing down * things */ slot->next_update = time(NULL) + 1; return ifd_protocol_transceive(slot->proto, slot->dad, sbuf, slen, rbuf, rlen); }
/* * Open device status interface */ static int open_devstat(char *name) { /* Open devstat to retrieve control pipe status. */ if (!devstat_fd) { char *devstat; if ((devstat = calloc(1, strlen(name) + 2)) == NULL) { ct_error("out of memory"); return IFD_ERROR_NO_MEMORY; } strcpy(devstat, name); strcpy(devstat + strlen(name) - 6, "devstat"); ifd_debug(6, "open_devstat: open device status: \"%s\"", devstat); if ((devstat_fd = open(devstat, O_RDONLY | O_EXCL | O_NONBLOCK)) < 0) { ifd_debug(6, "open_devstat: Error opening \"%s\": %s", devstat, strerror(errno)); free(devstat); return -1; } free(devstat); ifd_debug(6, "open_cntrl0stat: devstat_fd=%d", devstat_fd); } return 0; }
/* * Try to establish a lock */ int ifdhandler_lock(ct_socket_t * sock, int slot, int type, ct_lock_handle * res) { ct_lock_t *l; int rc; /* See if we have a locking conflict */ if ((rc = ifdhandler_check_lock(sock, slot, type)) < 0) return rc; /* No conflict - grant lock and record this fact */ l = (ct_lock_t *) calloc(1, sizeof(*l)); if (!l) { ct_error("out of memory"); return IFD_ERROR_NO_MEMORY; } l->exclusive = (type == IFD_LOCK_EXCLUSIVE); l->uid = sock->client_uid; l->handle = lock_handle++; l->owner = sock; l->slot = slot; l->next = locks; locks = l; ifd_debug(1, "granted %s lock %u for slot %u by uid=%u", l->exclusive ? "excl" : "shared", l->handle, l->slot, l->uid); *res = l->handle; return 0; }
/* * Reset - nothing to be done? * We should do something to make it come back with all state zapped */ static int starkey_card_reset(ifd_reader_t * reader, int slot, void *atr, size_t size) { ifd_device_t *dev = reader->device; unsigned char buffer[32]; int rc, atrlen; ifd_usb_capture_t *cap; rc = ifd_usb_begin_capture(dev, IFD_USB_URB_TYPE_INTERRUPT, 0x81, sizeof(buffer), &cap); if (rc < 0) return rc; rc = ifd_usb_capture(dev, cap, buffer, sizeof(buffer), STARKEY_TIMEOUT); if (rc <= 0) { ct_error("starkey: failed to activate token"); return -1; } memcpy(atr, buffer, rc); atrlen = rc; return atrlen; }
int ria_svc_listen(const char *address, int trusted) { ct_socket_t *sock; int rc; sock = ct_socket_new(1024); if ((rc = ct_socket_listen(sock, address, 0666)) < 0) { ct_error("Cannot bind to network address \"%s\"\n", address); ct_socket_free(sock); return rc; } sock->recv = ria_svc_accept; sock->send = NULL; if (trusted) { sock->process = ria_svc_app_handler; sock->close = ria_svc_app_close; } else { sock->process = ria_svc_dev_handler; sock->close = ria_svc_dev_close; } ct_mainloop_add_socket(sock); return 0; }
/* * Parse the ifd config file */ int ifd_config_parse(const char *filename) { char buffer[512]; int rc; if ((config_filename = filename) == NULL) config_filename = OPENCT_CONF_PATH; /* If config file doesn't exist, quietly sneak out of here */ if ((config_fd = open(config_filename, O_RDONLY)) < 0) { if (errno == ENOENT) return 0; ct_error("Unable to open %s: %m", filename); return -1; } /* Init parse buffer. */ ct_buf_init(&config_buf, buffer, sizeof(buffer)); config_line = 1; config_top.name = "<config>"; rc = conf_parse_group(&config_top, END_OF_FILE); close(config_fd); config_fd = -1; if (ct_config.debug > 2) conf_dump(&config_top, 0); return rc; }
int ifd_sysdep_usb_begin_capture(ifd_device_t * dev, int type, int ep, size_t maxpacket, ifd_usb_capture_t ** capret) { ifd_usb_capture_t *cap; int direction = (ep & USB_EP_DIR_MASK) == USB_EP_DIR_IN ? 1 : 0; int endpoint = (ep & ~USB_EP_DIR_MASK); if (!(cap = (ifd_usb_capture_t *) calloc(1, sizeof(*cap) + maxpacket))) { ct_error("out of memory"); return -1; } cap->type = type; cap->endpoint = ep; cap->maxpacket = maxpacket; if (!interfaces[0][endpoint].ep_fd[direction]) { if (open_ep(dev->name, 0, endpoint, direction, O_NONBLOCK)) { ct_debug ("ifd_sysdep_usb_begin_capture: opening endpoint failed"); return -1; } } *capret = cap; return 0; }
/* helper function */ static void do_charevod( int iSwitch ) { if( HB_ISCHAR( 1 ) ) { const char * pcString = hb_parc( 1 ); HB_SIZE sLen = hb_parclen( 1 ); char * pcResult; HB_SIZE sPos, sResultPos; if( sLen == 0 ) { int iArgErrorMode = ct_getargerrormode(); if( iArgErrorMode != CT_ARGERR_IGNORE ) ct_error( ( HB_USHORT ) iArgErrorMode, EG_ARG, iSwitch == DO_CHAREVOD_CHAREVEN ? CT_ERROR_CHAREVEN : CT_ERROR_CHARODD, NULL, HB_ERR_FUNCNAME, 0, EF_CANDEFAULT, HB_ERR_ARGS_BASEPARAMS ); hb_retc_null(); return; } pcResult = ( char * ) hb_xgrab( ( sLen + 1 ) / 2 ); if( iSwitch == DO_CHAREVOD_CHAREVEN ) sPos = 1; else sPos = 0; sResultPos = 0; for( ; sPos < sLen; sPos += 2 ) pcResult[ sResultPos++ ] = pcString[ sPos ]; if( sResultPos == 0 ) hb_retc_null(); else hb_retclen( pcResult, sResultPos ); hb_xfree( pcResult ); } else { PHB_ITEM pSubst = NULL; int iArgErrorMode = ct_getargerrormode(); if( iArgErrorMode != CT_ARGERR_IGNORE ) pSubst = ct_error_subst( ( HB_USHORT ) iArgErrorMode, EG_ARG, iSwitch == DO_CHAREVOD_CHAREVEN ? CT_ERROR_CHAREVEN : CT_ERROR_CHARODD, NULL, HB_ERR_FUNCNAME, 0, EF_CANSUBSTITUTE, HB_ERR_ARGS_BASEPARAMS ); if( pSubst != NULL ) hb_itemReturnRelease( pSubst ); else hb_retc_null(); } }
int ifd_sysdep_usb_bulk(ifd_device_t * dev, int ep, void *buffer, size_t len, long timeout) { int bytes_to_process; int bytes_processed; int direction = (ep & USB_EP_DIR_MASK) == USB_EP_DIR_IN ? 1 : 0; int endpoint = (ep & ~USB_EP_DIR_MASK); ct_debug("ifd_sysdep_usb_bulk: endpoint=%d direction=%d", endpoint, direction); if (open_ep(dev->name, 0, endpoint, direction, 0)) { ct_debug("ifd_sysdep_usb_bulk: opening endpoint failed"); return -1; } if (direction) { if ((bytes_to_process = read(interfaces[0][endpoint].ep_fd[direction], buffer, len)) < 0) { ifd_debug(6, "ifd_sysdep_usb_bulk: read failed: %s", strerror(errno)); ct_error("usb_bulk read failed: %s", strerror(errno)); return IFD_ERROR_COMM_ERROR; } ct_debug("ifd_sysdep_usb_bulk: read %d bytes", bytes_to_process); return bytes_to_process; } else { bytes_to_process = len; if ((bytes_processed = write(interfaces[0][endpoint].ep_fd[direction], buffer, bytes_to_process)) != bytes_to_process) { ifd_debug(6, "ifd_sysdep_usb_bulk: write failed: %s", strerror(errno)); ct_error("usb_bulk write failed: %s", strerror(errno)); return IFD_ERROR_COMM_ERROR; } ct_debug("ifd_sysdep_usb_bulk: wrote buffer[%d]=%s", bytes_processed, ct_hexdump(buffer, len)); return bytes_processed; } }
void ct_log_destination(const char *dest) { ct_log_init(); if (!strcmp(dest, "@stderr")) { log_dest = DST_STDERR; } else if (!strcmp(dest, "@syslog")) { log_dest = DST_SYSLOG; } else { log_dest = DST_STDERR; ct_error("log destination %s not implemented yet", dest); } }
static ria_peer_t *ria_peer_new(ct_socket_t * sock) { ria_peer_t *clnt; clnt = (ria_peer_t *) calloc(1, sizeof(ria_peer_t)); if (!clnt) { ct_error("out of memory"); return NULL; } clnt->sock = sock; ria_svc_link(clnt); return clnt; }
static int eg_set_protocol(ifd_reader_t * reader, int s, int proto) { ifd_slot_t *slot; ifd_protocol_t *p; ifd_debug(1, "proto=%d", proto); if (proto != IFD_PROTOCOL_T0 && proto != IFD_PROTOCOL_TRANSPARENT) { ct_error("%s: protocol %d not supported", reader->name, proto); return IFD_ERROR_NOT_SUPPORTED; } slot = &reader->slot[s]; p = ifd_protocol_new(IFD_PROTOCOL_TRANSPARENT, reader, slot->dad); if (p == NULL) { ct_error("%s: internal error", reader->name); return IFD_ERROR_GENERIC; } if (slot->proto) { ifd_protocol_free(slot->proto); slot->proto = NULL; } slot->proto = p; return 0; }
/* * Eject the card */ int ifd_card_eject(ifd_reader_t * reader, unsigned int idx, time_t timeout, const char *message) { const ifd_driver_t *drv = reader->driver; if (idx > reader->nslots) { ct_error("%s: invalid slot number %u", reader->name, idx); return -1; } if (!drv || !drv->ops || !drv->ops->card_eject) return 0; return drv->ops->card_eject(reader, idx, timeout, message); }
/* * Tokenizer */ static int get_token(char **tok) { static char buffer[512]; unsigned int m, n, copy, retry = 1; char *s; /* consume initial white space */ if (skipws() < 0) return -1; again: s = (char *)ct_buf_head(&config_buf); n = ct_buf_avail(&config_buf); if (n && issepa(*s)) { m = 1; } else { for (m = 0; !isspace((int)s[m]) && !issepa(s[m]) && m < n; m++) ; } /* If we hit the end of the buffer while scanning * for white space, read more data and try * again */ if (m >= n && retry) { if (ct_buf_read(&config_buf, config_fd) < 0) { ct_error("%s: error while reading file: %m", config_filename); return -1; } retry = 0; goto again; } if (m == 0) return -1; if ((copy = m) >= sizeof(buffer)) copy = sizeof(buffer) - 1; memcpy(buffer, s, copy); buffer[copy] = '\0'; ct_buf_get(&config_buf, NULL, m); ifd_debug(5, "ifd_config_parse: token=\"%s\"", buffer); *tok = buffer; return 0; }
/* * Config node handling */ static ifd_conf_node_t *conf_add_node(ifd_conf_node_t * parent, const char *name) { ifd_conf_node_t **p, *node; node = (ifd_conf_node_t *) calloc(1, sizeof(*node)); if (!node) { ct_error("out of memory"); return NULL; } node->name = strdup(name); for (p = &parent->children; *p; p = &(*p)->next) ; *p = node; return node; }
/* * Get/set parmaters for T1 protocol */ static int t0_set_param(ifd_protocol_t * prot, int type, long value) { t0_state_t *t0 = (t0_state_t *) prot; switch (type) { case IFD_PROTOCOL_RECV_TIMEOUT: t0->timeout = value; break; case IFD_PROTOCOL_BLOCK_ORIENTED: t0->block_oriented = value; break; default: ct_error("Unsupported parameter %d", type); return -1; } return 0; }
/* * Perform a PIN verification, using the reader's pin pad */ int ifd_card_perform_verify(ifd_reader_t * reader, unsigned int idx, time_t timeout, const char *message, const unsigned char *data, size_t data_len, unsigned char *resp, size_t resp_len) { const ifd_driver_t *drv = reader->driver; if (idx > reader->nslots) { ct_error("%s: invalid slot number %u", reader->name, idx); return -1; } if (!drv || !drv->ops || !drv->ops->perform_verify) return IFD_ERROR_NOT_SUPPORTED; return drv->ops->perform_verify(reader, idx, timeout, message, data, data_len, resp, resp_len); }
static int epass3k_set_protocol(ifd_reader_t * reader, int nslot, int proto) { ifd_debug(1, "%s:%d epass3k_set_protocol()", __FILE__, __LINE__); ifd_protocol_t *protocol; ifd_slot_t *slot; if (IFD_PROTOCOL_T0 != proto) return IFD_ERROR_NOT_SUPPORTED; slot = &reader->slot[nslot]; slot->proto = ifd_protocol_new(proto, reader, slot->dad); if (slot->proto == NULL) { ct_error("acr: unable to create protocol"); return -1; } ifd_protocol_set_parameter(slot->proto, IFD_PROTOCOL_BLOCK_ORIENTED, 1); return 1; }
static int eg_card_reset(ifd_reader_t * reader, int slot, void *atr, size_t size) { ifd_device_t *dev = reader->device; unsigned char buffer[EGATE_ATR_MAXSIZE]; int rc, atrlen, stat; ifd_debug(1, "called."); usleep(100000); /* Reset the device */ rc = ifd_usb_control(dev, EGATE_DIR_OUT, EGATE_CMD_RESET, 0, 0, NULL, 0, EG_TIMEOUT * 2); if (rc < 0) { failed: ct_error("egate: failed to activate token"); return IFD_ERROR_COMM_ERROR; } usleep(100000); rc = ifd_usb_control(reader->device, EGATE_DIR_IN, EGATE_CMD_STATUS, 0, 0, &stat, 1, EG_TIMEOUT); if (rc != 1) return IFD_ERROR_COMM_ERROR; /* Fetch the ATR */ usleep(100000); rc = ifd_usb_control(dev, EGATE_DIR_IN, EGATE_CMD_READ_ATR, 0, 0, buffer, EGATE_ATR_MAXSIZE, EG_TIMEOUT); if (rc <= 0) goto failed; if (rc > IFD_MAX_ATR_LEN) goto failed; if (rc > size) rc = size; atrlen = rc; memcpy(atr, buffer, atrlen); return atrlen; }
/* * Read/write synchronous ICCs */ int ifd_card_read_memory(ifd_reader_t * reader, unsigned int idx, unsigned short addr, unsigned char *rbuf, size_t rlen) { ifd_slot_t *slot; if (idx > reader->nslots) return -1; slot = &reader->slot[idx]; if (slot->proto == NULL) { ct_error("No communication protocol selected"); return -1; } /* An application is talking to the card. Prevent * automatic card status updates from slowing down * things */ slot->next_update = time(NULL) + 1; return ifd_protocol_read_memory(slot->proto, idx, addr, rbuf, rlen); }
static int t1_get_param(ifd_protocol_t * prot, int type, long *result) { t1_state_t *t1 = (t1_state_t *) prot; long value; switch (type) { case IFD_PROTOCOL_RECV_TIMEOUT: value = t1->timeout; break; case IFD_PROTOCOL_BLOCK_ORIENTED: value = t1->block_oriented; break; default: ct_error("Unsupported parameter %d", type); return -1; } if (result) *result = value; return 0; }