diff --git a/virtualsmartcard/configure.ac b/virtualsmartcard/configure.ac index e4a8914..1949e09 100644 --- a/virtualsmartcard/configure.ac +++ b/virtualsmartcard/configure.ac @@ -124,6 +124,22 @@ else fi +HAVE_QRENCODE=yes +PKG_CHECK_EXISTS([libqrencode], + [PKG_CHECK_MODULES([QRENCODE], [libqrencode])], + [AC_MSG_WARN([libqrencode not found by pkg-config])]) +CPPFLAGS="$CPPFLAGS $QRENCODE_CFLAGS -I${srcdir}/src/opensc/src" +LIBS="$LDFLAGS $QRENCODE_LIBS" +AC_CHECK_HEADERS(qrencode.h, [], [ HAVE_QRENCODE=no ]) +AC_MSG_CHECKING([for QRcode_encodeString]) +AC_TRY_LINK_FUNC(QRcode_encodeString, [ AC_MSG_RESULT([yes]) ], [ HAVE_QRENCODE=no ]) +AM_CONDITIONAL(HAVE_QRENCODE, test "${HAVE_QRENCODE}" = "yes") +AM_COND_IF(HAVE_QRENCODE, [AC_DEFINE(HAVE_QRENCODE, 1, [enable QR support])]) +CPPFLAGS="$saved_CPPFLAGS" +LIBS="$saved_LIBS" + + + PACKAGE_SUMMARY="Smart card emulator written in Python" AC_SUBST(PACKAGE_SUMMARY) @@ -210,6 +226,8 @@ PTHREAD_LIBS: ${PTHREAD_LIBS} PTHREAD_CFLAGS: ${PTHREAD_CFLAGS} PCSC_CFLAGS: ${PCSC_CFLAGS} PCSC_LIBS: ${PCSC_LIBS} +QRENCODE_CFLAGS: ${QRENCODE_CFLAGS} +QRENCODE_LIBS: ${QRENCODE_LIBS} BUNDLE_HOST: ${BUNDLE_HOST} LIB_PREFIX: ${LIB_PREFIX} DYN_LIB_EXT: ${DYN_LIB_EXT} @@ -230,5 +248,6 @@ AC_CONFIG_FILES([Makefile src/ifd-vpcd/Makefile src/vpcd/Makefile src/vpicc/Makefile + src/vpcd-config/Makefile ]) AC_OUTPUT diff --git a/virtualsmartcard/doc/README.txt b/virtualsmartcard/doc/README.txt index d4af28a..623f26b 100644 --- a/virtualsmartcard/doc/README.txt +++ b/virtualsmartcard/doc/README.txt @@ -224,6 +224,13 @@ options of |vpicc|. .. program-output:: vicc --help +.. versionadded:: 0.7 + We implemented :command:`vpcd-config` which tries to guess the local IP + address and outputs |vpcd|'s configuration. |vpicc|'s options should be + chosen accordingly (:option:`--hostname` and :option:`--port`) + :command:`vpcd-config` also prints a QR code for configuration of the + :ref:`remote-reader`. + On Windows you can start |vpicc| with :command:`python.exe src/vpicc/vicc.in` or :command:`python.exe vicc`. Note emulating the German ID card (:option:`--type nPA`) when running |vpicc| on Windows is currently not diff --git a/virtualsmartcard/doc/README.txt.in b/virtualsmartcard/doc/README.txt.in index e737f3d..a9e380b 100644 --- a/virtualsmartcard/doc/README.txt.in +++ b/virtualsmartcard/doc/README.txt.in @@ -224,6 +224,13 @@ options of |vpicc|. .. program-output:: vicc --help +.. versionadded:: 0.7 + We implemented :command:`vpcd-config` which tries to guess the local IP + address and outputs |vpcd|'s configuration. |vpicc|'s options should be + chosen accordingly (:option:`--hostname` and :option:`--port`) + :command:`vpcd-config` also prints a QR code for configuration of the + :ref:`remote-reader`. + On Windows you can start |vpicc| with :command:`python.exe src/vpicc/vicc.in` or :command:`python.exe vicc`. Note emulating the German ID card (:option:`--type nPA`) when running |vpicc| on Windows is currently not diff --git a/virtualsmartcard/src/Makefile.am b/virtualsmartcard/src/Makefile.am index 0eaa864..54d4f00 100644 --- a/virtualsmartcard/src/Makefile.am +++ b/virtualsmartcard/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = vpcd vpicc ifd-vpcd +SUBDIRS = vpcd vpicc ifd-vpcd vpcd-config if BUILD_LIBPCSCLITE SUBDIRS += pcsclite-vpcd diff --git a/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c b/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c index 8b6e618..9641bce 100644 --- a/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c +++ b/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.c @@ -28,8 +28,8 @@ /* pcscd allows at most 16 readers. We will use 10. * See PCSCLITE_MAX_READERS_CONTEXTS in pcsclite.h */ #define VICC_MAX_SLOTS \ - PCSCLITE_MAX_READERS_CONTEXTS > 6 ? \ - PCSCLITE_MAX_READERS_CONTEXTS-6 : 1 + (PCSCLITE_MAX_READERS_CONTEXTS > 6 ? \ + PCSCLITE_MAX_READERS_CONTEXTS-6 : 1) const unsigned char vicc_max_slots = VICC_MAX_SLOTS; static struct vicc_ctx *ctx[VICC_MAX_SLOTS]; diff --git a/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.h b/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.h index 9f5bef5..b624eb9 100644 --- a/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.h +++ b/virtualsmartcard/src/ifd-vpcd/ifd-vpcd.h @@ -23,7 +23,7 @@ extern "C" { #endif -extern const unsigned char VICC_MAX_SLOTS; +extern const unsigned char vicc_max_slots; extern const char *hostname; #ifdef __cplusplus diff --git a/virtualsmartcard/src/vpcd-config/Makefile.am b/virtualsmartcard/src/vpcd-config/Makefile.am new file mode 100644 index 0000000..e8ee7d3 --- /dev/null +++ b/virtualsmartcard/src/vpcd-config/Makefile.am @@ -0,0 +1,7 @@ +EXTRA_DIST = qransi.c + +bin_PROGRAMS = vpcd-config + +vpcd_config_CFLAGS = $(PCSC_CFLAGS) $(QRENCODE_CFLAGS) -I$(srcdir)/../vpcd +vpcd_config_SOURCES = vpcd-config.c local-ip.c +vpcd_config_LDADD = $(QRENCODE_LIBS) diff --git a/virtualsmartcard/src/vpcd-config/local-ip.c b/virtualsmartcard/src/vpcd-config/local-ip.c new file mode 100644 index 0000000..57d7d76 --- /dev/null +++ b/virtualsmartcard/src/vpcd-config/local-ip.c @@ -0,0 +1,51 @@ +/* Derived from http://www.binarytides.com/get-local-ip-c-linux/ by Silver Moon */ + +/* + * Find local ip used as source ip in ip packets. + * Use getsockname and a udp connection + */ + +#include //printf +#include //memset +#include //errno +#include //socket +#include //sockaddr_in +#include //getsockname +#include //close + +#define ERROR_STRING "Unable to guess local IP address" + +const char *local_ip (void) +{ + const char* google_dns_server = "8.8.8.8", *ip = NULL; + int dns_port = 53; + struct sockaddr_in name; + socklen_t namelen = sizeof(name); + struct sockaddr_in serv; + static char buffer[20]; + int sock = socket ( AF_INET, SOCK_DGRAM, 0); + if(sock < 0) { + perror(ERROR_STRING); + return NULL; + } + + memset( &serv, 0, sizeof(serv) ); + serv.sin_family = AF_INET; + serv.sin_addr.s_addr = inet_addr( google_dns_server ); + serv.sin_port = htons( dns_port ); + + if (0 != connect( sock , (const struct sockaddr*) &serv , sizeof(serv) ) + || 0 != getsockname(sock, (struct sockaddr*) &name, &namelen) + || !inet_ntop(AF_INET, &name.sin_addr, buffer, sizeof(buffer) )) + goto err; + + ip = buffer; + +err: + if (!ip) + printf("%s: %s\n" , ERROR_STRING, strerror(errno)); + if (sock > 0) + close(sock); + + return ip; +} diff --git a/virtualsmartcard/src/vpcd-config/qransi.c b/virtualsmartcard/src/vpcd-config/qransi.c new file mode 100644 index 0000000..25f07a2 --- /dev/null +++ b/virtualsmartcard/src/vpcd-config/qransi.c @@ -0,0 +1,45 @@ +/* Derived from https://github.com/bengl/qransi by Bryan English */ + +#include +#include +#include + +#define WHITE "\033[47m \033[0m" +#define BLACK "\033[40m \033[0m" + +void pixels(char* color, int size) +{ + int i; + for(i=0; iwidth; + data = code->data; + whiteRow(padding, width); + for (y=0; y. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vpcd.h" + +extern const char *local_ip (void); + +/* pcscd allows at most 16 readers. We will use 10. + * See PCSCLITE_MAX_READERS_CONTEXTS in pcsclite.h */ +#include +#define VICC_MAX_SLOTS \ + (PCSCLITE_MAX_READERS_CONTEXTS > 6 ? \ + PCSCLITE_MAX_READERS_CONTEXTS-6 : 1) + +#define ERROR_STRING "Unable to guess local IP address" + + + +#ifdef HAVE_QRENCODE + +#include "qransi.c" + +void print_qrcode(const char *uri) +{ + qransi (uri); +} + +#else + +void print_qrcode(const char *uri) +{ + printf("https://api.qrserver.com/v1/create-qr-code/?data=%s\n", uri); +} +#endif + + + +int main ( int argc , char *argv[] ) +{ + char slot; + char uri[60]; + const char *ip = NULL; + int fail = 1, port; + + ip = local_ip(); + if (!ip) + goto err; + + for (slot = 1; slot < VICC_MAX_SLOTS; slot++) { + port = VPCDPORT+slot-1; + printf("VPCD hostname: %s\n", ip); + printf("VPCD port: %d\n", port); + printf("On your NFC phone with the Remote Smart Card Reader app scan this code:\n", port); + sprintf(uri, "vpcd://%s:%d", ip, port); + print_qrcode(uri); + puts(""); + } + + fail = 0; + +err: + return fail; +}