include-afsconfig-before-param-h-20010712
[openafs.git] / src / kauth / read_passwd.c
1 /*
2  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
3  * of Technology.
4  *
5  * For copying and distribution information, please see the file
6  * <mit-copyright.h>.
7  *
8  * This routine prints the supplied string to standard
9  * output as a prompt, and reads a password string without
10  * echoing.
11  */
12
13 #include <afsconfig.h>
14 #include <afs/param.h>
15
16 RCSID("$Header$");
17
18 #include <mit-cpyright.h>
19 #include <des.h>
20
21 #include <stdio.h>
22 #ifdef  BSDUNIX
23 #include <strings.h>
24 #include <sys/ioctl.h>
25 #include <signal.h>
26 #include <setjmp.h>
27 #else
28 char     *strcpy();
29 int      strcmp();
30 #endif
31 #if defined(AFS_AIX_ENV)
32 #include <signal.h>
33 #endif
34 #if defined(AFS_SGI_ENV)
35 #include <strings.h>
36 #include <signal.h>
37 #endif
38
39 #if     defined (AFS_AIX_ENV) || defined(AFS_SGI_ENV)
40 /* Just temp till we figure out the aix stuff */
41 #undef  BSDUNIX
42 static int intrupt;
43 #endif
44
45 #ifdef  BSDUNIX
46 static jmp_buf env;
47 #endif
48
49 #ifdef BSDUNIX
50 static void sig_restore();
51 static push_signals(), pop_signals();
52 int read_pw_string();
53 #endif
54
55 /*** Routines ****************************************************** */
56 int
57 des_read_password(k,prompt,verify)
58     C_Block *k;
59     char *prompt;
60     int verify;
61 {
62     int ok;
63     char key_string[BUFSIZ];
64
65 #ifdef BSDUNIX
66     if (setjmp(env)) {
67         ok = -1;
68         goto lose;
69     }
70 #endif
71
72     ok = read_pw_string(key_string, BUFSIZ, prompt, verify);
73     if (ok == 0)
74         string_to_key(key_string, k);
75
76 lose:
77     bzero(key_string, sizeof (key_string));
78     return ok;
79 }
80
81 /* good_gets is like gets except that it take a max string length and won't
82    write past the end of its input buffer.  It returns a variety of negative
83    numbers in case of errors and zero if there was no characters read (a blank
84    line for instance).  Otherwise it returns the length of the string read in.
85    */
86
87 static int good_gets (s, max)
88   char *s;
89   int   max;
90 {   int l;                              /* length of string read */
91     if (!fgets (s, max, stdin)) {
92         if (feof(stdin)) return EOF;    /* EOF on input, nothing read */
93         else return -2;                 /* I don't think this can happen */
94     }
95     l = strlen (s);
96     if (l && (s[l-1] == '\n')) s[--l] = 0;
97     return l;
98 }
99
100 /*
101  * This version just returns the string, doesn't map to key.
102  *
103  * Returns 0 on success, non-zero on failure.
104  */
105
106 #if     !defined(BSDUNIX) && (defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV))
107 #include <termio.h>
108 #endif
109
110 int
111 read_pw_string(s,max,prompt,verify)
112     char *s;
113     int max;
114     char *prompt;
115     int verify;
116 {
117     int ok = 0;
118     int len;                            /* password length */
119
120 #ifdef  BSDUNIX
121     jmp_buf old_env;
122     struct sgttyb tty_state;
123 #else
124 #if     defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
125     struct termio ttyb;
126     FILE *fi;
127     char savel, flags;
128     int (*sig)(), catch();
129     extern void setbuf();
130     extern int kill(), fclose();
131 #endif
132 #endif
133     char key_string[BUFSIZ];
134
135     if (max > BUFSIZ) {
136         return -1;
137     }
138
139 #ifdef  BSDUNIX
140     bcopy(env, old_env, sizeof(env));
141     if (setjmp(env))
142         goto lose;
143
144     /* save terminal state*/
145     if (ioctl(0,TIOCGETP,&tty_state) == -1)
146         return -1;
147
148     push_signals();
149     /* Turn off echo */
150     tty_state.sg_flags &= ~ECHO;
151     if (ioctl(0,TIOCSETP,&tty_state) == -1) {
152         pop_signals();
153         return -1;
154     }
155 #else
156 #if     defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
157         if((fi = fopen("/dev/tty", "r+")) == NULL)
158                 return(-1);
159         else
160                 setbuf(fi, (char*)NULL);
161         sig = signal(SIGINT, catch);
162         intrupt = 0;
163         (void) ioctl(fileno(fi), TCGETA, &ttyb);
164         savel = ttyb.c_line;
165         ttyb.c_line = 0;
166         flags = ttyb.c_lflag;
167         ttyb.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
168         (void) ioctl(fileno(fi), TCSETAF, &ttyb);
169 #endif
170 #endif
171
172     while (!ok) {
173         printf(prompt);
174         fflush(stdout);
175 #ifdef  CROSSMSDOS
176         h19line(s,sizeof(s),0);
177         if (!strlen(s))
178             continue;
179 #else
180         if (good_gets(s, max) <= 0) {
181             if (feof (stdin)) break;    /* just give up */
182             else continue;              /* try again: blank line */
183         }
184 #endif
185         if (verify) {
186             printf("\nVerifying, please re-enter %s",prompt);
187             fflush(stdout);
188 #ifdef CROSSMSDOS
189             h19line(key_string,sizeof(key_string),0);
190             if (!strlen(key_string))
191                 continue;
192 #else
193             if (good_gets(key_string, sizeof(key_string)) <= 0)
194                 continue;
195 #endif
196             if (strcmp(s,key_string)) {
197                 printf("\n\07\07Mismatch - try again\n");
198                 fflush(stdout);
199                 continue;
200             }
201         }
202         ok = 1;
203     }
204
205 lose:
206     if (!ok)
207         bzero(s, max);
208 #ifdef  BSDUNIX
209     /* turn echo back on */
210     tty_state.sg_flags |= ECHO;
211     if (ioctl(0,TIOCSETP,&tty_state))
212         ok = 0;
213     pop_signals();
214     bcopy(old_env, env, sizeof(env));
215 #else
216 #if     defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
217     ttyb.c_lflag = flags;
218     ttyb.c_line = savel;
219     (void) ioctl(fileno(fi), TCSETAW, &ttyb);
220     (void) signal(SIGINT, sig);
221     if(fi != stdin)
222         (void) fclose(fi);
223     if(intrupt)
224         (void) kill(getpid(), SIGINT);
225 #endif
226 #endif
227     if (verify)
228         bzero(key_string, sizeof (key_string));
229     s[max-1] = 0;               /* force termination */
230     return !ok;                 /* return nonzero if not okay */
231 }
232
233 #ifdef  BSDUNIX
234 /*
235  * this can be static since we should never have more than
236  * one set saved....
237  */
238 static int (*old_sigfunc[NSIG])();
239
240 static push_signals()
241 {
242     register i;
243     for (i = 0; i < NSIG; i++)
244         old_sigfunc[i] = signal(i,sig_restore);
245 }
246
247 static pop_signals()
248 {
249     register i;
250     for (i = 0; i < NSIG; i++)
251         signal(i,old_sigfunc[i]);
252 }
253
254 static void sig_restore(sig,code,scp)
255     int sig,code;
256     struct sigcontext *scp;
257 {
258     longjmp(env,1);
259 }
260 #endif
261
262 #if     defined(AFS_AIX_ENV) || defined(AFS_SGI_ENV)
263 static int
264 catch()
265 {
266         ++intrupt;
267 }
268 #endif