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