|
WizardsToolkit
1.0.7
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % PPPP AAA SSSSS SSSSS PPPP H H RRRR AAA SSSSS EEEEE % 00007 % P P A A SS SS P P H H R R A A SS E % 00008 % PPPP AAAAA SSS SSS PPPP HHHHH RRRR AAAAA SSS EEE % 00009 % P A A SS SS P H H R R A A SS E % 00010 % P A A SSSSS SSSSS P H H R R A A SSSSS EEEEE % 00011 % % 00012 % % 00013 % Wizard's Toolkit Passphrase Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % March 2003 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.wizards-toolkit.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 */ 00038 00039 #include "wizard/studio.h" 00040 #include "wizard/exception.h" 00041 #include "wizard/exception-private.h" 00042 #include "wizard/memory_.h" 00043 #include "wizard/passphrase.h" 00044 #include "wizard/utility-private.h" 00045 #if defined(WIZARDSTOOLKIT_HAVE_TERMIOS_H) 00046 #include <termios.h> 00047 #endif 00048 00049 /* 00050 Define declarations. 00051 */ 00052 #ifdef TCSASOFT 00053 # define _T_FLUSH (TCSAFLUSH | TCSASOFT) 00054 #else 00055 # define _T_FLUSH (TCSAFLUSH) 00056 #endif 00057 00058 #if !defined(_POSIX_VDISABLE) && defined(VDISABLE) 00059 # define _POSIX_VDISABLE VDISABLE 00060 #endif 00061 00062 #define _PATH_TTY "/dev/tty" 00063 00064 /* 00065 Typedef declarations. 00066 */ 00067 typedef enum 00068 { 00069 EchoOffMode = 0x00, /* Turn off echo (default). */ 00070 EchoOnMode = 0x01, /* Leave echo on. */ 00071 RequireTTYMode = 0x02, /* Fail if there is no tty. */ 00072 ForceLowerMode = 0x04, /* Force input to lower case. */ 00073 ForceUpperMode = 0x08, /* Force input to upper case. */ 00074 SevenBitMode = 0x10, /* Strip the high bit from input. */ 00075 StdinMode = 0x20 /* Read from stdin, not /dev/tty */ 00076 } PassphraseMode; 00077 00078 /* 00079 Global declarations. 00080 */ 00081 static volatile sig_atomic_t 00082 signal_number = 0; 00083 00084 /* 00085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00086 % % 00087 % % 00088 % % 00089 % G e t P h r a s e % 00090 % % 00091 % % 00092 % % 00093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00094 % 00095 % GetPhrase() gets a phrase from the terminal. 00096 % 00097 % The format of the GetPhrase method is: 00098 % 00099 % WizardBooleanType GetPhrase(const char *prompt,PassphraseMode flags, 00100 % StringInfo *phrase) 00101 % 00102 % A description of each parameter follows: 00103 % 00104 % o prompt: Prompt the user for the passphrase. 00105 % 00106 % o flags: modify the behavior of this method by setting one or more of 00107 % these flags: 00108 % 00109 % EchoOffMode Turn off echo (default). 00110 % EchoOnMode Leave echo on. 00111 % RequireTTYMode Fail if there is no tty. 00112 % ForceLowerMode Force input to lower case. 00113 % ForceUpperMode Force input to upper case. 00114 % SevenBitMode Strip the high bit from input. 00115 % StdinMode Read from stdin, not /dev/tty. 00116 % 00117 % o phrase: The passphrase is returned in this buffer. 00118 % 00119 */ 00120 00121 static void SignalHandler(int signal) 00122 { 00123 signal_number=(sig_atomic_t) signal; 00124 } 00125 00126 static WizardBooleanType GetPhrase(const char *prompt,PassphraseMode flags, 00127 StringInfo *phrase) 00128 { 00129 ssize_t 00130 count; 00131 00132 #if defined(WIZARDSTOOLKIT_HAVE_TERMIOS_H) 00133 char 00134 c; 00135 00136 int 00137 input, 00138 output; 00139 00140 register unsigned char 00141 *p; 00142 00143 struct sigaction 00144 action, 00145 sigalrm, 00146 sighup, 00147 sigint, 00148 sigpipe, 00149 sigquit, 00150 sigterm, 00151 sigtstp, 00152 sigttin, 00153 sigttou; 00154 00155 struct termios 00156 attributes, 00157 save_attributes; 00158 00159 /* 00160 Read and write to _PATH_TTY if available, otherwise from stdin. 00161 */ 00162 signal_number=0; 00163 input=STDIN_FILENO; 00164 output=STDERR_FILENO; 00165 if ((flags & StdinMode) == 0) 00166 { 00167 input=open_utf8(_PATH_TTY,O_RDWR,0); 00168 output=input; 00169 } 00170 if (((flags & StdinMode) != 0) || (input == -1) || (output == -1)) 00171 { 00172 if ((flags & RequireTTYMode) != 0) 00173 { 00174 errno=ENOTTY; 00175 return(WizardFalse); 00176 } 00177 } 00178 /* 00179 Set our signal handler. 00180 */ 00181 (void) sigemptyset(&action.sa_mask); 00182 action.sa_flags=0; /* don't restart system calls */ 00183 action.sa_handler=SignalHandler; 00184 (void) sigaction(SIGALRM,&action,&sigalrm); 00185 (void) sigaction(SIGHUP,&action,&sighup); 00186 (void) sigaction(SIGINT,&action,&sigint); 00187 (void) sigaction(SIGPIPE,&action,&sigpipe); 00188 (void) sigaction(SIGQUIT,&action,&sigquit); 00189 (void) sigaction(SIGTERM,&action,&sigterm); 00190 (void) sigaction(SIGTSTP,&action,&sigtstp); 00191 (void) sigaction(SIGTTIN,&action,&sigttin); 00192 (void) sigaction(SIGTTOU,&action,&sigttou); 00193 if ((input == STDIN_FILENO) || (tcgetattr(input,&save_attributes) != 0)) 00194 { 00195 (void) ResetWizardMemory(&attributes,0,sizeof(attributes)); 00196 attributes.c_lflag|=ECHO; 00197 (void) CopyWizardMemory(&save_attributes,&attributes,sizeof(attributes)); 00198 } 00199 else 00200 { 00201 /* 00202 Turn off echo. 00203 */ 00204 (void) CopyWizardMemory(&attributes,&save_attributes,sizeof(attributes)); 00205 if ((flags & EchoOnMode) == 0) 00206 attributes.c_lflag&=(~(ECHO | ECHONL)); 00207 #if defined(VSTATUS) 00208 if (attributes.c_cc[VSTATUS] != _POSIX_VDISABLE) 00209 attributes.c_cc[VSTATUS]=_POSIX_VDISABLE; 00210 #endif 00211 (void) tcsetattr(input,_T_FLUSH,&attributes); 00212 } 00213 if ((flags & StdinMode) == 0) 00214 count=write(output,prompt,strlen(prompt)); 00215 SetStringInfoLength(phrase,MaxTextExtent); 00216 p=GetStringInfoDatum(phrase); 00217 while (((count=read(input,&c,1)) == 1) && (c != '\n') && (c != '\r')) 00218 { 00219 if ((size_t) (p-GetStringInfoDatum(phrase)) < 00220 (GetStringInfoLength(phrase)-1)) 00221 { 00222 if ((flags & SevenBitMode) != 0) 00223 c&=0x7f; 00224 if (isalpha((int) c) != 0) 00225 { 00226 if ((flags & ForceLowerMode) != 0) 00227 c=(char) tolower((int) c); 00228 if ((flags & ForceUpperMode) != 0) 00229 c=(char) toupper((int) c); 00230 } 00231 *p++=(unsigned char) c; 00232 } 00233 } 00234 *p=(unsigned char) '\0'; 00235 SetStringInfoLength(phrase,(size_t) (p-GetStringInfoDatum(phrase))); 00236 if ((attributes.c_lflag & ECHO) == 0) 00237 count=write(output,"\n",1); 00238 /* 00239 Restore old terminal settings and signals. 00240 */ 00241 if (memcmp(&attributes,&save_attributes,sizeof(attributes)) != 0) 00242 (void) tcsetattr(input,_T_FLUSH,&save_attributes); 00243 (void) sigaction(SIGALRM,&sigalrm,(struct sigaction *) NULL); 00244 (void) sigaction(SIGHUP,&sighup,(struct sigaction *) NULL); 00245 (void) sigaction(SIGINT,&sigint,(struct sigaction *) NULL); 00246 (void) sigaction(SIGQUIT,&sigquit,(struct sigaction *) NULL); 00247 (void) sigaction(SIGPIPE,&sigpipe,(struct sigaction *) NULL); 00248 (void) sigaction(SIGTERM,&sigterm,(struct sigaction *) NULL); 00249 (void) sigaction(SIGTSTP,&sigtstp,(struct sigaction *) NULL); 00250 (void) sigaction(SIGTTIN,&sigttin,(struct sigaction *) NULL); 00251 if (input != STDIN_FILENO) 00252 input=close(input)-1; 00253 if (signal_number != 0) 00254 { 00255 /* 00256 We were interrupted by a signal. 00257 */ 00258 (void) kill((pid_t) getpid(),(int) signal_number); 00259 if ((signal_number == (sig_atomic_t) SIGTSTP) || 00260 (signal_number == (sig_atomic_t) SIGTTIN) || 00261 (signal_number == (sig_atomic_t) SIGTTOU)) 00262 return(GetPhrase(prompt,flags,phrase)); 00263 } 00264 #else 00265 (void) fputs(prompt,stdout); 00266 SetStringInfoLength(phrase,MaxTextExtent); 00267 count=read(fileno(stdin),GetStringInfoDatum(phrase),MaxTextExtent); 00268 SetStringInfoLength(phrase,count); 00269 #endif 00270 return(count != -1 ? WizardTrue : WizardFalse); 00271 } 00272 00273 /* 00274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00275 % % 00276 % % 00277 % % 00278 % G e t P a s s p h r a s e % 00279 % % 00280 % % 00281 % % 00282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00283 % 00284 % GetPassphrase() gets a passphrase from the terminal and returns it. 00285 % 00286 % The format of the GetPassphrase method is: 00287 % 00288 % StringInfo GetPassphrase(ExceptionInfo *exception) 00289 % 00290 % A description of each parameter follows: 00291 % 00292 % o prompt: Prompt the user for the passphrase. 00293 % 00294 */ 00295 WizardExport StringInfo *GetPassphrase(ExceptionInfo *exception) 00296 { 00297 char 00298 prompt[MaxTextExtent]; 00299 00300 WizardBooleanType 00301 status; 00302 00303 StringInfo 00304 *phrase, 00305 *rephrase; 00306 00307 phrase=AcquireStringInfo(MaxTextExtent); 00308 rephrase=AcquireStringInfo(MaxTextExtent); 00309 (void) FormatLocaleString(prompt,MaxTextExtent, 00310 "Enter the passphrase (maximum of %d characters)\n",MaxTextExtent); 00311 status=write(STDERR_FILENO,prompt,strlen(prompt)) < 0 ? WizardFalse : 00312 WizardTrue; 00313 for ( ; ; ) 00314 { 00315 status=GetPhrase("Enter passphrase: ",EchoOffMode,phrase); 00316 if (status == WizardFalse) 00317 { 00318 (void) ThrowWizardException(exception,GetWizardModule(), 00319 AuthenticateError,"unable to get pass phrase `%s'",strerror(errno)); 00320 return((StringInfo *) NULL); 00321 } 00322 status=GetPhrase("Enter same passphrase again: ",EchoOffMode,rephrase); 00323 if (status == WizardFalse) 00324 { 00325 (void) ThrowWizardException(exception,GetWizardModule(), 00326 AuthenticateError,"unable to get pass phrase `%s'",strerror(errno)); 00327 return((StringInfo *) NULL); 00328 } 00329 if (CompareStringInfo(phrase,rephrase) == 0) 00330 break; 00331 (void) PrintWizardString(stderr,"Passphrases are different. Try again.\n"); 00332 } 00333 rephrase=DestroyStringInfo(rephrase); 00334 SetStringInfoLength(phrase,GetStringInfoLength(phrase)); 00335 return(phrase); 00336 }