hidekey/host/hidekey.c
2012-03-09 16:10:54 +01:00

248 lines
5.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <libusb-1.0/libusb.h>
#include "../config.h"
const char *errorMsgs[] = {
"no error",
"write protection is enabled",
"string to long",
"invalid slot",
"unknown"
};
const char *writableStates[] = {
"no protection",
"true",
"false"
};
char * getPass(char *buffer, size_t size) {
char *r, *n;
struct termios oldt, newt;
int fd = fileno(stdin);
tcgetattr(fd, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(fd, TCSANOW, &newt);
r = fgets(buffer, size, stdin);
if (n = strrchr(buffer, '\n')) {
*n = '\0';
}
tcsetattr(fd, TCSANOW, &oldt);
return r;
}
char * getUser(char *buffer, size_t size) {
char *r, *n;
r = fgets(buffer, size, stdin);
if (n = strrchr(buffer, '\n')) {
*n = '\0';
}
return r;
}
int setSlot(struct libusb_device_handle *handle, uint16_t slotIndex, struct slot slot) {
return libusb_control_transfer(
handle,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, /* bmRequestType */
USBRQ_VENDOR_SET_SLOT, /* bRequest */
0, /* wValue */
slotIndex, /* wIndex */
(uint8_t *) &slot, /* data */
sizeof(struct slot), /* wLength */
500 /* timeout */
);
}
struct status getStatus(struct libusb_device_handle *handle) {
struct status stat;
libusb_control_transfer(
handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
USBRQ_VENDOR_GET_STATUS,
0,
0,
(uint8_t *) &stat,
sizeof(stat),
500
);
return stat;
}
int checkStatus(struct libusb_device_handle *handle) {
struct status stat = getStatus(handle);
if (stat.error != ERROR_SUCCESS) {
fprintf(stderr, "Error orccured: %s (%u)\n", errorMsgs[stat.error], stat.error);
return stat.error;
}
return EXIT_SUCCESS;
}
double decodeUsbBcd(uint16_t bcd) {
double result = 0;
result += ((bcd & 0x0f00) >> 8) * 1e-2;
result += ((bcd & 0xf000) >> 12) * 1e-1;
result += ((bcd & 0x000f) >> 0) * 1e0;
result += ((bcd & 0x00f0) >> 4) * 1e1;
return result;
}
int main(int argc, char *argv[]) {
struct libusb_device_handle *handle;
struct libusb_device_descriptor desc;
int r;
r = libusb_init(NULL);
if (r < 0) {
return EXIT_FAILURE;
}
/* search device */
handle = libusb_open_device_with_vid_pid(NULL, DEVICE_VID, DEVICE_PID);
if (handle == NULL) {
fprintf(stderr, "failed to open the device\n");
return EXIT_FAILURE;
}
/* get status */
struct status stat = getStatus(handle);
r = libusb_get_device_descriptor(libusb_get_device(handle), &desc);
if (r < 0) {
fprintf(stderr, "failed to get device descriptor\n");
return EXIT_FAILURE;
}
if (argc == 1) {
printf("usage: hidekey COMMAND [OPTIONS]\n");
printf(" available COMMANDs and their specific OPTIONS:\n\n");
printf(" info\n\tshow information about plugged in keys\n\n");
printf(" set SLOT TYPE USER [PASSWORD]\n\tstore new user/password combination on stick\n\n");
printf(" clear SLOT\n\tdelete password from SLOT\n\n");
printf(" reset\n\tprune all passwords and reset startup counter\n\n");
printf(" serial SERIAL\tset new serial (expert option)\n\n");
printf("hidekey 0.1 - HIDeKey setup utility\n");
printf("by Steffen Vogel <stv0g@0l.de>\n");
printf("please send bugreports to http://bugs.0l.de\n");
}
else if (argc == 2 && strcmp(argv[1], "info") == 0) {
/* get product string */
char productString[255];
libusb_get_string_descriptor_ascii(handle, desc.iProduct, productString, 255);
printf("name: %s\n", productString);
/* get product version */
printf("version: %.2f\n", decodeUsbBcd(desc.bcdDevice)); /* decode bcd */
/* get serial no */
char serialNumber[255];
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, serialNumber, 255);
printf("serial: %s\n", serialNumber);
/* get status struct */
printf("startups: %u\n", stat.counter);
printf("writable: %s\n", writableStates[stat.writable]);// ? "true" : "false");
printf("slots: %u\n", stat.maxSlots);
printf("max user length: %u\n", stat.maxUserLen);
printf("max password length: %u\n", stat.maxPassLen);
printf("max serial length: %u\n", stat.maxSerialLen);
}
else if (argc == 2 && strcmp(argv[1], "reset") == 0) {
libusb_control_transfer(
handle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
USBRQ_VENDOR_RESET,
0,
0,
NULL,
0,
500
);
}
else if (argc == 3 && strcmp(argv[1], "serial") == 0) {
size_t len = strlen(argv[2]);
libusb_control_transfer(
handle,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, /* bmRequestType */
USBRQ_VENDOR_SET_SERIAL,/* bRequest */
0, /* wValue */
0, /* wIndex */
(uint8_t *) argv[2], /* data */
len, /* wLength (string is not \0-terminated!) */
500 /* timeout */
);
}
else if (argc == 3 && strcmp(argv[1], "clear") == 0) {
uint16_t slotIndex = atoi(argv[2]);
struct slot slot = { SLOT_EMPTY };
setSlot(handle, slotIndex, slot);
}
else if (argc >= 4 && strcmp(argv[1], "set") == 0) {
uint16_t slotIndex = atoi(argv[2]);
uint8_t type = atoi(argv[3]);
struct slot slot = {
.type = type,
.options = SKIP_USER | SKIP_DELIMITER | SKIP_RETURN,
.delimiter = '\t'
}; // TODO make configurable
if (argc >= 5) {
strncpy(slot.user, argv[4], MAX_USER_LEN);
}
else {
printf("User: ");
getUser(slot.user, MAX_PASS_LEN);
}
if (type == SLOT_STRING) {
if (argc == 6) {
strncpy(slot.pass.string, argv[5], MAX_PASS_LEN);
}
else {
char tmpPass[MAX_PASS_LEN];
printf("Password: ");
getPass(slot.pass.string, MAX_PASS_LEN);
printf("\nRepeat password: ");
getPass(tmpPass, MAX_PASS_LEN);
printf("\n");
if (strcmp(slot.pass.string, tmpPass) != 0) {
fprintf(stderr, "Passwords didn't match!\n");
return EXIT_FAILURE;
}
}
}
setSlot(handle, slotIndex, slot);
}
else {
fprintf(stderr, "Unknown command\n");
return EXIT_FAILURE;
}
return checkStatus(handle);
}