macOS: Added support for notifications

- adds framework for user defined message strings
- automatically determine the system's language
This commit is contained in:
Frank Morgner 2017-05-24 12:46:42 +02:00
parent 0b3d7f25c8
commit bf828014e5
18 changed files with 787 additions and 14 deletions

View File

@ -91,7 +91,23 @@ fi
test -L OpenSC.tokend/build/opensc-src || ln -sf ${BUILDPATH}/src OpenSC.tokend/build/opensc-src
# Build and copy OpenSC.tokend
xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${PWD}/target
xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${BUILDPATH}/target
#if ! test -e $BUILDPATH/target/Library/Security/tokend/OpenSC.tokend/Contents/Resources/Applications/terminal-notifier.app; then
#if ! test -e terminal-notifier-1.7.1.zip; then
#curl -L https://github.com/julienXX/terminal-notifier/releases/download/1.7.1/terminal-notifier-1.7.1.zip > terminal-notifier-1.7.1.zip
#fi
#if ! test -e terminal-notifier-1.7.1; then
#unzip terminal-notifier-1.7.1.zip
#fi
#mkdir -p $BUILDPATH/target/Library/Security/tokend/OpenSC.tokend/Contents/Resources/Applications
#cp -r terminal-notifier-1.7.1/terminal-notifier.app $BUILDPATH/target/Library/Security/tokend/OpenSC.tokend/Contents/Resources/Applications
#fi
if ! test -e NotificationProxy; then
git clone http://github.com/frankmorgner/NotificationProxy.git
fi
xcodebuild -target NotificationProxy -configuration Release -project NotificationProxy/NotificationProxy.xcodeproj install DSTROOT=$BUILDPATH/target/Library/Security/tokend/OpenSC.tokend/Contents/Resources/
# Prepare target root
# The "UnInstaller"

View File

@ -245,6 +245,13 @@ AC_ARG_ENABLE(
[enable_dnie_ui="no"]
)
AC_ARG_ENABLE(
[notify],
[AS_HELP_STRING([--enable-notify],[enable notifications @<:@detect@:>@])],
,
[enable_notify="detect"]
)
AC_ARG_ENABLE(
[werror-declaration-after-statement],
[AS_HELP_STRING([--disable-werror-declaration-after-statement],[disable -Werror 'declaration-after-statement' @<:@enabled@:>@])],
@ -443,7 +450,7 @@ if test "${enable_dnie_ui}" = "yes"; then
AC_DEFINE([ENABLE_DNIE_UI], [1], [Enable the use of external user interface program to request DNIe user pin])
case "${host}" in
*-apple-*)
*-*-darwin)
if test "${enable_dnie_ui}" = "yes"; then
LDFLAGS="${LDFLAGS} -framework Carbon"
fi
@ -451,6 +458,37 @@ if test "${enable_dnie_ui}" = "yes"; then
esac
fi
case "${host}" in
*-*-darwin*)
have_notify="yes"
;;
*)
;;
esac
case "${enable_notify}" in
no)
have_notify="no"
;;
detect)
if test "${have_notify}" = "yes"; then
enable_notify="yes"
else
enable_notify="no"
fi
;;
esac
if test "${enable_notify}" = "yes"; then
if test "${have_notify}" = "yes"; then
AC_DEFINE([ENABLE_NOTIFY], [1], [Use notification libraries and header files])
OPTIONAL_NOTIFY_CFLAGS="${NOTIFY_CFLAGS}"
OPTIONAL_NOTIFY_LIBS="${NOTIFY_LIBS}"
else
AC_MSG_ERROR([notification linkage required, but no notification provider was found])
fi
fi
AC_ARG_VAR([ZLIB_CFLAGS], [C compiler flags for zlib])
AC_ARG_VAR([ZLIB_LIBS], [linker flags for zlib])
if test -z "${ZLIB_LIBS}"; then
@ -914,6 +952,8 @@ AC_SUBST([DEFAULT_SM_MODULE_PATH])
AC_SUBST([DEBUG_FILE])
AC_SUBST([PROFILE_DIR])
AC_SUBST([PROFILE_DIR_DEFAULT])
AC_SUBST([OPTIONAL_NOTIFY_CFLAGS])
AC_SUBST([OPTIONAL_NOTIFY_LIBS])
AM_CONDITIONAL([ENABLE_MAN], [test "${enable_man}" = "yes"])
AM_CONDITIONAL([ENABLE_THREAD_LOCKING], [test "${enable_thread_locking}" = "yes"])
@ -956,6 +996,7 @@ AC_CONFIG_FILES([
etc/Makefile
src/Makefile
src/common/Makefile
src/ui/Makefile
src/libopensc/Makefile
src/sm/Makefile
src/pkcs11/Makefile
@ -1021,6 +1062,7 @@ minidriver support: ${enable_minidriver}
SM support: ${enable_sm}
SM default module: ${DEFAULT_SM_MODULE}
DNIe UI support: ${enable_dnie_ui}
Notification support: ${enable_notify}
Debug file: ${DEBUG_FILE}
PC/SC default provider: ${DEFAULT_PCSC_PROVIDER}
@ -1045,6 +1087,8 @@ OPENCT_CFLAGS: ${OPENCT_CFLAGS}
OPENCT_LIBS: ${OPENCT_LIBS}
PCSC_CFLAGS: ${PCSC_CFLAGS}
CRYPTOTOKENKIT_CFLAGS: ${CRYPTOTOKENKIT_CFLAGS}
NOTIFY_CFLAGS: ${NOTIFY_CFLAGS}
NOTIFY_LIBS: ${NOTIFY_LIBS}
EOF

View File

@ -2,7 +2,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
EXTRA_DIST = Makefile.mak
# Order IS important
SUBDIRS = common scconf pkcs15init sm \
SUBDIRS = common scconf ui pkcs15init sm \
libopensc pkcs11 tools tests minidriver
if ENABLE_SM

View File

@ -1,6 +1,6 @@
TOPDIR = ..
SUBDIRS = common scconf sm pkcs15init \
SUBDIRS = common scconf ui sm pkcs15init \
libopensc pkcs11 tools tests
default: all

View File

@ -78,6 +78,8 @@ libopensc_la_LIBADD = $(OPENPACE_LIBS) $(OPTIONAL_OPENSSL_LIBS) \
$(top_builddir)/src/pkcs15init/libpkcs15init.la \
$(top_builddir)/src/scconf/libscconf.la \
$(top_builddir)/src/common/libscdl.la \
$(top_builddir)/src/ui/libnotify.la \
$(top_builddir)/src/ui/libstrings.la \
$(top_builddir)/src/sm/libsmeac.la \
$(top_builddir)/src/common/libcompat.la
if WIN32

View File

@ -41,6 +41,8 @@ OBJECTS = \
LIBS = $(TOPDIR)\src\scconf\scconf.lib \
$(TOPDIR)\src\common\common.lib \
$(TOPDIR)\src\common\libscdl.lib \
$(TOPDIR)\src\ui\strings.lib \
$(TOPDIR)\src\ui\notify.lib \
$(TOPDIR)\src\sm\libsmiso.lib \
$(TOPDIR)\src\sm\libsmeac.lib \
$(TOPDIR)\src\pkcs15init\pkcs15init.lib

View File

@ -363,3 +363,8 @@ escape_pace_output_to_buf
escape_buf_to_pace_output
escape_pace_capabilities_to_buf
escape_buf_to_pace_capabilities
ui_get_str
sc_notify_init
sc_notify_close
sc_notify
sc_notify_id

View File

@ -30,6 +30,7 @@
#include "internal.h"
#include "asn1.h"
#include "pkcs15.h"
#include "ui/notify.h"
int _sc_pkcs15_verify_pin(struct sc_pkcs15_card *, struct sc_pkcs15_object *,
const unsigned char *, size_t);
@ -358,12 +359,14 @@ int sc_pkcs15_verify_pin_with_session_pin(struct sc_pkcs15_card *p15card,
"PIN(type:%X; method:%X; value(%p:%"SC_FORMAT_LEN_SIZE_T"u)",
auth_info->auth_type, auth_info->auth_method,
pincode, pinlen);
if (pinlen > SC_MAX_PIN_SIZE)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_LENGTH, "Invalid PIN size");
card = p15card->card;
if (pinlen > SC_MAX_PIN_SIZE) {
sc_notify_id(card->ctx, &card->reader->atr, p15card,
NOTIFY_PIN_BAD);
LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_LENGTH, "Invalid PIN size");
}
/* Initialize arguments */
memset(&data, 0, sizeof(data));
data.pin_type = auth_info->auth_method;
@ -408,10 +411,10 @@ int sc_pkcs15_verify_pin_with_session_pin(struct sc_pkcs15_card *p15card,
data.pin_reference = skey_info->key_reference;
}
if((p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD
|| p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)
&& !pinlen) {
data.flags |= SC_PIN_CMD_USE_PINPAD;
if ((p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD
|| p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) {
if (!pincode && !pinlen)
data.flags |= SC_PIN_CMD_USE_PINPAD;
if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)
data.pin1.prompt = "Please enter SO PIN";
@ -450,10 +453,19 @@ int sc_pkcs15_verify_pin_with_session_pin(struct sc_pkcs15_card *p15card,
*sessionpinlen = data.pin2.len;
}
} else {
sc_notify_id(card->ctx, &card->reader->atr, p15card,
NOTIFY_PIN_BAD);
if (data.cmd == SC_PIN_CMD_GET_SESSION_PIN) {
*sessionpinlen = 0;
}
}
if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_PIN
&& auth_info->auth_method != SC_AC_SESSION) {
sc_notify_id(card->ctx, &card->reader->atr, p15card,
r == SC_SUCCESS ? NOTIFY_PIN_GOOD : NOTIFY_PIN_BAD);
}
out:
sc_unlock(card);
LOG_FUNC_RETURN(ctx, r);

View File

@ -25,6 +25,7 @@
#include "libopensc/internal.h"
#include "libopensc/asn1.h"
#include "libopensc/cardctl.h"
#include "ui/notify.h"
#include "common/compat_strnlen.h"
#ifdef ENABLE_OPENSSL
@ -329,6 +330,12 @@ pkcs15_bind(struct sc_pkcs11_card *p11card, struct sc_app_info *app_info)
}
}
if (idx == 0) {
/* send a notification only for the first application that's bound */
sc_notify_id(p11card->card->ctx, &p11card->reader->atr, fw_data->p15_card,
NOTIFY_CARD_INSERTED);
}
return CKR_OK;
}
@ -356,8 +363,20 @@ pkcs15_unbind(struct sc_pkcs11_card *p11card)
unlock_card(fw_data);
if (fw_data->p15_card)
if (fw_data->p15_card) {
if (idx == 0) {
int rc = sc_detect_card_presence(fw_data->p15_card->card->reader);
if (rc <= 0 || rc & SC_READER_CARD_CHANGED) {
/* send a notification only if the card was removed/changed
* and only for the first application that's unbound */
sc_notify_id(fw_data->p15_card->card->ctx,
&fw_data->p15_card->card->reader->atr,
fw_data->p15_card,
NOTIFY_CARD_REMOVED);
}
}
rv = sc_pkcs15_unbind(fw_data->p15_card);
}
fw_data->p15_card = NULL;
free(fw_data);

View File

@ -19,7 +19,7 @@ EXTRA_DIST = Makefile.mak versioninfo-tools.rc.in npa-tool.ggo.in npa-tool.1
noinst_HEADERS = util.h fread_to_eof.h
noinst_PROGRAMS = sceac-example
bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-tool pkcs15-crypt \
pkcs11-tool cardos-tool eidenv openpgp-tool iasecc-tool
pkcs11-tool cardos-tool eidenv openpgp-tool iasecc-tool opensc-notify
if ENABLE_OPENSSL
bin_PROGRAMS += cryptoflex-tool pkcs15-init netkey-tool piv-tool \
westcos-tool sc-hsm-tool dnie-tool gids-tool npa-tool
@ -46,6 +46,7 @@ piv_tool_SOURCES = piv-tool.c util.c
piv_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
opensc_explorer_SOURCES = opensc-explorer.c util.c
opensc_explorer_LDADD = $(OPTIONAL_READLINE_LIBS)
opensc_notify_SOURCES = opensc-notify.c
pkcs15_tool_SOURCES = pkcs15-tool.c util.c
pkcs15_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
pkcs11_tool_SOURCES = pkcs11-tool.c util.c

View File

@ -6,6 +6,7 @@ default: all
TARGETS = opensc-tool.exe opensc-explorer.exe pkcs15-tool.exe pkcs15-crypt.exe \
pkcs11-tool.exe cardos-tool.exe eidenv.exe openpgp-tool.exe iasecc-tool.exe \
opensc-notify.exe \
$(PROGRAMS_OPENSSL)
OBJECTS = util.obj npa-tool-cmdline.obj fread_to_eof.obj versioninfo-tools.res

50
src/tools/opensc-notify.c Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
*
* This file is part of OpenSC.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "ui/notify.h"
#include <stdio.h>
int
main (int argc, char **argv)
{
const char *title = NULL, *text = NULL;
switch (argc) {
case 3:
text = argv[2];
/* fall through */
case 2:
text = argv[1];
/* fall through */
case 1:
break;
default:
fprintf(stderr, "Usage: opensc-notify [title [text]]");
return 1;
}
sc_notify_init();
sc_notify(title, text);
sc_notify_close();
return 0;
}

16
src/ui/Makefile.am Normal file
View File

@ -0,0 +1,16 @@
include $(top_srcdir)/win32/ltrc.inc
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
EXTRA_DIST = Makefile.mak
noinst_LTLIBRARIES = libstrings.la libnotify.la
noinst_HEADERS = strings.h notify.h
AM_CPPFLAGS = -I$(top_srcdir)/src
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(OPTIONAL_NOTIFY_CFLAGS)
AM_OBJCFLAGS = $(AM_CFLAGS)
libstrings_la_SOURCES = strings.c
libnotify_la_SOURCES = notify.c
libnotify_la_LIBADD = $(OPTIONAL_NOTIFY_LIBS)

17
src/ui/Makefile.mak Normal file
View File

@ -0,0 +1,17 @@
TOPDIR = ..\..
TARGET = strings.lib
OBJECTS = strings.obj
TARGET2 = notify.lib
OBJECTS2 = notify.obj
all: $(TARGET) $(TARGET2)
!INCLUDE $(TOPDIR)\win32\Make.rules.mak
$(TARGET): $(OBJECTS)
lib $(LIBFLAGS) /out:$(TARGET) $(OBJECTS)
$(TARGET2): $(OBJECTS2)
lib $(LIBFLAGS) /out:$(TARGET2) $(OBJECTS2)

176
src/ui/notify.c Normal file
View File

@ -0,0 +1,176 @@
/*
* notify.c: Notification implementation
*
* Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "notify.h"
#if defined(ENABLE_NOTIFY) && defined(__APPLE__)
#include "libopensc/log.h"
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static pid_t child = -1;
void sc_notify_init(void)
{
}
void sc_notify_close(void)
{
if (child > 0) {
int i, status;
for (i = 0; child != waitpid(child, &status, WNOHANG); i++) {
switch (i) {
case 0:
kill(child, SIGKILL);
break;
case 1:
kill(child, SIGTERM);
break;
default:
/* SIGTERM was our last resort */
return;
}
usleep(100);
}
child = -1;
}
}
static void notify_proxy(struct sc_context *ctx,
const char *title, const char* subtitle,
const char *text, const char *icon, const char *sound,
const char *group)
{
/* terminal-notifier does not reliably activate keychain when clicked on
* the notification
* (https://github.com/julienXX/terminal-notifier/issues/196), that's why
* we're including NotificationProxy which has similar features */
const char notificationproxy[] = "/Library/Security/tokend/OpenSC.tokend/Contents/Resources/Applications/NotificationProxy.app/Contents/MacOS/NotificationProxy";
if (child > 0) {
int status;
if (0 == waitpid(child, &status, WNOHANG)) {
kill(child, SIGKILL);
usleep(100);
if (0 == waitpid(child, &status, WNOHANG)) {
sc_log(ctx, "Can't kill %ld, skipping current notification", (long) child);
return;
}
}
}
child = fork();
switch (child) {
case 0:
/* child process */
/* for some reason the user _tokend can call brew's installation of
* terminal-notifier, but it cannot call `/usr/bin/open` with
* NotificationProxy.app that we're shipping... However, while
* `sudo -u _tokend /usr/local/bin/terminal-notifier -title test`
* works in the terminal, it hangs when executed from the tokend
* process. For now, we try to deliver the notification anyway
* making sure that we are waiting for only one forked process. */
if (0 > execl(notificationproxy, notificationproxy,
title ? title : "",
subtitle ? subtitle : "",
text ? text : "",
icon ? icon : "",
group ? group : "",
sound ? sound : "",
(char *) NULL)) {
perror("exec failed");
exit(0);
}
break;
case -1:
sc_log(ctx, "failed to fork for notification");
break;
default:
if (ctx) {
sc_log(ctx, "Created %ld for notification:", (long) child);
sc_log(ctx, "%s %s %s %s %s %s %s", notificationproxy,
title ? title : "",
subtitle ? subtitle : "",
text ? text : "",
icon ? icon : "",
group ? group : "",
sound ? sound : "");
}
break;
}
}
void sc_notify(const char *title, const char *text)
{
notify_proxy(NULL, title, NULL, text, NULL, NULL, NULL);
}
void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
struct sc_pkcs15_card *p15card, enum ui_str id)
{
const char *title, *text, *icon, *group;
title = ui_get_str(ctx, atr, p15card, id);
text = ui_get_str(ctx, atr, p15card, id+1);
if (p15card && p15card->card && p15card->card->reader) {
group = p15card->card->reader->name;
} else {
group = ctx ? ctx->app_name : NULL;
}
switch (id) {
case NOTIFY_CARD_INSERTED:
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/VCard.icns";
break;
case NOTIFY_CARD_REMOVED:
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/EjectMediaIcon.icns";
break;
case NOTIFY_PIN_GOOD:
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/UnlockedIcon.icns";
break;
case NOTIFY_PIN_BAD:
icon = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/LockedIcon.icns";
break;
default:
icon = NULL;
break;
}
notify_proxy(ctx, title, NULL, text, icon, NULL, group);
}
#else
void sc_notify_init(void) {}
void sc_notify_close(void) {}
void sc_notify(const char *title, const char *text) {}
void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
struct sc_pkcs15_card *p15card, enum ui_str id) {}
#endif

40
src/ui/notify.h Normal file
View File

@ -0,0 +1,40 @@
/*
* notify.h: OpenSC library header file
*
* Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NOTIFY_H
#define _NOTIFY_H
#include "strings.h"
#ifdef __cplusplus
extern "C" {
#endif
void sc_notify_init(void);
void sc_notify_close(void);
void sc_notify(const char *title, const char *text);
void sc_notify_id(struct sc_context *ctx, struct sc_atr *atr,
struct sc_pkcs15_card *p15card, enum ui_str id);
#ifdef __cplusplus
}
#endif
#endif

313
src/ui/strings.c Normal file
View File

@ -0,0 +1,313 @@
/*
* strings.c: Implementation of default UI strings
*
* Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libopensc/internal.h"
#include "strings.h"
#include <string.h>
#include <locale.h>
enum ui_langs {
EN,
DE,
};
static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_atr *atr)
{
static char text[3*SC_MAX_ATR_SIZE] = {0};
const char prefix[] = "ATR: ";
if (p15card && p15card->card && p15card->card->name) {
return p15card->card->name;
}
if (!atr)
return NULL;
strcpy(text, prefix);
sc_bin_to_hex(atr->value, atr->len, text + (sizeof prefix) - 1,
sizeof(text) - (sizeof prefix) - 1, ':');
return text;
}
static const char *get_removed_text(struct sc_pkcs15_card *p15card)
{
if (p15card && p15card->card && p15card->card->reader
&& p15card->card->reader->name) {
return p15card->card->reader->name;
}
return NULL;
}
static const char *ui_get_config_str(struct sc_context *ctx,
struct sc_atr *atr, const char *flag_name, const char *ret_default)
{
const char *ret = ret_default;
scconf_block *atrblock = _sc_match_atr_block(ctx, NULL, atr);
if (atrblock)
ret = scconf_get_str(atrblock, flag_name, ret_default);
return ret;
}
static int find_lang_str(const char *str, enum ui_langs *lang)
{
if (str) {
if (0 == strncmp(str, "de", 2)) {
if (lang) {
*lang = DE;
}
return 1;
} else if (0 == strncmp(str, "en", 2)) {
if (lang) {
*lang = EN;
}
return 1;
}
}
return 0;
}
const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr,
struct sc_pkcs15_card *p15card, enum ui_str id)
{
enum ui_langs lang = EN;
const char *str, *option;
/* load option strings */
switch (id) {
case MD_PINPAD_DLG_TITLE:
option = "md_pinpad_dlg_title";
break;
case MD_PINPAD_DLG_MAIN:
option = "md_pinpad_dlg_main";
break;
case MD_PINPAD_DLG_CONTENT_USER:
option = "md_pinpad_dlg_content_user";
break;
case MD_PINPAD_DLG_CONTENT_ADMIN:
option = "md_pinpad_dlg_content_admin";
break;
case MD_PINPAD_DLG_CONTENT_CANCEL:
option = "md_pinpad_dlg_content_cancel";
break;
case MD_PINPAD_DLG_EXPANDED:
option = "md_pinpad_dlg_expanded";
break;
case MD_PINPAD_DLG_EXPANDED_CANCEL:
option = "md_pinpad_dlg_expanded_cancel";
break;
case MD_PINPAD_DLG_ICON:
option = "md_pinpad_dlg_icon";
break;
case NOTIFY_CARD_INSERTED:
option = "notify_card_inserted";
break;
case NOTIFY_CARD_INSERTED_TEXT:
option = "notify_card_inserted_text";
break;
case NOTIFY_CARD_REMOVED:
option = "notify_card_removed";
break;
case NOTIFY_CARD_REMOVED_TEXT:
option = "notify_card_removed_text";
break;
case NOTIFY_PIN_GOOD:
option = "notify_pin_good";
break;
case NOTIFY_PIN_GOOD_TEXT:
option = "notify_pin_good_text";
break;
case NOTIFY_PIN_BAD:
option = "notify_pin_bad";
break;
case NOTIFY_PIN_BAD_TEXT:
option = "notify_pin_bad_text";
break;
default:
option = NULL;
break;
}
/* load language */
/* card's language supersedes system's language */
if (!p15card || !p15card->tokeninfo
|| !find_lang_str(p15card->tokeninfo->preferred_language, &lang)) {
#ifdef _WIN32
LANGID langid = GetUserDefaultUILanguage();
if (langid & LANG_GERMAN) {
lang = DE;
}
#else
/* LANGUAGE supersedes locale */
if (!find_lang_str(getenv("LANGUAGE"), &lang)) {
/* XXX Should we use LC_MESSAGES instead? */
find_lang_str(setlocale(LC_ALL, ""), &lang);
}
#endif
}
/* load default strings */
switch (lang) {
case DE:
switch (id) {
case MD_PINPAD_DLG_TITLE:
str = "Windows-Sicherheit";
break;
case MD_PINPAD_DLG_MAIN:
str = "OpenSC Smartcard-Anbieter";
break;
case MD_PINPAD_DLG_CONTENT_USER:
str = "Bitte geben Sie Ihre PIN für die digitale Signatur auf dem PIN-Pad ein.";
break;
case MD_PINPAD_DLG_CONTENT_ADMIN:
str = "Bitte geben Sie Ihre PIN zum Entsperren der Nutzer-PIN auf dem PIN-Pad ein.";
break;
case MD_PINPAD_DLG_CONTENT_CANCEL:
str = "Nutzen Sie das PIN-Pad, um den Vorgang abzubrechen.";
break;
case MD_PINPAD_DLG_EXPANDED:
str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden).";
break;
case MD_PINPAD_DLG_EXPANDED_CANCEL:
str = "Einige Kartenleser unterstützen das Abbrechen ausschließlich am PIN-Pad. Drücken Sie Cancel (Abbruch) oder entfernen Sie die Karte.";
break;
case NOTIFY_CARD_INSERTED:
if (p15card) {
str = "Smartcard kann jetzt verwendet werden";
} else {
str = "Smartcard erkannt";
}
break;
case NOTIFY_CARD_INSERTED_TEXT:
str = get_inserted_text(p15card, atr);
break;
case NOTIFY_CARD_REMOVED:
str = "Smartcard entfernt";
break;
case NOTIFY_CARD_REMOVED_TEXT:
str = get_removed_text(p15card);
break;
case NOTIFY_PIN_GOOD:
str = "PIN verifiziert";
break;
case NOTIFY_PIN_GOOD_TEXT:
str = "Smartcard ist entsperrt";
break;
case NOTIFY_PIN_BAD:
str = "PIN nicht verifiziert";
break;
case NOTIFY_PIN_BAD_TEXT:
str = "Smartcard ist gesperrt";
break;
case MD_PINPAD_DLG_CONTROL_COLLAPSED:
/* fall through */
case MD_PINPAD_DLG_CONTROL_EXPANDED:
str = "Weitere Informationen";
break;
case MD_PINPAD_DLG_CANCEL:
str = "Abbrechen";
break;
default:
str = NULL;
break;
}
break;
case EN:
/* fall through */
default:
switch (id) {
case MD_PINPAD_DLG_TITLE:
str = "Windows Security";
break;
case MD_PINPAD_DLG_MAIN:
str = "OpenSC Smart Card Provider";
break;
case MD_PINPAD_DLG_CONTENT_USER:
str = "Please enter your digital signature PIN on the PIN pad.";
break;
case MD_PINPAD_DLG_CONTENT_ADMIN:
str = "Please enter your PIN to unblock the user PIN on the PIN pad.";
break;
case MD_PINPAD_DLG_CONTENT_CANCEL:
str = "Use the PIN pad to cancel the operation.";
break;
case MD_PINPAD_DLG_EXPANDED:
str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds).";
break;
case MD_PINPAD_DLG_EXPANDED_CANCEL:
str = "Some readers only support canceling the operation on the PIN pad. Press Cancel or remove the card.";
break;
case NOTIFY_CARD_INSERTED:
if (p15card) {
str = "Smart card is ready to use";
} else {
str = "Smart card detected";
}
break;
case NOTIFY_CARD_INSERTED_TEXT:
str = get_inserted_text(p15card, atr);
break;
case NOTIFY_CARD_REMOVED:
str = "Smart card removed";
break;
case NOTIFY_CARD_REMOVED_TEXT:
str = get_removed_text(p15card);
break;
case NOTIFY_PIN_GOOD:
str = "PIN verified";
break;
case NOTIFY_PIN_GOOD_TEXT:
str = "Smart card is unlocked";
break;
case NOTIFY_PIN_BAD:
str = "PIN not verified";
break;
case NOTIFY_PIN_BAD_TEXT:
str = "Smart card is locked";
break;
case MD_PINPAD_DLG_CONTROL_COLLAPSED:
/* fall through */
case MD_PINPAD_DLG_CONTROL_EXPANDED:
str = "Click here for more information";
break;
case MD_PINPAD_DLG_CANCEL:
str = "Cancel";
break;
default:
str = NULL;
break;
}
break;
}
/* user's strings supersede default strings */
if (option != NULL) {
/* overwrite str with the user's choice */
str = ui_get_config_str(ctx, atr, option, str);
}
return str;
}

59
src/ui/strings.h Normal file
View File

@ -0,0 +1,59 @@
/*
* strings.c: default UI strings
*
* Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _STRINGS_H
#define _STRINGS_H
#include "libopensc/pkcs15.h"
#ifdef __cplusplus
extern "C" {
#endif
enum ui_str {
MD_PINPAD_DLG_TITLE,
MD_PINPAD_DLG_MAIN,
MD_PINPAD_DLG_CONTENT_USER,
MD_PINPAD_DLG_CONTENT_ADMIN,
MD_PINPAD_DLG_CONTENT_CANCEL,
MD_PINPAD_DLG_EXPANDED,
MD_PINPAD_DLG_EXPANDED_CANCEL,
MD_PINPAD_DLG_CONTROL_COLLAPSED,
MD_PINPAD_DLG_CONTROL_EXPANDED,
MD_PINPAD_DLG_ICON,
MD_PINPAD_DLG_CANCEL,
NOTIFY_CARD_INSERTED,
NOTIFY_CARD_INSERTED_TEXT,
NOTIFY_CARD_REMOVED,
NOTIFY_CARD_REMOVED_TEXT,
NOTIFY_PIN_GOOD,
NOTIFY_PIN_GOOD_TEXT,
NOTIFY_PIN_BAD,
NOTIFY_PIN_BAD_TEXT,
};
const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr,
struct sc_pkcs15_card *p15card, enum ui_str id);
#ifdef __cplusplus
}
#endif
#endif