openscd code hasn't been used by anyone in years.
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2366 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
3d0f17bc95
commit
8e0d600b10
|
@ -1,15 +0,0 @@
|
||||||
# Process this file with automake to create Makefile.in
|
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
|
||||||
|
|
||||||
EXTRA_DIST = test.c
|
|
||||||
|
|
||||||
INCLUDES = @CPPFLAGS@ @CFLAGS_ASSUAN@
|
|
||||||
AM_LDFLAGS = @LIBOPENSC@
|
|
||||||
|
|
||||||
if HAVE_ASSUAN
|
|
||||||
noinst_PROGRAMS = openscd
|
|
||||||
endif
|
|
||||||
|
|
||||||
openscd_SOURCES = openscd.c commands.c mkdtemp.c openscd.h
|
|
||||||
openscd_LDADD = @GETOPTSRC@ @LIBASSUAN@ ../scrandom/libscrandom.la
|
|
|
@ -1,361 +0,0 @@
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <assuan.h>
|
|
||||||
#include <opensc/opensc.h>
|
|
||||||
#include <opensc/log.h>
|
|
||||||
#include <opensc/pkcs15.h>
|
|
||||||
#include "openscd.h"
|
|
||||||
|
|
||||||
static struct openscd_card * find_card(struct openscd_context *dctx,
|
|
||||||
sc_reader_t *reader,
|
|
||||||
int slot_id)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < dctx->card_count; i++) {
|
|
||||||
struct openscd_card *dcard = dctx->cards + i;
|
|
||||||
|
|
||||||
if (dcard->reader == reader && dcard->slot_id == slot_id)
|
|
||||||
return dcard;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct openscd_card * find_card_by_id(struct openscd_context *dctx,
|
|
||||||
int card_id)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < dctx->card_count; i++) {
|
|
||||||
struct openscd_card *dcard = dctx->cards + i;
|
|
||||||
|
|
||||||
if (dcard->card_id == card_id)
|
|
||||||
return dcard;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void card_inserted(struct openscd_context *dctx,
|
|
||||||
sc_reader_t *reader,
|
|
||||||
int slot_id)
|
|
||||||
{
|
|
||||||
int n = dctx->card_count;
|
|
||||||
int r;
|
|
||||||
sc_card_t *card;
|
|
||||||
struct sc_pkcs15_card *p15card;
|
|
||||||
|
|
||||||
dctx->cards = (struct openscd_card *) realloc(dctx->cards, (n + 1) * sizeof(struct openscd_card));
|
|
||||||
assert(dctx->cards != NULL);
|
|
||||||
memset(dctx->cards + n, 0, sizeof(struct openscd_card));
|
|
||||||
|
|
||||||
dctx->cards[n].reader = reader;
|
|
||||||
dctx->cards[n].slot_id = slot_id;
|
|
||||||
|
|
||||||
r = sc_connect_card(reader, slot_id, &card);
|
|
||||||
if (r) {
|
|
||||||
sc_error(dctx->ctx, "Unable to connect to card: %s\n", sc_strerror(r));
|
|
||||||
} else {
|
|
||||||
dctx->cards[n].card = card;
|
|
||||||
r = sc_pkcs15_bind(card, &p15card);
|
|
||||||
if (r) {
|
|
||||||
sc_error(dctx->ctx, "Error with PKCS #15 card: %s\n", sc_strerror(r));
|
|
||||||
} else
|
|
||||||
dctx->cards[n].p15card = p15card;
|
|
||||||
}
|
|
||||||
dctx->cards[n].card_id = dctx->card_id_number;
|
|
||||||
pthread_mutex_init(&dctx->cards[n].mutex, NULL);
|
|
||||||
dctx->card_id_number++;
|
|
||||||
dctx->card_count++;
|
|
||||||
fprintf(stderr, "Card %d inserted.\n", dctx->cards[n].card_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void card_removed(struct openscd_context *dctx,
|
|
||||||
struct openscd_card *dcard)
|
|
||||||
{
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
fprintf(stderr, "Card %d removed.\n", dcard->card_id);
|
|
||||||
if (dcard->p15card != NULL) {
|
|
||||||
sc_pkcs15_unbind(dcard->p15card);
|
|
||||||
dcard->p15card = NULL;
|
|
||||||
}
|
|
||||||
if (dcard->card != NULL) {
|
|
||||||
/* This should fail... */
|
|
||||||
sc_disconnect_card(dcard->card, SC_DISCONNECT_AND_EJECT);
|
|
||||||
dcard->card = NULL;
|
|
||||||
}
|
|
||||||
for (idx = 0; idx < dctx->card_count; idx++) {
|
|
||||||
if (dctx->cards + idx == dcard) {
|
|
||||||
memmove(dctx->cards, dctx->cards + idx + 1,
|
|
||||||
dctx->card_count - (idx + 1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(idx != dctx->card_count);
|
|
||||||
dctx->card_count--;
|
|
||||||
dctx->cards = (struct openscd_card *) realloc(dctx->cards, dctx->card_count * sizeof(struct openscd_card));
|
|
||||||
assert(dctx->cards != NULL || dctx->card_count == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_list_readers(ASSUAN_CONTEXT actx, char *line)
|
|
||||||
{
|
|
||||||
struct openscd_context *dctx = (struct openscd_context *) assuan_get_pointer(actx);
|
|
||||||
int i, r;
|
|
||||||
|
|
||||||
for (i = 0; i < dctx->ctx->reader_count; i++) {
|
|
||||||
char line[80];
|
|
||||||
|
|
||||||
snprintf(line, sizeof(line), "%s", dctx->ctx->reader[i]->name);
|
|
||||||
r = assuan_send_data(actx, line, strlen(line));
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_list_cards(ASSUAN_CONTEXT actx, char *line)
|
|
||||||
{
|
|
||||||
struct openscd_context *dctx = (struct openscd_context *) assuan_get_pointer(actx);
|
|
||||||
int i, r = 0;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&dctx->card_mutex);
|
|
||||||
for (i = 0; i < dctx->card_count; i++) {
|
|
||||||
char line[80];
|
|
||||||
|
|
||||||
snprintf(line, sizeof(line), "Card%d '%s' %d", dctx->cards[i].card_id,
|
|
||||||
dctx->cards[i].reader->name, dctx->cards[i].slot_id);
|
|
||||||
r = assuan_send_data(actx, line, strlen(line));
|
|
||||||
if (r)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&dctx->card_mutex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_get_objects(ASSUAN_CONTEXT actx, char *line)
|
|
||||||
{
|
|
||||||
struct openscd_context *dctx = (struct openscd_context *) assuan_get_pointer(actx);
|
|
||||||
struct openscd_card *dcard;
|
|
||||||
int card_id, obj_type, i, obj_count, r = 0;
|
|
||||||
struct sc_pkcs15_object *objs[32];
|
|
||||||
|
|
||||||
r = sscanf(line, "%X %X", &card_id, &obj_type);
|
|
||||||
if (r != 2)
|
|
||||||
return ASSUAN_Invalid_Command;
|
|
||||||
pthread_mutex_lock(&dctx->card_mutex);
|
|
||||||
dcard = find_card_by_id(dctx, card_id);
|
|
||||||
if (dcard != NULL)
|
|
||||||
pthread_mutex_lock(&dcard->mutex);
|
|
||||||
pthread_mutex_unlock(&dctx->card_mutex);
|
|
||||||
if (dcard == NULL)
|
|
||||||
return ASSUAN_Invalid_Card;
|
|
||||||
if (dcard->p15card == NULL) {
|
|
||||||
r = ASSUAN_No_PKCS15_App;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
obj_count = sc_pkcs15_get_objects(dcard->p15card, obj_type, objs, 32);
|
|
||||||
if (obj_count < 0) {
|
|
||||||
/* FIXME */
|
|
||||||
r = ASSUAN_Card_Error;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
for (i = 0; i < obj_count; i++) {
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
line = (char *) malloc(objs[i]->der.len * 2 + 2);
|
|
||||||
if (line == NULL)
|
|
||||||
return ASSUAN_Out_Of_Core;
|
|
||||||
sc_bin_to_hex(objs[i]->der.value, objs[i]->der.len,
|
|
||||||
line, objs[i]->der.len * 2 + 2, 0);
|
|
||||||
strcat(line, "\n");
|
|
||||||
r = assuan_send_data(actx, line, strlen(line));
|
|
||||||
free(line);
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
ret:
|
|
||||||
pthread_mutex_unlock(&dcard->mutex);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
const char *name;
|
|
||||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
|
||||||
} ctable[] = {
|
|
||||||
{ "LISTR", cmd_list_readers },
|
|
||||||
{ "LISTC", cmd_list_cards },
|
|
||||||
{ "GET_OBJ", cmd_get_objects },
|
|
||||||
{ "INPUT", NULL },
|
|
||||||
{ "OUTPUT", NULL },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int register_commands(ASSUAN_CONTEXT assuan_ctx)
|
|
||||||
{
|
|
||||||
int i, j, r;
|
|
||||||
|
|
||||||
for (i = j = 0; ctable[i].name != NULL; i++) {
|
|
||||||
r = assuan_register_command(assuan_ctx,
|
|
||||||
ctable[i].name, ctable[i].handler);
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
assuan_set_hello_line(assuan_ctx, "openscd ready");
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
assuan_register_reset_notify (ctx, reset_notify);
|
|
||||||
assuan_register_option_handler (ctx, option_handler);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void * sc_thread(void *arg)
|
|
||||||
{
|
|
||||||
struct openscd_thread_arg *targ = (struct openscd_thread_arg *) arg;
|
|
||||||
struct openscd_context *dctx = targ->dctx;
|
|
||||||
sc_reader_t *reader = targ->reader;
|
|
||||||
sc_context_t *ctx = dctx->ctx;
|
|
||||||
const int sleep_time = 200;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
free(arg);
|
|
||||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
|
||||||
for (;;) {
|
|
||||||
struct openscd_card *dcard;
|
|
||||||
|
|
||||||
r = sc_detect_card_presence(reader, 0);
|
|
||||||
if (r < 0) {
|
|
||||||
sc_perror(ctx, r, "Unable to detect card presence");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pthread_testcancel();
|
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
|
||||||
pthread_mutex_lock(&dctx->card_mutex);
|
|
||||||
dcard = find_card(dctx, reader, 0);
|
|
||||||
if (r == 1) {
|
|
||||||
if (dcard == NULL)
|
|
||||||
card_inserted(dctx, reader, 0);
|
|
||||||
} else {
|
|
||||||
if (dcard != NULL) {
|
|
||||||
pthread_mutex_lock(&dcard->mutex);
|
|
||||||
card_removed(dctx, dcard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&dctx->card_mutex);
|
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
|
||||||
usleep(sleep_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_cmd_stuff(struct openscd_context *dctx)
|
|
||||||
{
|
|
||||||
pthread_mutex_init(&dctx->card_mutex, NULL);
|
|
||||||
|
|
||||||
dctx->cmd_stuff_ok = 1;
|
|
||||||
dctx->card_count = 0;
|
|
||||||
dctx->thread_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cleanup_cmd_stuff(struct openscd_context *dctx)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!dctx->cmd_stuff_ok)
|
|
||||||
return;
|
|
||||||
for (i = 0; i < dctx->thread_count; i++) {
|
|
||||||
pthread_cancel(dctx->threads[i]);
|
|
||||||
pthread_join(dctx->threads[i], NULL);
|
|
||||||
}
|
|
||||||
free(dctx->threads);
|
|
||||||
|
|
||||||
pthread_mutex_destroy(&dctx->card_mutex);
|
|
||||||
|
|
||||||
for (i = 0; i < dctx->card_count; i++) {
|
|
||||||
struct openscd_card *dcard = dctx->cards + i;
|
|
||||||
|
|
||||||
if (dcard->p15card != NULL)
|
|
||||||
sc_pkcs15_unbind(dcard->p15card);
|
|
||||||
if (dcard->card != NULL)
|
|
||||||
sc_disconnect_card(dcard->card, SC_DISCONNECT_AND_RESET);
|
|
||||||
}
|
|
||||||
if (dctx->cards != NULL)
|
|
||||||
free(dctx->cards);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spawn_reader_threads(struct openscd_context *dctx)
|
|
||||||
{
|
|
||||||
int i, r, count;
|
|
||||||
|
|
||||||
if (dctx->ctx->reader_count == 0)
|
|
||||||
return;
|
|
||||||
count = dctx->ctx->reader_count;
|
|
||||||
dctx->threads = (pthread_t *) calloc(count, sizeof(pthread_t));
|
|
||||||
assert(dctx->threads != NULL);
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
struct openscd_thread_arg *arg;
|
|
||||||
|
|
||||||
arg = (struct openscd_thread_arg *) malloc(sizeof(struct openscd_thread_arg));
|
|
||||||
assert(arg != NULL);
|
|
||||||
arg->dctx = dctx;
|
|
||||||
arg->reader = dctx->ctx->reader[i];
|
|
||||||
r = pthread_create(dctx->threads + i, NULL, sc_thread, arg);
|
|
||||||
if (r) {
|
|
||||||
free(arg);
|
|
||||||
free(dctx->threads);
|
|
||||||
/* FIXME: Kill all the spawned threads */
|
|
||||||
die(1, "Unable to spawn thread: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dctx->thread_count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void command_handler(struct openscd_context *dctx)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
ASSUAN_CONTEXT assuan_ctx;
|
|
||||||
|
|
||||||
spawn_reader_threads(dctx);
|
|
||||||
|
|
||||||
if (dctx->socket_fd <= 0) {
|
|
||||||
int fds[2];
|
|
||||||
|
|
||||||
fds[0] = 0;
|
|
||||||
fds[1] = 1;
|
|
||||||
r = assuan_init_pipe_server(&assuan_ctx, fds);
|
|
||||||
} else
|
|
||||||
r = assuan_init_socket_server(&assuan_ctx, dctx->socket_fd);
|
|
||||||
if (r)
|
|
||||||
die(1, "Failed to initialize the server: %s\n",
|
|
||||||
assuan_strerror((AssuanError) r));
|
|
||||||
r = register_commands(assuan_ctx);
|
|
||||||
if (r)
|
|
||||||
die(1, "Failed to register commands with Assuan: %s\n",
|
|
||||||
assuan_strerror((AssuanError) r));
|
|
||||||
|
|
||||||
assuan_set_pointer(assuan_ctx, dctx);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
r = assuan_accept(assuan_ctx);
|
|
||||||
if (r == -1)
|
|
||||||
break;
|
|
||||||
if (r) {
|
|
||||||
sc_error(dctx->ctx, "Assuan accept problem: %s\n", assuan_strerror((AssuanError) r));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r = assuan_process(assuan_ctx);
|
|
||||||
if (r) {
|
|
||||||
sc_error(dctx->ctx, "Assuan processing failed: %s\n", assuan_strerror((AssuanError) r));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assuan_deinit_server(assuan_ctx);
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
/* mkdtemp.c - libc replacement function
|
|
||||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of GnuPG.
|
|
||||||
*
|
|
||||||
* GnuPG is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* GnuPG is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is a replacement function for mkdtemp in case the platform
|
|
||||||
we're building on (like mine!) doesn't have it. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <opensc/scrandom.h>
|
|
||||||
|
|
||||||
#ifdef MKDIR_TAKES_ONE_ARG
|
|
||||||
# undef mkdir
|
|
||||||
# define mkdir(a,b) mkdir(a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char *mkdtemp(char *tmpl)
|
|
||||||
{
|
|
||||||
int attempts, idx, count = 0;
|
|
||||||
char *ch;
|
|
||||||
|
|
||||||
idx = strlen(tmpl);
|
|
||||||
|
|
||||||
/* Walk backwards to count all the Xes */
|
|
||||||
while (idx > 0 && tmpl[idx - 1] == 'X') {
|
|
||||||
count++;
|
|
||||||
idx--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ch = &tmpl[idx];
|
|
||||||
|
|
||||||
/* Try 4 times to make the temp directory */
|
|
||||||
for (attempts = 0; attempts < 4; attempts++) {
|
|
||||||
int remaining = count;
|
|
||||||
char *marker = ch;
|
|
||||||
unsigned char *randombits;
|
|
||||||
|
|
||||||
idx = 0;
|
|
||||||
|
|
||||||
/* Using really random bits is probably overkill here. The
|
|
||||||
worst thing that can happen with a directory name collision
|
|
||||||
is that the function will return an error. */
|
|
||||||
|
|
||||||
randombits = (unsigned char *) malloc(4 * remaining);
|
|
||||||
assert(randombits != NULL);
|
|
||||||
assert(scrandom_get_data(randombits, 4 * remaining) ==
|
|
||||||
4 * remaining);
|
|
||||||
|
|
||||||
while (remaining > 1) {
|
|
||||||
sprintf(marker, "%02X", randombits[idx++]);
|
|
||||||
marker += 2;
|
|
||||||
remaining -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Any leftover Xes? get_random_bits rounds up to full bytes,
|
|
||||||
so this is safe. */
|
|
||||||
if (remaining > 0)
|
|
||||||
sprintf(marker, "%X", randombits[idx] & 0xF);
|
|
||||||
|
|
||||||
free(randombits);
|
|
||||||
|
|
||||||
if (mkdir(tmpl, 0700) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attempts == 4)
|
|
||||||
return NULL; /* keeps the errno from mkdir, whatever it is */
|
|
||||||
|
|
||||||
return tmpl;
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <assuan.h>
|
|
||||||
#include <opensc/opensc.h>
|
|
||||||
#include <opensc/pkcs15.h>
|
|
||||||
#include "openscd.h"
|
|
||||||
|
|
||||||
struct openscd_context *dctx = NULL;
|
|
||||||
|
|
||||||
int opt_pipe = 0;
|
|
||||||
|
|
||||||
void cleanup(void)
|
|
||||||
{
|
|
||||||
if (dctx == NULL)
|
|
||||||
return;
|
|
||||||
cleanup_cmd_stuff(dctx);
|
|
||||||
if (dctx->ctx != NULL)
|
|
||||||
sc_release_context(dctx->ctx);
|
|
||||||
if (dctx->socket_name != NULL) {
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (dctx->socket_fd >= 0)
|
|
||||||
close(dctx->socket_fd);
|
|
||||||
unlink(dctx->socket_name);
|
|
||||||
if ((p = strrchr(dctx->socket_name, '/')) != NULL) {
|
|
||||||
*p = '\0';
|
|
||||||
rmdir(dctx->socket_name);
|
|
||||||
}
|
|
||||||
free(dctx->socket_name);
|
|
||||||
}
|
|
||||||
free(dctx);
|
|
||||||
dctx = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void die(int return_code, const char *errmsg, ...)
|
|
||||||
{
|
|
||||||
if (errmsg != NULL) {
|
|
||||||
va_list ap;
|
|
||||||
char *p = (char *) malloc(strlen(errmsg)+2);
|
|
||||||
|
|
||||||
strcpy(p, errmsg);
|
|
||||||
strcat(p, "\n");
|
|
||||||
va_start(ap, errmsg);
|
|
||||||
vfprintf(stderr, p, ap);
|
|
||||||
free(p);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
cleanup();
|
|
||||||
|
|
||||||
exit(return_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_socket(void)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
const char *socket_dir = "/tmp/openscd-XXXXXX";
|
|
||||||
const char *socket_file = "socket";
|
|
||||||
char *socket_name;
|
|
||||||
struct sockaddr_un serv_addr;
|
|
||||||
|
|
||||||
socket_name = (char *) malloc(strlen(socket_dir)+strlen(socket_file)+2);
|
|
||||||
assert(socket_name != NULL);
|
|
||||||
strcpy(socket_name, socket_dir);
|
|
||||||
|
|
||||||
if (mkdtemp(socket_name) == NULL)
|
|
||||||
die(1, "Unable to create directory '%s': %s\n",
|
|
||||||
socket_name, strerror(errno));
|
|
||||||
strcat(socket_name, "/");
|
|
||||||
strcat(socket_name, socket_file);
|
|
||||||
if (strlen(socket_name) + 1 >= sizeof(serv_addr.sun_path))
|
|
||||||
die(1, "Name of socket too long\n");
|
|
||||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
if (fd == -1)
|
|
||||||
die(1, "Can't create socket: %s\n", strerror(errno));
|
|
||||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
|
||||||
serv_addr.sun_family = AF_UNIX;
|
|
||||||
strcpy(serv_addr.sun_path, socket_name);
|
|
||||||
if (bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) {
|
|
||||||
close(fd);
|
|
||||||
die(1, "Error binding socket to '%s': %s\n",
|
|
||||||
serv_addr.sun_path, strerror(errno));
|
|
||||||
}
|
|
||||||
if (listen(fd, 5) == -1) {
|
|
||||||
close(fd);
|
|
||||||
die(1, "listen() failed: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
dctx->socket_name = strdup(socket_name);
|
|
||||||
dctx->socket_fd = fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_fork(void)
|
|
||||||
{
|
|
||||||
int pid;
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid == (pid_t) -1)
|
|
||||||
die(1, "fork() failed: %s\n", strerror(errno));
|
|
||||||
if (pid) {
|
|
||||||
char *infostr;
|
|
||||||
int n = strlen(dctx->socket_name) + 40;
|
|
||||||
|
|
||||||
infostr = (char *) malloc(n);
|
|
||||||
if (snprintf(infostr, n, "OPENSCD_INFO=%s:%lu:1",
|
|
||||||
dctx->socket_name, (ulong) pid) < 0) {
|
|
||||||
kill(pid, SIGTERM);
|
|
||||||
die(1, "Something went wrong\n");
|
|
||||||
}
|
|
||||||
printf("%s; export OPENSCD_INFO;\n", infostr);
|
|
||||||
free(infostr);
|
|
||||||
|
|
||||||
free(dctx->socket_name);
|
|
||||||
dctx->socket_name = NULL;
|
|
||||||
die(0, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_dctx(void)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = sc_establish_context(&dctx->ctx, "openscd");
|
|
||||||
if (r != 0)
|
|
||||||
die(1, "Unable to establish context: %s", sc_strerror(r));
|
|
||||||
init_cmd_stuff(dctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
dctx = (struct openscd_context *) malloc(sizeof(struct openscd_context));
|
|
||||||
assert(dctx != NULL);
|
|
||||||
memset(dctx, 0, sizeof(struct openscd_context));
|
|
||||||
|
|
||||||
if (!opt_pipe) {
|
|
||||||
setup_socket();
|
|
||||||
do_fork();
|
|
||||||
}
|
|
||||||
|
|
||||||
init_dctx();
|
|
||||||
|
|
||||||
atexit(cleanup);
|
|
||||||
command_handler(dctx);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
#ifndef _OPENSCD_H
|
|
||||||
#define _OPENSCD_H
|
|
||||||
|
|
||||||
#include <opensc/opensc.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_CARDS 4
|
|
||||||
|
|
||||||
struct openscd_card {
|
|
||||||
sc_card_t *card;
|
|
||||||
sc_pkcs15_card_t *p15card;
|
|
||||||
|
|
||||||
struct sc_reader *reader;
|
|
||||||
int slot_id;
|
|
||||||
int card_id;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct openscd_context {
|
|
||||||
struct sc_context *ctx;
|
|
||||||
char *socket_name;
|
|
||||||
int socket_fd;
|
|
||||||
|
|
||||||
int cmd_stuff_ok;
|
|
||||||
struct openscd_card *cards;
|
|
||||||
int card_count;
|
|
||||||
int card_id_number;
|
|
||||||
pthread_mutex_t card_mutex;
|
|
||||||
|
|
||||||
pthread_t *threads;
|
|
||||||
int thread_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct openscd_thread_arg {
|
|
||||||
struct openscd_context *dctx;
|
|
||||||
struct sc_reader *reader;
|
|
||||||
};
|
|
||||||
|
|
||||||
char *mkdtemp(char *tmpl);
|
|
||||||
void die(int return_code, const char *errmsg, ...);
|
|
||||||
void command_handler(struct openscd_context *dctx);
|
|
||||||
void init_cmd_stuff(struct openscd_context *dctx);
|
|
||||||
void cleanup_cmd_stuff(struct openscd_context *dctx);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _OPENSCD_H */
|
|
|
@ -1,45 +0,0 @@
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assuan.h>
|
|
||||||
|
|
||||||
static AssuanError reply_cb(void *opaque, const void *buf, size_t len)
|
|
||||||
{
|
|
||||||
printf("%d\n%s\n", len, buf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
char *infostr, *p;
|
|
||||||
char socket[150];
|
|
||||||
int r;
|
|
||||||
ASSUAN_CONTEXT ctx;
|
|
||||||
|
|
||||||
infostr = getenv("OPENSCD_INFO");
|
|
||||||
if (infostr == NULL)
|
|
||||||
return 0;
|
|
||||||
p = strchr(infostr, ':');
|
|
||||||
if (p == NULL)
|
|
||||||
return 0;
|
|
||||||
strncpy(socket, infostr, p - infostr);
|
|
||||||
socket[p - infostr] = '\0';
|
|
||||||
printf("Socket is: '%s'\n", socket);
|
|
||||||
|
|
||||||
r = assuan_socket_connect(&ctx, socket, -1);
|
|
||||||
if (r) {
|
|
||||||
fprintf(stderr, "Unable to connect: %s\n", assuan_strerror(r));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = assuan_transact(ctx, "GET_OBJ 0 400", reply_cb, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (r) {
|
|
||||||
fprintf(stderr, "Unable to transact: %s\n", assuan_strerror(r));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue