- Added new user interface code (not used yet)

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1553 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2003-10-21 11:12:32 +00:00
parent f730572f34
commit 5791395e74
3 changed files with 334 additions and 1 deletions

View File

@ -13,7 +13,7 @@ bin_SCRIPTS = opensc-config
lib_LTLIBRARIES = libopensc.la
libopensc_la_SOURCES = \
sc.c ctx.c log.c errors.c portability.c module.c \
sc.c ctx.c ui.c log.c errors.c portability.c module.c \
asn1.c base64.c sec.c card.c iso7816.c dir.c padding.c \
\
pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \

240
src/libopensc/ui.c Normal file
View File

@ -0,0 +1,240 @@
/*
* User interface layer. This library adds an abstraction layer to
* user interaction, allowing to configure at run time with ui
* to use (tty, qt, gnome, win32, ...)
*
* Dynamically loads user interface libraries for different platforms,
* if configured. Otherwise, uses default functions that communicate
* with the user through stdin/stdout.
*
* Copyright (C) 2003 Olaf Kirch <okir@lse.de>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <opensc/opensc.h>
#include <opensc/scdl.h>
#include <opensc/log.h>
#include <opensc/ui.h>
#include "internal.h"
/*
* We keep a global shared library handle here.
* This is ugly; we should somehow tie this to the sc_context.
*/
static void * sc_ui_lib_handle = NULL;
static int sc_ui_lib_loaded = 0;
typedef int sc_ui_get_pin_fn_t(sc_context_t *, const char *,
const char *,
const sc_ui_get_pin_info_t *, char **);
typedef int sc_ui_get_pin_pair_fn_t(sc_context_t *, const char *,
const char *,
const sc_ui_get_pin_info_t *, char **,
const sc_ui_get_pin_info_t *, char **);
static int sc_ui_get_func(sc_context_t *, const char *, void **);
static int sc_ui_get_pin_default(sc_context_t *, const char *,
const char *,
const sc_ui_get_pin_info_t *, char **);
static int sc_ui_get_pin_pair_default(sc_context_t *, const char *,
const char *,
const sc_ui_get_pin_info_t *, char **,
const sc_ui_get_pin_info_t *, char **);
/*
* Retrieve a PIN from the user.
*/
int
sc_ui_get_pin(sc_context_t *ctx, const char *name, const char *prompt,
const sc_ui_get_pin_info_t *info, char **out)
{
static sc_ui_get_pin_fn_t *get_pin_fn;
int r;
if (!get_pin_fn) {
void *addr;
r = sc_ui_get_func(ctx,
"sc_ui_get_pin_handler",
&addr);
if (r < 0)
return r;
get_pin_fn = (sc_ui_get_pin_fn_t *) addr;
if (get_pin_fn == NULL)
get_pin_fn = sc_ui_get_pin_default;
}
return get_pin_fn(ctx, name, prompt, info, out);
}
int
sc_ui_get_pin_pair(sc_context_t *ctx, const char *name, const char *prompt,
const sc_ui_get_pin_info_t *old_info, char **old_out,
const sc_ui_get_pin_info_t *new_info, char **new_out)
{
static sc_ui_get_pin_pair_fn_t *get_pin_pair_fn;
int r;
if (!get_pin_pair_fn) {
void *addr;
r = sc_ui_get_func(ctx,
"sc_ui_get_pin_pair_handler",
&addr);
if (r < 0)
return r;
get_pin_pair_fn = (sc_ui_get_pin_pair_fn_t *) addr;
if (get_pin_pair_fn == NULL)
get_pin_pair_fn = sc_ui_get_pin_pair_default;
}
return get_pin_pair_fn(ctx, name, prompt,
old_info, old_out,
new_info, new_out);
}
/*
* Get the named functions from the user interface
* library. If no library is configured, or if the
* libray doesn't define the named symbol, fall back
* to the default function
*/
int
sc_ui_get_func(sc_context_t *ctx, const char *name, void **ret)
{
int r;
if (!sc_ui_lib_handle && !sc_ui_lib_loaded) {
const char *lib_name = NULL;
scconf_block *blk;
int i;
/* Prevent recursion */
sc_ui_lib_loaded = 1;
for (i = 0; (blk = ctx->conf_blocks[i]); i++) {
lib_name = scconf_get_str(blk,
"user_interface",
NULL);
if (lib_name)
break;
}
if (!lib_name)
return 0;
r = sc_module_open(ctx, &sc_ui_lib_handle, lib_name);
if (r < 0) {
sc_error(ctx,
"Unable to open user interface library %s\n",
lib_name);
return r;
}
}
return sc_module_get_address(ctx, sc_ui_lib_handle, ret, name);
}
/*
* Default ui functions
*/
int
sc_ui_get_pin_default(sc_context_t *ctx, const char *name,
const char *prompt,
const sc_ui_get_pin_info_t *info,
char **out)
{
const char *name_hint;
if ((name_hint = info->name_hint) == NULL)
name_hint = "PIN";
if (prompt) {
printf("%s%s.\n", prompt,
(info->flags & SC_UI_PIN_OPTIONAL)? "" :
" (Optional - press return for no PIN)");
}
*out = NULL;
while (1) {
char buffer[64], *pin;
size_t len;
snprintf(buffer, sizeof(buffer),
"Please enter %s: ", name_hint);
if ((pin = getpass(buffer)) == NULL)
return SC_ERROR_INTERNAL;
len = strlen(pin);
if (len == 0 && (info->flags & SC_UI_PIN_OPTIONAL))
return SC_ERROR_KEYPAD_CANCELLED;
if (info->flags & SC_UI_PIN_CHECK_LENGTH) {
if (len < info->min_len) {
fprintf(stderr,
"PIN too short (min %u characters)\n",
info->min_len);
continue;
}
if (len > info->max_len) {
fprintf(stderr,
"PIN too long (max %u characters)\n",
info->max_len);
continue;
}
}
*out = strdup(pin);
memset(pin, 0, len);
if (!(info->flags & SC_UI_PIN_RETYPE))
break;
pin = getpass("Please type again to verify: ");
if (!strcmp(*out, pin)) {
memset(pin, 0, len);
break;
}
free(*out);
*out = NULL;
if (!(info->flags & SC_UI_PIN_MISMATCH_RETRY)) {
fprintf(stderr, "PINs do not match.\n");
return SC_ERROR_KEYPAD_PIN_MISMATCH;
}
memset(pin, 0, strlen(pin));
/* Currently, there's no way out of this dialog.
* We should allow the user to bail out after n
* attempts. */
}
return 0;
}
int
sc_ui_get_pin_pair_default(sc_context_t *ctx, const char *name,
const char *prompt,
const sc_ui_get_pin_info_t *old_info, char **old_out,
const sc_ui_get_pin_info_t *new_info, char **new_out)
{
int r;
if (prompt)
printf("%s\n", prompt);
r = sc_ui_get_pin_default(ctx, "foo", NULL, old_info, old_out);
if (r < 0)
return r;
return sc_ui_get_pin_default(ctx, "foo", NULL, new_info, new_out);
}

93
src/libopensc/ui.h Normal file
View File

@ -0,0 +1,93 @@
/*
* User interface layer.
*
* Copyright (C) 2003 Olaf Kirch <okir@lse.de>
*/
#ifndef _SC_UI_H
#define _SC_UI_H
#include <opensc/opensc.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct sc_ui_get_pin_info {
const char * name_hint; /* PIN/PUK/old PIN etc */
int flags;
unsigned int min_len, max_len;
} sc_ui_get_pin_info_t;
#define SC_UI_PIN_RETYPE 0x0001 /* new pin, retype */
#define SC_UI_PIN_OPTIONAL 0x0002 /* new pin optional */
#define SC_UI_PIN_CHECK_LENGTH 0x0004 /* check pin length */
#define SC_UI_PIN_MISMATCH_RETRY 0x0008 /* retry if new pin mismatch? */
/*
* Specify the dialog language, if the backend is localized.
*/
extern int sc_ui_set_language(sc_context_t *, const char *);
/*
* Retrieve a PIN from the user.
*
* @name Dialog name, can be used by the dialog backend
* to retrieve additional resources such as help
* texts, icons etc.
* @prompt Text prompt that is displayed if there's no
* GUI backend configured.
* @info Additional info on the dialog to display.
* @out PIN entered by the user; must be freed.
* NULL if dialog was canceled.
*/
extern int sc_ui_get_pin(sc_context_t *ctx,
const char *name,
const char *prompt,
const sc_ui_get_pin_info_t *info,
char **out);
/*
* PIN pair dialog. Can be used for PIN change/unblock, but
* also to enter a PIN/PUK pair.
*
* @name Dialog name, can be used by the dialog backend
* to retrieve additional resources such as help
* texts, icons etc.
* @prompt Text prompt that is displayed if there's no
* GUI backend configured.
* @old_info Additional info on the dialog to display.
* @old_out PIN entered by the user; must be freed.
* NULL if dialog was canceled.
* @new_info Additional info on the dialog to display.
* @new_out PIN entered by the user; must be freed.
* NULL if dialog was canceled.
*/
extern int sc_ui_get_pin_pair(sc_context_t *ctx,
const char *name,
const char *prompt,
const sc_ui_get_pin_info_t *old_info,
char **old_out,
const sc_ui_get_pin_info_t *new_info,
char **new_out);
/*
* Other ui functions, not fully spec'ed yet
*/
extern int sc_ui_display_question(sc_context_t *ctx,
const char *name,
const char *prompt);
extern int sc_ui_display_message(sc_context_t *ctx,
const char *name,
const char *message);
extern int sc_ui_display_error(sc_context_t *ctx,
const char *msg);
extern int sc_ui_display_debug(sc_context_t *ctx,
const char *msg);
#ifdef __cplusplus
}
#endif
#endif /* _SC_UI_H */