start moving code to the library, and add error codes
This commit is contained in:
@@ -37,6 +37,8 @@ yubico-piv-tool-*-mac.zip.sig
|
|||||||
tests/basic.sh.log
|
tests/basic.sh.log
|
||||||
tests/basic.sh.trs
|
tests/basic.sh.trs
|
||||||
tests/test-suite.log
|
tests/test-suite.log
|
||||||
|
lib/error.lo
|
||||||
|
lib/error.o
|
||||||
lib/libykpiv.la
|
lib/libykpiv.la
|
||||||
lib/version.lo
|
lib/version.lo
|
||||||
lib/version.o
|
lib/version.o
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ if test "$gl_gcc_warnings" = yes; then
|
|||||||
nw="$nw -Wtraditional-conversion" # Too many warnings for now
|
nw="$nw -Wtraditional-conversion" # Too many warnings for now
|
||||||
nw="$nw -Wconversion" # Too many warnings for now
|
nw="$nw -Wconversion" # Too many warnings for now
|
||||||
nw="$nw -Wsuggest-attribute=pure" # Is it worth using attributes?
|
nw="$nw -Wsuggest-attribute=pure" # Is it worth using attributes?
|
||||||
|
nw="$nw -Wsuggest-attribute=const" # Is it worth using attributes?
|
||||||
|
|
||||||
gl_MANYWARN_ALL_GCC([ws])
|
gl_MANYWARN_ALL_GCC([ws])
|
||||||
gl_MANYWARN_COMPLEMENT(ws, [$ws], [$nw])
|
gl_MANYWARN_COMPLEMENT(ws, [$ws], [$nw])
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ AM_CPPFLAGS = $(OPENSSL_CFLAGS) $(PCSC_CFLAGS)
|
|||||||
lib_LTLIBRARIES = libykpiv.la
|
lib_LTLIBRARIES = libykpiv.la
|
||||||
|
|
||||||
libykpiv_la_SOURCES = ykpiv.c version.c ykpiv.pc.in ykpiv.map internal.h
|
libykpiv_la_SOURCES = ykpiv.c version.c ykpiv.pc.in ykpiv.map internal.h
|
||||||
|
libykpiv_la_SOURCES += error.c
|
||||||
libykpiv_la_includedir = $(includedir)/ykpiv
|
libykpiv_la_includedir = $(includedir)/ykpiv
|
||||||
libykpiv_la_include_HEADERS = ykpiv.h ykpiv-version.h
|
libykpiv_la_include_HEADERS = ykpiv.h ykpiv-version.h
|
||||||
|
|
||||||
|
|||||||
+95
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 Yubico AB
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Additional permission under GNU GPL version 3 section 7
|
||||||
|
*
|
||||||
|
* If you modify this program, or any covered work, by linking or
|
||||||
|
* combining it with the OpenSSL project's OpenSSL library (or a
|
||||||
|
* modified version of that library), containing parts covered by the
|
||||||
|
* terms of the OpenSSL or SSLeay licenses, We grant you additional
|
||||||
|
* permission to convey the resulting work. Corresponding Source for a
|
||||||
|
* non-source form of such a combination shall include the source code
|
||||||
|
* for the parts of OpenSSL used as well as that of the covered work.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ykpiv.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define ERR(name, desc) { name, #name, desc }
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ykpiv_rc rc;
|
||||||
|
const char *name;
|
||||||
|
const char *description;
|
||||||
|
} err_t;
|
||||||
|
|
||||||
|
static const err_t errors[] = {
|
||||||
|
ERR (YKPIV_OK, "Successful return"),
|
||||||
|
ERR (YKPIV_MEMORY_ERROR, "Error allocating memory"),
|
||||||
|
ERR (YKPIV_PCSC_ERROR, "Error in PCSC call"),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ykpiv_strerror:
|
||||||
|
* @err: error code
|
||||||
|
*
|
||||||
|
* Convert return code to human readable string explanation of the
|
||||||
|
* reason for the particular error code.
|
||||||
|
*
|
||||||
|
* This string can be used to output a diagnostic message to the user.
|
||||||
|
*
|
||||||
|
* Return value: Returns a pointer to a statically allocated string
|
||||||
|
* containing an explanation of the error code @err.
|
||||||
|
**/
|
||||||
|
const char *ykpiv_strerror(ykpiv_rc err) {
|
||||||
|
static const char *unknown = "Unknown ykpiv error";
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
if (-err < 0 || -err >= (int) (sizeof (errors) / sizeof (errors[0])))
|
||||||
|
return unknown;
|
||||||
|
|
||||||
|
p = errors[-err].description;
|
||||||
|
if (!p)
|
||||||
|
p = unknown;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ykpiv_strerror_name:
|
||||||
|
* @err: error code
|
||||||
|
*
|
||||||
|
* Convert return code to human readable string representing the error
|
||||||
|
* code symbol itself. For example, ykpiv_strerror_name(%YKPIV_OK)
|
||||||
|
* returns the string "YKPIV_OK".
|
||||||
|
*
|
||||||
|
* This string can be used to output a diagnostic message to the user.
|
||||||
|
*
|
||||||
|
* Return value: Returns a pointer to a statically allocated string
|
||||||
|
* containing a string version of the error code @err, or NULL if
|
||||||
|
* the error code is not known.
|
||||||
|
**/
|
||||||
|
const char *ykpiv_strerror_name(ykpiv_rc err) {
|
||||||
|
if (-err < 0 || -err >= (int) (sizeof (errors) / sizeof (errors[0])))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return errors[-err].name;
|
||||||
|
}
|
||||||
+18
-2
@@ -30,9 +30,25 @@
|
|||||||
#ifndef YKPIV_INTERNAL_H
|
#ifndef YKPIV_INTERNAL_H
|
||||||
#define YKPIV_INTERNAL_H
|
#define YKPIV_INTERNAL_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#if BACKEND_PCSC
|
||||||
|
#if defined HAVE_PCSC_WINSCARD_H
|
||||||
|
# include <PCSC/wintypes.h>
|
||||||
|
# include <PCSC/winscard.h>
|
||||||
|
#else
|
||||||
|
# include <winscard.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ykpiv_state {
|
struct ykpiv_state {
|
||||||
SCARDCONTEXT card;
|
SCARDCONTEXT context;
|
||||||
SCARDHANDLE cardHandle;
|
SCARDHANDLE card;
|
||||||
|
int verbose;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned const char aid[] = {
|
||||||
|
0xa0, 0x00, 0x00, 0x03, 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+89
-20
@@ -29,30 +29,99 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
#if BACKEND_PCSC
|
|
||||||
#if defined HAVE_PCSC_WINSCARD_H
|
|
||||||
# include <PCSC/wintypes.h>
|
|
||||||
# include <PCSC/winscard.h>
|
|
||||||
#else
|
|
||||||
# include <winscard.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "ykpiv.h"
|
#include "ykpiv.h"
|
||||||
|
|
||||||
int ykpiv_init(ykpiv_state **state) {
|
ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose) {
|
||||||
ykpiv_state *s = malloc(sizeof(ykpiv_state));
|
ykpiv_state *s = malloc(sizeof(ykpiv_state));
|
||||||
if(s == NULL) {
|
if(s == NULL) {
|
||||||
return -1;
|
return YKPIV_MEMORY_ERROR;
|
||||||
}
|
}
|
||||||
memset(s, 0, sizeof(ykpiv_state));
|
memset(s, 0, sizeof(ykpiv_state));
|
||||||
*state = s;
|
s->verbose = verbose;
|
||||||
return 0;
|
*state = s;
|
||||||
|
return YKPIV_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ykpiv_done(ykpiv_state *state) {
|
ykpiv_rc ykpiv_done(ykpiv_state *state) {
|
||||||
free(state);
|
free(state);
|
||||||
return 0;
|
return YKPIV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted) {
|
||||||
|
unsigned long num_readers = 0;
|
||||||
|
unsigned long active_protocol;
|
||||||
|
char reader_buf[1024];
|
||||||
|
long rc;
|
||||||
|
char *reader_ptr;
|
||||||
|
|
||||||
|
rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context);
|
||||||
|
if (rc != SCARD_S_SUCCESS) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf (stderr, "error: SCardEstablishContext failed, rc=%08lx\n", rc);
|
||||||
|
}
|
||||||
|
return YKPIV_PCSC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SCardListReaders(state->context, NULL, NULL, &num_readers);
|
||||||
|
if (rc != SCARD_S_SUCCESS) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc);
|
||||||
|
}
|
||||||
|
SCardReleaseContext(state->context);
|
||||||
|
return YKPIV_PCSC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_readers > sizeof(reader_buf)) {
|
||||||
|
num_readers = sizeof(reader_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SCardListReaders(state->context, NULL, reader_buf, &num_readers);
|
||||||
|
if (rc != SCARD_S_SUCCESS)
|
||||||
|
{
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf (stderr, "error: SCardListReaders failed, rc=%08lx\n", rc);
|
||||||
|
}
|
||||||
|
SCardReleaseContext(state->context);
|
||||||
|
return YKPIV_PCSC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader_ptr = reader_buf;
|
||||||
|
if(wanted) {
|
||||||
|
while(*reader_ptr != '\0') {
|
||||||
|
if(strstr(reader_ptr, wanted)) {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "using reader '%s' matching '%s'.\n", reader_ptr, wanted);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "skipping reader '%s' since it doesn't match.\n", reader_ptr);
|
||||||
|
}
|
||||||
|
reader_ptr += strlen(reader_ptr) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(*reader_ptr == '\0') {
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "error: no useable reader found.\n");
|
||||||
|
}
|
||||||
|
SCardReleaseContext(state->context);
|
||||||
|
return YKPIV_PCSC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = SCardConnect(state->context, reader_ptr, SCARD_SHARE_SHARED,
|
||||||
|
SCARD_PROTOCOL_T1, &state->card, &active_protocol);
|
||||||
|
if(rc != SCARD_S_SUCCESS)
|
||||||
|
{
|
||||||
|
if(state->verbose) {
|
||||||
|
fprintf(stderr, "error: SCardConnect failed, rc=%08lx\n", rc);
|
||||||
|
}
|
||||||
|
SCardReleaseContext(state->context);
|
||||||
|
return YKPIV_PCSC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YKPIV_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-2
@@ -37,8 +37,20 @@ extern "C"
|
|||||||
|
|
||||||
typedef struct ykpiv_state ykpiv_state;
|
typedef struct ykpiv_state ykpiv_state;
|
||||||
|
|
||||||
int ykpiv_init(ykpiv_state **state);
|
typedef enum {
|
||||||
int ykpiv_done(ykpiv_state *state);
|
YKPIV_OK = 0,
|
||||||
|
YKPIV_MEMORY_ERROR = -1,
|
||||||
|
YKPIV_PCSC_ERROR = -2,
|
||||||
|
} ykpiv_rc;
|
||||||
|
|
||||||
|
const char *ykpiv_strerror(ykpiv_rc err);
|
||||||
|
const char *ykpiv_strerror_name(ykpiv_rc err);
|
||||||
|
|
||||||
|
ykpiv_rc ykpiv_init(ykpiv_state **state, int verbose);
|
||||||
|
ykpiv_rc ykpiv_done(ykpiv_state *state);
|
||||||
|
ykpiv_rc ykpiv_connect(ykpiv_state *state, const char *wanted);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ YKPIV_0.1.0
|
|||||||
{
|
{
|
||||||
global:
|
global:
|
||||||
ykpiv_check_version;
|
ykpiv_check_version;
|
||||||
|
ykpiv_strerror_name;
|
||||||
|
ykpiv_strerror;
|
||||||
ykpiv_init;
|
ykpiv_init;
|
||||||
ykpiv_map;
|
ykpiv_map;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user