warning-cleanup-20010414
[openafs.git] / src / des / read_pssword.c
1 /*
2  *
3  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
4  * of Technology.
5  *
6  * For copying and distribution information, please see the file
7  * <mit-cpyright.h>.
8  *
9  * This routine prints the supplied string to standard
10  * output as a prompt, and reads a password string without
11  * echoing.
12  */
13
14 #include <afs/param.h>
15 #include <mit-cpyright.h>
16 #include <des.h>
17 #include "conf.h"
18
19 #include <stdio.h>
20
21 #if defined(AFS_SUN5_ENV) || defined(AFS_NT40_ENV)
22 #include <string.h>
23 #else
24 #include <strings.h>
25 #endif
26
27 #ifdef  BSDUNIX
28 #ifdef  AFS_SUN5_ENV
29 #define BSD_COMP
30 #endif
31 #if defined(AFS_FBSD_ENV)
32 #define USE_OLD_TTY
33 #endif
34 #include <sys/ioctl.h>
35 #include <signal.h>
36 #include <setjmp.h>
37 #endif
38
39 #if defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
40 #include <signal.h>
41 #include <unistd.h>
42 #endif
43
44 #ifdef  AFS_HPUX_ENV
45 #include <bsdtty.h>
46 #include <sys/ttold.h>
47 #include <termios.h>
48 static int intrupt;
49 #endif
50
51 #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
52 #include <termios.h>
53 #endif
54
55 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
56 #include <termios.h>
57 #endif
58 #ifdef AFS_NT40_ENV
59 #include <windows.h>
60 #endif
61
62 static int intrupt;
63 #if defined(AFS_SGI_ENV) || defined (AFS_AIX_ENV) /*|| defined (AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)*/
64 #undef  BSDUNIX
65 #endif
66
67 #ifdef  BSDUNIX
68 static jmp_buf env;
69 #endif
70
71 #ifdef BSDUNIX
72 #define POSIX
73 #ifdef POSIX
74 typedef void sigtype;
75 #else
76 typedef int sigtype;
77 #endif
78 static sigtype sig_restore();
79 static push_signals(), pop_signals();
80 #endif
81
82 int des_read_pw_string(char *, int, char *, int);
83 int des_string_to_key(char *, des_cblock *);
84
85 /*** Routines ****************************************************** */
86 int
87 des_read_password(k,prompt,verify)
88     des_cblock *k;
89     char *prompt;
90     int verify;
91 {
92     int ok;
93     char key_string[BUFSIZ];
94
95 #ifdef BSDUNIX
96     if (setjmp(env)) {
97         ok = -1;
98         goto lose;
99     }
100 #endif
101
102     ok = des_read_pw_string(key_string, BUFSIZ, prompt, verify);
103     if (ok == 0)
104         des_string_to_key(key_string, k);
105
106 #ifdef BSDUNIX
107 lose:
108 #endif
109     bzero(key_string, sizeof (key_string));
110     return ok;
111 }
112
113 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
114 static void catch(int);
115 #endif
116
117 #if     !defined(BSDUNIX) && (defined(AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV))
118 #include <termio.h>
119 #endif
120
121 /*
122  * This version just returns the string, doesn't map to key.
123  *
124  * Returns 0 on success, non-zero on failure.
125  */
126 int
127 des_read_pw_string(s,maxa,prompt,verify)
128     char *s;
129     int maxa;
130     char *prompt;
131     int verify;
132 {
133     int ok = 0, cnt1=0;
134     char *ptr;
135 #if defined(AFS_HPUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
136     register int fno;
137     struct sigaction newsig, oldsig;
138     struct termios save_ttyb, ttyb;
139 #endif
140 #if defined(AFS_DARWIN_ENV)
141     FILE *fi;
142 #endif
143 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
144     struct termios ttyb;
145     struct sigaction osa, sa;
146 #endif
147 #ifdef BSDUNIX
148     jmp_buf old_env;
149     unsigned long flags;
150     struct sgttyb tty_state, echo_off_tty_state;
151     FILE *fi;
152 #else
153 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
154     struct termio ttyb;
155     FILE *fi;
156     char savel, flags;
157     void (*sig)();
158     extern void setbuf();
159     extern int kill(), fclose();
160 #endif
161 #endif
162 #ifdef AFS_NT40_ENV
163     HANDLE hConStdin;
164     DWORD oldConMode, newConMode;
165     BOOL resetConMode = FALSE;
166 #endif
167     char key_string[BUFSIZ];
168
169     if (maxa > BUFSIZ) {
170         return -1;
171     }
172
173 #if defined(AFS_HPUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
174     if ((fi = fopen("/dev/tty", "r")) == NULL)
175         return -1;
176     setbuf(fi, (char *)NULL);                   /* We don't want any buffering for our i/o. */
177     /*
178      * Install signal handler for SIGINT so that we can restore
179      * the tty settings after we change them.  The handler merely
180      * increments the variable "intrupt" to tell us that an
181      * interrupt signal was received.
182      */
183     newsig.sa_handler = catch;
184     sigemptyset(&newsig.sa_mask);
185     newsig.sa_flags = 0;
186     sigaction(SIGINT, &newsig, &oldsig);
187     intrupt = 0;
188  
189     /*
190      * Get the terminal characters (save for later restoration) and
191      * reset them so that echo is off
192      */
193     fno = fileno(fi);
194     tcgetattr(fno, &ttyb);
195     save_ttyb = ttyb;
196     ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
197     tcsetattr(fno, TCSAFLUSH, &ttyb);
198 #else
199 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
200     if((fi = fopen("/dev/tty", "r")) == NULL) {
201                 return(-1);
202             }
203     else
204         setbuf(fi, (char*)NULL);
205     sa.sa_handler = catch;
206     sa.sa_mask = 0;
207     sa.sa_flags = SA_INTERRUPT;
208     (void) sigaction(SIGINT, &sa, &osa);
209     intrupt = 0;
210     (void) ioctl(fileno(fi), TCGETS, &ttyb);
211     flags = ttyb.c_lflag;
212     ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
213     (void) ioctl(fileno(fi), TCSETSF, &ttyb);
214 #else
215 #ifdef  BSDUNIX
216     /* XXX assume jmp_buf is typedef'ed to an array */
217     bcopy((char *)old_env, (char *)env, sizeof(env));
218     if (setjmp(env))
219         goto lose;
220     /* save terminal state*/
221     if (ioctl(0,TIOCGETP,(char *)&tty_state) == -1)
222         return -1;
223     push_signals();
224     /* Turn off echo */
225     bcopy (&tty_state, &echo_off_tty_state, sizeof (tty_state));
226     echo_off_tty_state.sg_flags &= ~ECHO;
227     if (ioctl(0,TIOCSETP,(char *)&echo_off_tty_state) == -1)
228         return -1;
229 #else
230 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
231         if((fi = fopen("/dev/tty", "r+")) == NULL)
232                 return(-1);
233         else
234                 setbuf(fi, (char*)NULL);
235         sig = signal(SIGINT, catch);
236         intrupt = 0;
237         (void) ioctl(fileno(fi), TCGETA, &ttyb);
238         savel = ttyb.c_line;
239         ttyb.c_line = 0;
240         flags = ttyb.c_lflag;
241         ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
242         (void) ioctl(fileno(fi), TCSETAF, &ttyb);
243 #else
244 #ifdef AFS_NT40_ENV
245     /* turn off console input echoing */
246     if ((hConStdin = GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE) {
247         if (GetConsoleMode(hConStdin, &oldConMode)) {
248             newConMode = (oldConMode & ~(ENABLE_ECHO_INPUT));
249             if (SetConsoleMode(hConStdin, newConMode)) {
250                 resetConMode = TRUE;
251             }
252         }
253     }
254 #endif
255 #endif
256 #endif
257 #endif
258 #endif
259     while (!ok) {
260         (void) printf(prompt);
261         (void) fflush(stdout);
262 #ifdef  CROSSMSDOS
263         h19line(s,sizeof(s),0);
264         if (!strlen(s))
265             continue;
266 #else
267         if (!fgets(s, maxa, stdin)) {
268             clearerr(stdin);
269             printf("\n");
270             if (cnt1++ > 1) {
271                 /*
272                  * Otherwise hitting ctrl-d will always leave us inside this loop forever!
273                  */
274                 break;
275             }
276             continue;
277         }
278         if ((ptr = index(s, '\n')))
279             *ptr = '\0';
280 #endif
281         if (verify) {
282             printf("\nVerifying, please re-enter %s",prompt);
283             (void) fflush(stdout);
284 #ifdef CROSSMSDOS
285             h19line(key_string,sizeof(key_string),0);
286             if (!strlen(key_string))
287                 continue;
288 #else
289             if (!fgets(key_string, sizeof(key_string), stdin)) {
290                 clearerr(stdin);
291                 continue;
292             }
293             if ((ptr = index(key_string, '\n')))
294             *ptr = '\0';
295 #endif
296             if (strcmp(s,key_string)) {
297                 printf("\n\07\07Mismatch - try again\n");
298                 (void) fflush(stdout);
299                 continue;
300             }
301         }
302         ok = 1;
303     }
304
305 #ifdef BSDUNIX
306 lose:
307 #endif
308     if (!ok)
309         bzero(s, maxa);
310     printf("\n");
311 #ifdef  AFS_HPUX_ENV
312     /*
313      * Restore the terminal to its previous characteristics.
314      * Restore the old signal handler for SIGINT.
315      */
316     tcsetattr(fno, TCSANOW, &save_ttyb);
317     sigaction(SIGINT, &oldsig, (struct sigaction *)0);
318     if (fi != stdin)
319         fclose(fi);
320  
321     /*
322      * If we got a SIGINT while we were doing things, send the SIGINT
323      * to ourselves so that the calling program receives it (since we
324      * were intercepting it for a period of time.)
325      */
326     if (intrupt)
327         kill(getpid(), SIGINT);
328 #else
329 #if     defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
330     ttyb.c_lflag = flags;
331     (void) ioctl(fileno(fi), TCSETSW, &ttyb);
332     (void) sigaction(SIGINT, &osa, (struct sigaction *)NULL);
333     if(fi != stdin)
334         (void) fclose(fi);
335 #else
336 #ifdef  BSDUNIX
337     if (ioctl(0,TIOCSETP,(char *)&tty_state))
338         ok = 0;
339     pop_signals();
340     bcopy((char *)env, (char *)old_env, sizeof(env));
341 #else
342 #if     defined (AFS_AIX_ENV) /*|| defined (AFS_HPUX_ENV)*/ || defined(AFS_SGI_ENV) || defined(AFS_LINUX20_ENV)
343     ttyb.c_lflag = flags;
344     ttyb.c_line = savel;
345     (void) ioctl(fileno(fi), TCSETAW, &ttyb);
346     (void) signal(SIGINT, sig);
347     if(fi != stdin)
348         (void) fclose(fi);
349     if(intrupt)
350         (void) kill(getpid(), SIGINT);
351 #else
352 #ifdef AFS_NT40_ENV
353     /* restore console to original mode settings */
354     if (resetConMode) {
355         (void)SetConsoleMode(hConStdin, oldConMode);
356     }
357 #endif
358 #endif
359 #endif
360 #endif
361 #endif
362     if (verify)
363         bzero(key_string, sizeof (key_string));
364     s[maxa-1] = 0;              /* force termination */
365     return !ok;                 /* return nonzero if not okay */
366 }
367
368 #ifdef  BSDUNIX
369 /*
370  * this can be static since we should never have more than
371  * one set saved....
372  */
373 #ifdef mips
374 void static (*old_sigfunc[NSIG])();
375 #else
376 static sigtype (*old_sigfunc[NSIG])();
377 #endif
378
379 static push_signals()
380 {
381     register i;
382     for (i = 0; i < NSIG; i++)
383         old_sigfunc[i] = signal(i,sig_restore);
384 }
385
386 static pop_signals()
387 {
388     register i;
389     for (i = 0; i < NSIG; i++)
390         (void) signal(i,old_sigfunc[i]);
391 }
392
393 static sigtype
394 sig_restore()
395 {
396     longjmp(env,1);
397 }
398 #endif
399
400
401 #if     defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV) || defined(AFS_SGI_ENV) || defined(AFS_SUN_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
402 static void
403 catch(int junk)
404 {
405         ++intrupt;
406 }
407 #endif