libdigidocpp
EstEIDConsolePinSigner.cpp
Go to the documentation of this file.
1 /*
2  * libdigidocpp
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  */
19 
20 #include "EstEIDConsolePinSigner.h"
21 
22 #include "../../log.h"
23 
24 #if defined(_WIN32)
25 #include <conio.h>
26 #else
27 #include <string.h>
28 #include <unistd.h>
29 #endif
30 
41 digidoc::EstEIDConsolePinSigner::EstEIDConsolePinSigner(const std::string& driver, const std::string& prompt) throw(SignException)
42  : EstEIDSigner(driver)
43  , prompt(prompt)
44 {
45 }
46 
55  : EstEIDSigner(driver)
56  , prompt("Please enter PIN for token '%s' or <enter> to cancel: ")
57 {
58 }
59 
64 {
65 }
66 
70 void digidoc::EstEIDConsolePinSigner::setPrompt(const std::string& prompt)
71 {
72  this->prompt = prompt;
73 }
74 
83 {
84  char pin[16];
85  size_t pinMax = 16;
86 
87 #if defined(_WIN32)
88  // something that acts wildly similarily with getpass()
89  {
90  printf( prompt.c_str(), certificate.token.label.c_str() );
91  size_t i = 0;
92  int c;
93  while ( (c = _getch()) != '\r' )
94  {
95  switch ( c )
96  {
97  default:
98  if ( i >= pinMax-1 || iscntrl( c ) )
99  {
100  // can't be a part of password
101  fputc( '\a', stdout );
102  break;
103  }
104  pin[i++] = static_cast<char>(c);
105  fputc( '*', stdout );
106  break;
107  case EOF:
108  {
109  fputs( "[EOF]\n", stdout );
110  SignException e( __FILE__, __LINE__, "PIN acquisition canceled with [EOF].");
112  throw e;
113  break;
114  }
115  case 0:
116  case 0xE0: // FN Keys (0 or E0) start of two-character FN code
117  c = ( c << 4 ) | _getch();
118  if ( c != 0xE53 && c != 0xE4B && c != 0x053 && c != 0x04b )
119  {
120  // not {DELETE}, {<--}, Num{DEL} and Num{<--}
121  fputc( '\a', stdout );
122  break;
123  }
124  // NO BREAK, fall through to the one-character deletes
125  case '\b':
126  case '127':
127  if ( i == 0 )
128  {
129  // nothing to delete
130  fputc( '\a', stdout );
131  break;
132  }
133  pin[--i] = '\0';
134  fputs( "\b \b", stdout );
135  break;
136  case 3: // CTRL+C
137  {
138  fputs( "^C\n", stdout );
139  SignException e( __FILE__, __LINE__, "PIN acquisition canceled with ^C.");
141  throw e;
142  break;
143  }
144  case 26: // CTRL+Z
145  {
146  fputs( "^Z\n", stdout );
147  SignException e( __FILE__, __LINE__, "PIN acquisition canceled with ^Z.");
149  throw e;
150  break;
151  }
152  case 27: // ESC
153  fputc('\n', stdout );
154  printf( prompt.c_str(), certificate.token.label.c_str() );
155  i = 0;
156  break;
157  }
158  }
159  fputc( '\n', stdout );
160  pin[i] = '\0';
161  }
162 #else
163  char* pwd = getpass(Log::format(prompt.c_str(), certificate.token.label.c_str()).c_str());
164  strncpy(pin, pwd, pinMax);
165 #endif
166 
167  pin[pinMax-1] = '\0';
168 
169  std::string result(pin);
170  if(result.empty())
171  {
172  SignException e( __FILE__, __LINE__, "PIN acquisition canceled.");
174  throw e;
175  }
176 
177  return result;
178 }