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

Reply via email to