0c05359d35af69740063943d927d07dd0a645c69
[krb5.git] / src / lib / krb5 / os / read_pwd.c
1 /*
2  * lib/krb5/os/read_pwd.c
3  *
4  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  * 
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  M.I.T. makes no representations about the suitability of
20  * this software for any purpose.  It is provided "as is" without express
21  * or implied warranty.
22  * 
23  *
24  * libos: krb5_read_password for BSD 4.3
25  */
26
27 #include "k5-int.h"
28 #ifndef _MSDOS
29 #include <stdio.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include <setjmp.h>
33
34 #ifdef sun
35 #include <sgtty.h>
36 #endif
37
38 extern int errno;
39
40 #ifdef ECHO_PASSWORD
41 #define cleanup(errcode) (void) signal(SIGINT, ointrfunc); return errcode;
42 #else
43
44 /* POSIX_* are auto-magically defined in <krb5/config.h> at source
45    configuration time. */
46
47 #ifdef POSIX_TERMIOS
48 #include <termios.h>
49 #else
50 #include <sys/ioctl.h>
51 #endif /* POSIX_TERMIOS */
52
53 #ifdef POSIX_TERMIOS
54 #define cleanup(errcode) (void) signal(SIGINT, ointrfunc); tcsetattr(fd, TCSANOW, &save_control); return errcode;
55 #else
56 #ifdef sun
57 #define cleanup(errcode) (void) signal(SIGINT, ointrfunc); stty(fd, (char *)&tty_savestate); return errcode;
58 #else /* !sun */
59 #define cleanup(errcode) (void) signal(SIGINT, ointrfunc); ioctl(fd, TIOCSETP, (char *)&tty_savestate); return errcode;
60 #endif /* sun */
61 #endif /* POSIX_TERMIOS */
62
63 #endif /* ECHO_PASSWORD */
64
65 static jmp_buf pwd_jump;
66
67
68 static krb5_sigtype
69 intr_routine()
70 {
71     longjmp(pwd_jump, 1);
72     /*NOTREACHED*/
73 }
74
75 krb5_error_code
76 krb5_read_password(context, prompt, prompt2, return_pwd, size_return)
77     krb5_context context;
78     char *prompt;
79     char *prompt2;
80     char *return_pwd;
81     int *size_return;
82 {
83     /* adapted from Kerberos v4 des/read_password.c */
84 #if defined(__STDC__) || defined(mips)
85     /* readin_string is used after a longjmp, so must be volatile */
86     volatile
87 #endif
88       char *readin_string = 0;
89     register char *ptr;
90     int scratchchar;
91     krb5_sigtype (*ointrfunc)();
92 #ifndef ECHO_PASSWORD
93 #ifdef POSIX_TERMIOS
94     struct termios echo_control, save_control;
95     int fd;
96
97     /* get the file descriptor associated with stdin */
98     fd=fileno(stdin);
99
100 #ifdef notdef
101     /* don't want to read password from anything but a terminal */
102     if (!isatty(fd)) {
103         fprintf(stderr,"Can only read password from a tty\n"); /* XXX */
104         errno=ENOTTY; /* say innapropriate ioctl for device */
105         return errno;
106     }
107 #endif /* notdef */
108
109     if (tcgetattr(fd, &echo_control) == -1)
110         return errno;
111
112     save_control = echo_control;
113     echo_control.c_lflag &= ~(ECHO|ECHONL);
114     
115     if (tcsetattr(fd, TCSANOW, &echo_control) == -1)
116         return errno;
117 #else
118     /* 4.3BSD style */
119     struct sgttyb tty_state, tty_savestate;
120     int fd;
121
122     /* get the file descriptor associated with stdin */
123     fd=fileno(stdin);
124
125 #ifdef notdef
126     /* don't want to read password from anything but a terminal */
127     if (!isatty(fd)) {
128         fprintf(stderr,"Can only read password from a tty\n"); /* XXX */
129         errno=ENOTTY; /* say innapropriate ioctl for device */
130         return errno;
131     }
132 #endif /* notdef */
133
134     /* save terminal state */
135     if (
136 #ifdef sun
137         gtty(fd,(char *)&tty_savestate)
138 #else
139         ioctl(fd,TIOCGETP,(char *)&tty_savestate)
140 #endif
141         == -1) 
142         return errno;
143
144     tty_state = tty_savestate;
145
146     tty_state.sg_flags &= ~ECHO;
147     if (
148 #ifdef sun
149         stty(fd,(char *)&tty_state)
150 #else
151         ioctl(fd,TIOCSETP,(char *)&tty_state)
152 #endif
153         == -1)
154         return errno;
155 #endif
156
157 #endif /* ECHO_PASSWORD */
158
159     if (setjmp(pwd_jump)) {
160         /* interrupted */
161         if (readin_string) {
162             (void) memset((char *)readin_string, 0, *size_return);
163             krb5_xfree(readin_string);
164         }
165         (void) memset(return_pwd, 0, *size_return);
166         cleanup(KRB5_LIBOS_PWDINTR);
167     }
168     /* save intrfunc */
169     ointrfunc = signal(SIGINT, intr_routine);
170
171     /* put out the prompt */
172     (void) fputs(prompt,stdout);
173     (void) fflush(stdout);
174     (void) memset(return_pwd, 0, *size_return);
175
176     if (fgets(return_pwd, *size_return, stdin) == NULL) {
177         /* error */
178         (void) putchar('\n');
179         (void) memset(return_pwd, 0, *size_return);
180         cleanup(KRB5_LIBOS_CANTREADPWD);
181     }
182     (void) putchar('\n');
183     /* fgets always null-terminates the returned string */
184
185     /* replace newline with null */
186     if (ptr = strchr(return_pwd, '\n'))
187         *ptr = '\0';
188     else /* flush rest of input line */
189         do {
190             scratchchar = getchar();
191         } while (scratchchar != EOF && scratchchar != '\n');
192
193     if (prompt2) {
194         /* put out the prompt */
195         (void) fputs(prompt2,stdout);
196         (void) fflush(stdout);
197         readin_string = malloc(*size_return);
198         if (!readin_string) {
199             (void) memset(return_pwd, 0, *size_return);
200             cleanup(ENOMEM);
201         }
202         (void) memset((char *)readin_string, 0, *size_return);
203         if (fgets((char *)readin_string, *size_return, stdin) == NULL) {
204             /* error */
205             (void) putchar('\n');
206             (void) memset((char *)readin_string, 0, *size_return);
207             (void) memset(return_pwd, 0, *size_return);
208             krb5_xfree(readin_string);
209             cleanup(KRB5_LIBOS_CANTREADPWD);
210         }
211         (void) putchar('\n');
212
213         if (ptr = strchr((char *)readin_string, '\n'))
214             *ptr = '\0';
215         else /* need to flush */
216             do {
217                 scratchchar = getchar();
218             } while (scratchchar != EOF && scratchchar != '\n');
219             
220         /* compare */
221         if (strncmp(return_pwd, (char *)readin_string, *size_return)) {
222             (void) memset((char *)readin_string, 0, *size_return);
223             (void) memset(return_pwd, 0, *size_return);
224             krb5_xfree(readin_string);
225             cleanup(KRB5_LIBOS_BADPWDMATCH);
226         }
227         (void) memset((char *)readin_string, 0, *size_return);
228         krb5_xfree(readin_string);
229     }
230     
231     /* reset intrfunc */
232     (void) signal(SIGINT, ointrfunc);
233
234 #ifndef ECHO_PASSWORD
235 #ifdef POSIX_TERMIOS
236     if (tcsetattr(fd, TCSANOW, &save_control) == -1)
237         return errno;
238 #else
239     if (
240 #ifdef sun
241         stty(fd, (char *)&tty_savestate)
242 #else
243         ioctl(fd, TIOCSETP, (char *)&tty_savestate)
244 #endif
245         == -1)
246         return errno;
247 #endif
248 #endif /* ECHO_PASSWORD */
249     *size_return = strlen(return_pwd);
250
251     return 0;
252 }
253 #else /* MSDOS */
254 /* Don't expect to be called, just define it for sanity and the linker.
255 */
256
257 krb5_error_code INTERFACE
258 krb5_read_password(context, prompt, prompt2, return_pwd, size_return)
259     krb5_context context;
260     char *prompt;
261     char *prompt2;
262     char *return_pwd;
263     int *size_return;
264 {
265    *size_return = 0;
266    return 0;
267 }
268 #endif   /* !MSDOS */