start moving code to the library, and add error codes

This commit is contained in:
Klas Lindfors
2014-06-16 13:19:48 +02:00
parent fe5632e603
commit 0d4dd2fea1
8 changed files with 222 additions and 24 deletions
+2
View File
@@ -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
+1
View File
@@ -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])
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
} }
+2
View File
@@ -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;