diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 1d42b0d5..000ca09a 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -11,7 +11,7 @@ noinst_HEADERS = cards.h ctbcs.h internal.h esteid.h muscle.h muscle-filesystem. cardctl.h asn1.h log.h \ errors.h types.h compression.h itacns.h iso7816.h \ authentic.h iasecc.h iasecc-sdo.h sm.h card-sc-hsm.h \ - pace.h cwa14890.h user-interface.h cwa-dnie.h + pace.h cwa14890.h cwa-dnie.h AM_CPPFLAGS = -DOPENSC_CONF_PATH=\"$(sysconfdir)/opensc.conf\" \ -I$(top_srcdir)/src @@ -40,7 +40,7 @@ libopensc_la_SOURCES = \ card-rtecp.c card-westcos.c card-myeid.c card-ias.c \ card-itacns.c card-authentic.c \ card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ - card-dnie.c cwa14890.c cwa-dnie.c user-interface.c \ + card-dnie.c cwa14890.c cwa-dnie.c \ card-isoApplet.c card-masktech.c \ \ pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \ diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak index bd33778c..1c078f4b 100644 --- a/src/libopensc/Makefile.mak +++ b/src/libopensc/Makefile.mak @@ -23,7 +23,7 @@ OBJECTS = \ card-rtecp.obj card-westcos.obj card-myeid.obj card-ias.obj \ card-itacns.obj card-authentic.obj \ card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ - card-sc-hsm.obj card-dnie.obj user-interface.obj card-isoApplet.obj \ + card-sc-hsm.obj card-dnie.obj card-isoApplet.obj \ card-masktech.obj \ \ pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \ diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 00968b29..f6eaf190 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -41,7 +41,20 @@ #include "compression.h" #include "cwa14890.h" #include "cwa-dnie.h" -#include "user-interface.h" + +#ifdef _WIN32 + +#ifndef UNICODE +#define UNICODE +#endif + +#include +#endif +#ifdef __APPLE__ +#include +#endif +/* default titles */ +#define USER_CONSENT_TITLE "Confirm" extern cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card); extern int dnie_read_file( @@ -142,6 +155,197 @@ const char *user_consent_message="Está a punto de realizar una firma electróni const char *user_consent_message="Esta a punto de realizar una firma digital\ncon su clave de FIRMA del DNI electronico.\nDesea permitir esta operacion?"; #endif +#ifdef ENABLE_DNIE_UI +/** + * Messages used on pinentry protocol + */ +char *user_consent_msgs[] = { "SETTITLE", "SETDESC", "CONFIRM", "BYE" }; + +/** + * Ask for user consent. + * + * Check for user consent configuration, + * Invoke proper gui app and check result + * + * @param card pointer to sc_card structure + * @param title Text to appear in the window header + * @param text Message to show to the user + * @return SC_SUCCESS on user consent OK , else error code + */ +int dnie_ask_user_consent(struct sc_card * card, const char *title, const char *message) +{ +#ifdef __APPLE__ + CFOptionFlags result; /* result code from the message box */ + /* convert the strings from char* to CFStringRef */ + CFStringRef header_ref; /* to store title */ + CFStringRef message_ref; /* to store message */ +#endif +#ifdef linux + pid_t pid; + FILE *fin=NULL; + FILE *fout=NULL; /* to handle pipes as streams */ + struct stat st_file; /* to verify that executable exists */ + int srv_send[2]; /* to send data from server to client */ + int srv_recv[2]; /* to receive data from client to server */ + char outbuf[1024]; /* to compose and send messages */ + char buf[1024]; /* to store client responses */ + int n = 0; /* to iterate on to-be-sent messages */ +#endif + int res = SC_ERROR_INTERNAL; /* by default error :-( */ + char *msg = NULL; /* to makr errors */ + + if ((card == NULL) || (card->ctx == NULL)) + return SC_ERROR_INVALID_ARGUMENTS; + LOG_FUNC_CALLED(card->ctx); + + if ((title==NULL) || (message==NULL)) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + + if (GET_DNIE_UI_CTX(card).user_consent_enabled == 0) { + sc_log(card->ctx, + "User Consent is disabled in configuration file"); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } +#ifdef _WIN32 + /* in Windows, do not use pinentry, but MessageBox system call */ + res = MessageBox ( + NULL, + TEXT(message), + TEXT(title), + MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_APPLMODAL + ); + if ( res == IDOK ) + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED); +#elif __APPLE__ + /* Also in Mac OSX use native functions */ + + /* convert the strings from char* to CFStringRef */ + header_ref = CFStringCreateWithCString( NULL, title, strlen(title) ); + message_ref = CFStringCreateWithCString( NULL,message, strlen(message) ); + + /* Displlay user notification alert */ + CFUserNotificationDisplayAlert( + 0, /* no timeout */ + kCFUserNotificationNoteAlertLevel, /* Alert level */ + NULL, /* IconURL, use default, you can change */ + /* it depending message_type flags */ + NULL, /* SoundURL (not used) */ + NULL, /* localization of strings */ + header_ref, /* header. Cannot be null */ + message_ref, /* message text */ + CFSTR("Cancel"), /* default ( "OK" if null) button text */ + CFSTR("OK"), /* second button title */ + NULL, /* third button title, null--> no other button */ + &result /* response flags */ + ); + + /* Clean up the strings */ + CFRelease( header_ref ); + CFRelease( message_ref ); + /* Return 0 only if "OK" is selected */ + if( result == kCFUserNotificationAlternateResponse ) + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED); +#elif linux + /* check that user_consent_app exists. TODO: check if executable */ + res = stat(GET_DNIE_UI_CTX(card).user_consent_app, &st_file); + if (res != 0) { + sc_log(card->ctx, "Invalid pinentry application: %s\n", + GET_DNIE_UI_CTX(card).user_consent_app); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } + + /* just a simple bidirectional pipe+fork+exec implementation */ + /* In a pipe, xx[0] is for reading, xx[1] is for writing */ + if (pipe(srv_send) < 0) { + msg = "pipe(srv_send)"; + goto do_error; + } + if (pipe(srv_recv) < 0) { + msg = "pipe(srv_recv)"; + goto do_error; + } + pid = fork(); + switch (pid) { + case -1: /* error */ + msg = "fork()"; + goto do_error; + case 0: /* child */ + /* make our pipes, our new stdin & stderr, closing older ones */ + dup2(srv_send[0], STDIN_FILENO); /* map srv send for input */ + dup2(srv_recv[1], STDOUT_FILENO); /* map srv_recv for output */ + /* once dup2'd pipes are no longer needed on client; so close */ + close(srv_send[0]); + close(srv_send[1]); + close(srv_recv[0]); + close(srv_recv[1]); + /* call exec() with proper user_consent_app from configuration */ + /* if ok should never return */ + execlp(GET_DNIE_UI_CTX(card).user_consent_app, GET_DNIE_UI_CTX(card).user_consent_app, (char *)NULL); + res = SC_ERROR_INTERNAL; + msg = "execlp() error"; /* exec() failed */ + goto do_error; + default: /* parent */ + /* Close the pipe ends that the child uses to read from / write to + * so when we close the others, an EOF will be transmitted properly. + */ + close(srv_send[0]); + close(srv_recv[1]); + /* use iostreams to take care on newlines and text based data */ + fin = fdopen(srv_recv[0], "r"); + if (fin == NULL) { + msg = "fdopen(in)"; + goto do_error; + } + fout = fdopen(srv_send[1], "w"); + if (fout == NULL) { + msg = "fdopen(out)"; + goto do_error; + } + /* read and ignore first line */ + fflush(stdin); + for (n = 0; n<4; n++) { + char *pt; + memset(outbuf, 0, sizeof(outbuf)); + if (n==0) snprintf(outbuf,1023,"%s %s\n",user_consent_msgs[0],title); + else if (n==1) snprintf(outbuf,1023,"%s %s\n",user_consent_msgs[1],message); + else snprintf(outbuf,1023,"%s\n",user_consent_msgs[n]); + /* send message */ + fputs(outbuf, fout); + fflush(fout); + /* get response */ + memset(buf, 0, sizeof(buf)); + pt=fgets(buf, sizeof(buf) - 1, fin); + if (pt==NULL) { + res = SC_ERROR_INTERNAL; + msg = "fgets() Unexpected IOError/EOF"; + goto do_error; + } + if (strstr(buf, "OK") == NULL) { + res = SC_ERROR_NOT_ALLOWED; + msg = "fail/cancel"; + goto do_error; + } + } + } /* switch */ + /* arriving here means signature has been accepted by user */ + res = SC_SUCCESS; + msg = NULL; +do_error: + /* close out channel to force client receive EOF and also die */ + if (fout != NULL) fclose(fout); + if (fin != NULL) fclose(fin); +#else +#error "Don't know how to handle user consent in this (rare) Operating System" +#endif + if (msg != NULL) + sc_log(card->ctx, "%s", msg); + LOG_FUNC_RETURN(card->ctx, res); +} + +#endif /* ENABLE_DNIE_UI */ + /** * DNIe specific card driver operations */ @@ -1372,7 +1576,7 @@ static int dnie_compute_signature(struct sc_card *card, #ifdef ENABLE_DNIE_UI /* (Requested by DGP): on signature operation, ask user consent */ if (GET_DNIE_PRIV_DATA(card)->rsa_key_ref == 0x02) { /* TODO: revise key ID handling */ - result = sc_ask_user_consent(card,user_consent_title,user_consent_message); + result = dnie_ask_user_consent(card,user_consent_title,user_consent_message); LOG_TEST_RET(card->ctx, result, "User consent denied"); } #endif diff --git a/src/libopensc/cwa-dnie.h b/src/libopensc/cwa-dnie.h index 31844704..8c0f2081 100644 --- a/src/libopensc/cwa-dnie.h +++ b/src/libopensc/cwa-dnie.h @@ -27,8 +27,15 @@ #include "libopensc/opensc.h" #include "cwa14890.h" + #ifdef ENABLE_DNIE_UI -#include "user-interface.h" +/** +* To handle user interface routines +*/ +typedef struct ui_context { + int user_consent_enabled; + char *user_consent_app; +} ui_context_t; #endif /** diff --git a/src/libopensc/user-interface.c b/src/libopensc/user-interface.c deleted file mode 100644 index dd3c7c09..00000000 --- a/src/libopensc/user-interface.c +++ /dev/null @@ -1,325 +0,0 @@ -/** - * user-interface.c: Support for GUI functions - * - * This file contains code for several related user-interface - * functions: - * - Ask user confirmation - * - Let user enter pin - * - * Copyright (C) 2010 Juan Antonio Martinez - * - * 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 - */ - -#define __USER_INTERFACE_C__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef ENABLE_OPENSSL /* empty file without openssl */ - -#include -#include -#include -#include - -#ifdef _WIN32 - -#ifndef UNICODE -#define UNICODE -#endif - -#include -#endif -#ifdef __APPLE__ -#include -#endif -/* default titles */ -#define USER_CONSENT_TITLE "Confirm" -#define USER_PIN_TITLE "PIN Request" -#define USER_PIN_PROMPT "Enter PIN:" - -#include "libopensc/opensc.h" -#include "libopensc/log.h" -#include "libopensc/user-interface.h" -#include "libopensc/cwa-dnie.h" - -#ifdef ENABLE_DNIE_UI -/** - * Messages used on pinentry protocol - */ -char *user_consent_msgs[] = { "SETTITLE", "SETDESC", "CONFIRM", "BYE" }; -char *user_pin_msgs[] = { "SETTITLE", "SETPROMPT", "GETPIN", "BYE" }; - -static int ui_ask_user_pin( - sc_context_t *ctx, /* Card context */ - const char *title, /* Title of the window */ - const char *msg, /* Text to be shown to the user */ - char *pinbuf, /* Where to store the user entered data */ - size_t *pinlen) { /* buffer length; on return user data length */ - - /* TODO: write :-) */ - return SC_ERROR_NOT_SUPPORTED; -} - -/** - * Ask user for pin. - * - * Check the user pin configuration, - * Invoke proper gui app and check result - * - * @param card pointer to sc_card structure - * @param title Text to appear in the window header - * @param pin Structure to handle/store pin related data - * @return SC_SUCCESS if user accepts , else error code - */ -int sc_ask_user_pin(struct sc_card * card, const char *title, struct sc_pin_cmd_pin *pin) { - char *pinbuf=NULL; - size_t pinlen=0; - int res=SC_ERROR_INTERNAL; - char *msg=NULL; - - if ( (card==NULL) || (card->ctx==NULL) ) - return SC_ERROR_INVALID_ARGUMENTS; - LOG_FUNC_CALLED(card->ctx); - if (pin==NULL) LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS); - - /* use a temporary buffer to ask for pin */ - if (pin->max_length<=0) { - msg="Invalid pin max lenght"; - res=SC_ERROR_INVALID_ARGUMENTS; - goto ask_user_pin_end; - } - pinlen=pin->max_length; - - pinbuf= calloc(pin->max_length, sizeof(char)); - if (!pinbuf) { - msg="Cannot create pin buffer"; - res=SC_ERROR_OUT_OF_MEMORY; - goto ask_user_pin_end; - } - - res= ui_ask_user_pin( - card->ctx, - (title==NULL)?USER_PIN_TITLE:title, - (pin->prompt==NULL)?USER_PIN_PROMPT:pin->prompt, - pinbuf, - &pinlen); - if (res!=SC_SUCCESS) { - msg="Error in ui_ask_user_pin"; - goto ask_user_pin_end; - } - - /* TODO: parse received data and fill result structure */ - - /* arriving here means success */ - res=SC_SUCCESS; - -ask_user_pin_end: - if (msg!=NULL) sc_log(card->ctx,msg); - if (pinbuf!=NULL) { - memset(pinbuf,0,pinlen); - free(pinbuf); - } - LOG_FUNC_RETURN(card->ctx,res); -} - -/** - * Ask for user consent. - * - * Check for user consent configuration, - * Invoke proper gui app and check result - * - * @param card pointer to sc_card structure - * @param title Text to appear in the window header - * @param text Message to show to the user - * @return SC_SUCCESS on user consent OK , else error code - */ -int sc_ask_user_consent(struct sc_card * card, const char *title, const char *message) -{ -#ifdef __APPLE__ - CFOptionFlags result; /* result code from the message box */ - /* convert the strings from char* to CFStringRef */ - CFStringRef header_ref; /* to store title */ - CFStringRef message_ref; /* to store message */ -#endif -#ifdef linux - pid_t pid; - FILE *fin=NULL; - FILE *fout=NULL; /* to handle pipes as streams */ - struct stat st_file; /* to verify that executable exists */ - int srv_send[2]; /* to send data from server to client */ - int srv_recv[2]; /* to receive data from client to server */ - char outbuf[1024]; /* to compose and send messages */ - char buf[1024]; /* to store client responses */ - int n = 0; /* to iterate on to-be-sent messages */ -#endif - int res = SC_ERROR_INTERNAL; /* by default error :-( */ - char *msg = NULL; /* to makr errors */ - - if ((card == NULL) || (card->ctx == NULL)) - return SC_ERROR_INVALID_ARGUMENTS; - LOG_FUNC_CALLED(card->ctx); - - if ((title==NULL) || (message==NULL)) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - - if (GET_DNIE_UI_CTX(card).user_consent_enabled == 0) { - sc_log(card->ctx, - "User Consent is disabled in configuration file"); - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); - } -#ifdef _WIN32 - /* in Windows, do not use pinentry, but MessageBox system call */ - res = MessageBox ( - NULL, - TEXT(message), - TEXT(title), - MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_APPLMODAL - ); - if ( res == IDOK ) - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED); -#elif __APPLE__ - /* Also in Mac OSX use native functions */ - - /* convert the strings from char* to CFStringRef */ - header_ref = CFStringCreateWithCString( NULL, title, strlen(title) ); - message_ref = CFStringCreateWithCString( NULL,message, strlen(message) ); - - /* Displlay user notification alert */ - CFUserNotificationDisplayAlert( - 0, /* no timeout */ - kCFUserNotificationNoteAlertLevel, /* Alert level */ - NULL, /* IconURL, use default, you can change */ - /* it depending message_type flags */ - NULL, /* SoundURL (not used) */ - NULL, /* localization of strings */ - header_ref, /* header. Cannot be null */ - message_ref, /* message text */ - CFSTR("Cancel"), /* default ( "OK" if null) button text */ - CFSTR("OK"), /* second button title */ - NULL, /* third button title, null--> no other button */ - &result /* response flags */ - ); - - /* Clean up the strings */ - CFRelease( header_ref ); - CFRelease( message_ref ); - /* Return 0 only if "OK" is selected */ - if( result == kCFUserNotificationAlternateResponse ) - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED); -#elif linux - /* check that user_consent_app exists. TODO: check if executable */ - res = stat(GET_DNIE_UI_CTX(card).user_consent_app, &st_file); - if (res != 0) { - sc_log(card->ctx, "Invalid pinentry application: %s\n", - GET_DNIE_UI_CTX(card).user_consent_app); - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - } - - /* just a simple bidirectional pipe+fork+exec implementation */ - /* In a pipe, xx[0] is for reading, xx[1] is for writing */ - if (pipe(srv_send) < 0) { - msg = "pipe(srv_send)"; - goto do_error; - } - if (pipe(srv_recv) < 0) { - msg = "pipe(srv_recv)"; - goto do_error; - } - pid = fork(); - switch (pid) { - case -1: /* error */ - msg = "fork()"; - goto do_error; - case 0: /* child */ - /* make our pipes, our new stdin & stderr, closing older ones */ - dup2(srv_send[0], STDIN_FILENO); /* map srv send for input */ - dup2(srv_recv[1], STDOUT_FILENO); /* map srv_recv for output */ - /* once dup2'd pipes are no longer needed on client; so close */ - close(srv_send[0]); - close(srv_send[1]); - close(srv_recv[0]); - close(srv_recv[1]); - /* call exec() with proper user_consent_app from configuration */ - /* if ok should never return */ - execlp(GET_DNIE_UI_CTX(card).user_consent_app, GET_DNIE_UI_CTX(card).user_consent_app, (char *)NULL); - res = SC_ERROR_INTERNAL; - msg = "execlp() error"; /* exec() failed */ - goto do_error; - default: /* parent */ - /* Close the pipe ends that the child uses to read from / write to - * so when we close the others, an EOF will be transmitted properly. - */ - close(srv_send[0]); - close(srv_recv[1]); - /* use iostreams to take care on newlines and text based data */ - fin = fdopen(srv_recv[0], "r"); - if (fin == NULL) { - msg = "fdopen(in)"; - goto do_error; - } - fout = fdopen(srv_send[1], "w"); - if (fout == NULL) { - msg = "fdopen(out)"; - goto do_error; - } - /* read and ignore first line */ - fflush(stdin); - for (n = 0; n<4; n++) { - char *pt; - memset(outbuf, 0, sizeof(outbuf)); - if (n==0) snprintf(outbuf,1023,"%s %s\n",user_consent_msgs[0],title); - else if (n==1) snprintf(outbuf,1023,"%s %s\n",user_consent_msgs[1],message); - else snprintf(outbuf,1023,"%s\n",user_consent_msgs[n]); - /* send message */ - fputs(outbuf, fout); - fflush(fout); - /* get response */ - memset(buf, 0, sizeof(buf)); - pt=fgets(buf, sizeof(buf) - 1, fin); - if (pt==NULL) { - res = SC_ERROR_INTERNAL; - msg = "fgets() Unexpected IOError/EOF"; - goto do_error; - } - if (strstr(buf, "OK") == NULL) { - res = SC_ERROR_NOT_ALLOWED; - msg = "fail/cancel"; - goto do_error; - } - } - } /* switch */ - /* arriving here means signature has been accepted by user */ - res = SC_SUCCESS; - msg = NULL; -do_error: - /* close out channel to force client receive EOF and also die */ - if (fout != NULL) fclose(fout); - if (fin != NULL) fclose(fin); -#else -#error "Don't know how to handle user consent in this (rare) Operating System" -#endif - if (msg != NULL) - sc_log(card->ctx, "%s", msg); - LOG_FUNC_RETURN(card->ctx, res); -} - -#endif /* ENABLE_DNIE_UI */ - -#endif /* ENABLE_OPENSSL */ diff --git a/src/libopensc/user-interface.h b/src/libopensc/user-interface.h deleted file mode 100644 index 14f635a5..00000000 --- a/src/libopensc/user-interface.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * user-interface.c: Support for GUI functions - * - * This file contains code for several related user-interface - * functions: - * - Ask user confirmation - * - Let user enter pin - * - * Copyright (C) 2010 Juan Antonio Martinez - * - * 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 __USER_INTERFACE_H__ -#define __USER_INTERFACE_H__ - -/** - * To handle user interface routines - */ -typedef struct ui_context { - int user_consent_enabled; - char *user_consent_app; -} ui_context_t; - -struct sc_card; -struct sc_pin_cmd_pin; - -/** - * Ask for user consent. - * - * Check for user consent configuration, - * invoke proper gui app and check result - * - * @param card pointer to sc_card structure - * @param title Text to appear in the window header - * @param text Message to show to the user - * @return SC_SUCCESS if user accepts , else error code - */ -int sc_ask_user_consent(struct sc_card * card, const char *title, const char *message); - -/** - * Ask user for pin. - * - * Check the user pin configuration, - * invoke proper gui app and check result - * - * @param card pointer to sc_card structure - * @param title Text to appear in the window header - * @param pin Structure to handle/store pin related data - * @return SC_SUCCESS if user accepts , else error code - */ -int sc_ask_user_pin(struct sc_card * card, const char *title, struct sc_pin_cmd_pin *pin); - -#endif