Am Donnerstag 15 April 2010 19:41:45 schrieb OpenSC: > #120: pkcs15-init needs to accept ctrl-c > --------------------+------------------------------------------------------ > - Reporter: aj | Owner: opensc-de...@… > Type: defect | Status: new > Priority: normal | Milestone: 0.12.0 > Component: tools | Version: 0.11.1 > Severity: normal | Keywords: > --------------------+------------------------------------------------------ > - > > Comment(by viktor.tara...@…): > > I propose to implement local version of getpass() sensible to Ctrl-C . > > Any objections? >
can you test attached patch? it is incomplete, but replaces getpass with out own code. it uses the recommended replacement for getpass - turn off echo with termios. like getline it will allocate space and the caller needs to free that space (and for PINs and passwords: cleanse it). because of that interface change the difference is quite big. not sure if it is such a good idea to change this interface. but the old interface with a pointer to some static data isn't great either. Regards, Andreas
diff -udrNPp --exclude=.svn opensc.orig/src/tools/pkcs11-tool.c opensc/src/tools/pkcs11-tool.c --- opensc.orig/src/tools/pkcs11-tool.c 2010-02-16 10:38:01.000000000 +0100 +++ opensc/src/tools/pkcs11-tool.c 2010-02-26 10:58:12.000000000 +0100 @@ -24,7 +24,6 @@ #include <opensc/pkcs11.h> #include <opensc/pkcs11-opensc.h> -#include <compat_getpass.h> #include "util.h" #ifdef ENABLE_OPENSSL @@ -848,6 +847,8 @@ static void list_objects(CK_SESSION_HAND static int login(CK_SESSION_HANDLE session, int login_type) { char *pin = NULL; + size_t len; + int pin_allocated = 0, r; CK_TOKEN_INFO info; CK_RV rv; @@ -867,12 +868,16 @@ static int login(CK_SESSION_HANDLE sessi if (!pin && (info.flags & CKF_LOGIN_REQUIRED) && !(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { - if (login_type == CKU_SO) - pin = getpass("Please enter SO PIN: "); + if (login_type == CKU_SO) + printf("Please enter SO PIN: "); else if (login_type == CKU_USER) - pin = getpass("Please enter User PIN: "); + printf("Please enter User PIN: "); else if (login_type == CKU_CONTEXT_SPECIFIC) - pin = getpass("Please enter Specific Context Secret Code: "); + printf("Please enter Specific Context Secret Code: "); + r = util_getpass(&pin,&len,stdin); + if (r < 0) + util_fatal("No PIN entered, exiting!\n"); + pin_allocated = 1; } if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) @@ -884,6 +889,8 @@ static int login(CK_SESSION_HANDLE sessi (CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin)); if (rv != CKR_OK) p11_fatal("C_Login", rv); + if (pin_allocated) + free(pin); return 0; } @@ -892,6 +899,8 @@ static void init_token(CK_SLOT_ID slot) { unsigned char token_label[33]; char new_buf[21], *new_pin = NULL; + size_t len; + int pin_allocated = 0, r; CK_TOKEN_INFO info; CK_RV rv; @@ -903,15 +912,22 @@ static void init_token(CK_SLOT_ID slot) get_token_info(slot, &info); if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { if (opt_so_pin == NULL) { - new_pin = getpass("Please enter the new SO PIN: "); + printf("Please enter the new SO PIN: "); + r = util_getpass(&new_pin,&len,stdin); + if (r < 0) + util_fatal("No PIN entered, exiting\n"); if (!new_pin || !*new_pin || strlen(new_pin) > 20) util_fatal("Invalid SO PIN\n"); strcpy(new_buf, new_pin); - new_pin = getpass("Please enter the new SO PIN " - "(again): "); + free(new_pin); new_pin = NULL; + printf("Please enter the new SO PIN (again): "); + r = util_getpass(&new_pin,&len,stdin); + if (r < 0) + util_fatal("No PIN entered, exiting\n"); if (!new_pin || !*new_pin || strcmp(new_buf, new_pin) != 0) util_fatal("Different new SO PINs, exiting\n"); + pin_allocated = 1; } else { new_pin = opt_so_pin; } @@ -924,33 +940,56 @@ static void init_token(CK_SLOT_ID slot) if (rv != CKR_OK) p11_fatal("C_InitToken", rv); printf("Token successfully initialized\n"); + + if (pin_allocated) + free(new_pin); } static void init_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess) { - char new_buf[21], *new_pin = NULL; + char *pin; + char *new_pin1 = NULL; + char *new_pin2 = NULL; + size_t len1, len2; + ssize_t r; CK_TOKEN_INFO info; CK_RV rv; get_token_info(slot, &info); - new_pin = opt_pin ? opt_pin : opt_new_pin; - if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { - if (new_pin == NULL) { - new_pin = getpass("Please enter the new PIN: "); - if (!new_pin || !*new_pin || strlen(new_pin) > 20) + if (! opt_pin && !opt_new_pin) { + printf("Please enter the new PIN: "); + r = util_getpass(&new_pin1,&len1,stdin); + if (r < 0) + util_fatal("No PIN entered, aborting.\n"); + if (!new_pin1 || !*new_pin1 || strlen(new_pin1) > 20) util_fatal("Invalid User PIN\n"); - strcpy(new_buf, new_pin); - new_pin = getpass("Please enter the new PIN again: "); - if (!new_pin || !*new_pin || - strcmp(new_buf, new_pin) != 0) + printf("Please enter the new PIN again: "); + r = util_getpass(&new_pin2,&len2,stdin); + if (r < 0) + util_fatal("No PIN entered, aborting.\n"); + if (!new_pin2 || !*new_pin2 || + strcmp(new_pin1, new_pin2) != 0) util_fatal("Different new User PINs, exiting\n"); } } + + pin = opt_pin; + if (!pin) pin = opt_new_pin; + if (!pin) pin = new_pin1; + + rv = p11->C_InitPIN(sess, (CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin)); + + if (new_pin1) { + bzero(new_pin1,len1); + free(new_pin1); + } + if (new_pin2) { + bzero(new_pin2,len2); + free(new_pin2); + } - rv = p11->C_InitPIN(sess, - (CK_UTF8CHAR *) new_pin, new_pin == NULL ? 0 : strlen(new_pin)); if (rv != CKR_OK) p11_fatal("C_InitPIN", rv); printf("User PIN successfully initialized\n"); diff -udrNPp --exclude=.svn opensc.orig/src/tools/util.c opensc/src/tools/util.c --- opensc.orig/src/tools/util.c 2010-02-16 10:38:01.000000000 +0100 +++ opensc/src/tools/util.c 2010-02-26 10:43:01.000000000 +0100 @@ -5,6 +5,7 @@ #include <stdlib.h> #include <stdarg.h> #include <ctype.h> +#include <termios.h> #include "util.h" int util_connect_card(sc_context_t *ctx, sc_card_t **cardp, @@ -281,3 +282,60 @@ util_warn(const char *fmt, ...) va_end(ap); } +ssize_t util_getpass (char **lineptr, size_t *len, FILE *stream) +{ +#ifdef _WIN32 +#define MAX_PASS_SIZE 128 + char *buf; + size_t i,n; + + buf = malloc(MAX_PASS_SIZE); + if (!buf) + return -1; + bzero(buf,MAX_PASS_SIZE); + + for (i = 0; i < MAX_PASS_SIZE - 1; i++) { + buf[i] = _getch(); + if (buf[i] == '\n' || buf[i] == 0) + break; + } + buf[i] = 0; + + if (*lineptr) { + if (*len < i+1) { + free(*lineptr); + *lineptr=buf; + *len = MAX_PASS_SIZE; + } else { + memcpy(*lineptr,buf,i+1); + bzero(buf,MAX_PASS_SIZE); + free(buf); + } + } else { + *lineptr = buf; + if (len) + *len = MAX_PASS_SIZE; + } + return i; +} +#else + struct termios old, new; + ssize_t nread; + + /* Turn echoing off and fail if we can't. */ + if (tcgetattr (fileno (stream), &old) != 0) + return -1; + new = old; + new.c_lflag &= ~ECHO; + if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0) + return -1; + + /* Read the password. */ + nread = getline (lineptr, len, stream); + + /* Restore terminal. */ + (void) tcsetattr (fileno (stream), TCSAFLUSH, &old); + return nread; +#endif +} + diff -udrNPp --exclude=.svn opensc.orig/src/tools/util.h opensc/src/tools/util.h --- opensc.orig/src/tools/util.h 2010-02-16 10:38:01.000000000 +0100 +++ opensc/src/tools/util.h 2010-02-26 10:19:04.000000000 +0100 @@ -35,6 +35,8 @@ void util_fatal(const char *fmt, ...); /* All singing all dancing card connect routine */ int util_connect_card(struct sc_context *, struct sc_card **, char *reader_id, int wait, int verbose); +ssize_t util_getpass (char **lineptr, size_t *n, FILE *stream); + #ifdef __cplusplus } #endif
_______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel