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. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 *
26 *
27 * libos: krb5_read_password for BSD 4.3
28 */
29
30 #include "k5-int.h"
31
32 #if !defined(_WIN32)
33 #define DEFINED_KRB5_READ_PASSWORD
34 #include <stdio.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <setjmp.h>
38
39 #ifndef ECHO_PASSWORD
40 #include <termios.h>
41 #endif /* ECHO_PASSWORD */
42
43 krb5_error_code
krb5_read_password(krb5_context context,const char * prompt,const char * prompt2,char * return_pwd,unsigned int * size_return)44 krb5_read_password(krb5_context context, const char *prompt, const char *prompt2, char *return_pwd, unsigned int *size_return)
45 {
46 krb5_data reply_data;
47 krb5_prompt k5prompt;
48 krb5_error_code retval;
49 reply_data.length = *size_return; /* NB: size_return is also an input */
50 reply_data.data = return_pwd;
51 k5prompt.prompt = (char *)prompt;
52 k5prompt.hidden = 1;
53 k5prompt.reply = &reply_data;
54 retval = krb5_prompter_posix(NULL,
55 NULL, NULL, NULL, 1, &k5prompt);
56
57 if ((retval==0) && prompt2) {
58 krb5_data verify_data;
59 verify_data.data = malloc(*size_return);
60 verify_data.length = *size_return;
61 k5prompt.prompt = (char *)prompt2;
62 k5prompt.reply = &verify_data;
63 if (!verify_data.data)
64 return ENOMEM;
65 retval = krb5_prompter_posix(NULL,
66 NULL,NULL, NULL, 1, &k5prompt);
67 if (retval == 0) {
68 /* compare */
69 if (strncmp(return_pwd, (char *)verify_data.data, *size_return))
70 retval = KRB5_LIBOS_BADPWDMATCH;
71 }
72 free(verify_data.data);
73 }
74 if (!retval)
75 *size_return = k5prompt.reply->length;
76 else
77 memset(return_pwd, 0, *size_return);
78 return retval;
79 }
80 #endif
81
82 #if defined(_WIN32)
83 #define DEFINED_KRB5_READ_PASSWORD
84
85 #include <io.h>
86
87 typedef struct {
88 char *pwd_prompt;
89 char *pwd_prompt2;
90 char *pwd_return_pwd;
91 int *pwd_size_return;
92 } pwd_params;
93
center_dialog(HWND hwnd)94 void center_dialog(HWND hwnd)
95 {
96 int scrwidth, scrheight;
97 int dlgwidth, dlgheight;
98 RECT r;
99 HDC hdc;
100
101 if (hwnd == NULL)
102 return;
103
104 GetWindowRect(hwnd, &r);
105 dlgwidth = r.right - r.left;
106 dlgheight = r.bottom - r.top ;
107 hdc = GetDC(NULL);
108 scrwidth = GetDeviceCaps(hdc, HORZRES);
109 scrheight = GetDeviceCaps(hdc, VERTRES);
110 ReleaseDC(NULL, hdc);
111 r.left = (scrwidth - dlgwidth) / 2;
112 r.top = (scrheight - dlgheight) / 2;
113 MoveWindow(hwnd, r.left, r.top, dlgwidth, dlgheight, TRUE);
114 }
115
116 #ifdef _WIN32
117 static krb5_error_code
read_console_password(krb5_context context,const char * prompt,const char * prompt2,char * password,int * pwsize)118 read_console_password(
119 krb5_context context,
120 const char * prompt,
121 const char * prompt2,
122 char * password,
123 int * pwsize)
124 {
125 HANDLE handle;
126 DWORD old_mode, new_mode;
127 char *tmpstr = 0;
128 char *ptr;
129 int scratchchar;
130 krb5_error_code errcode = 0;
131
132 handle = GetStdHandle(STD_INPUT_HANDLE);
133 if (handle == INVALID_HANDLE_VALUE)
134 return ENOTTY;
135 if (!GetConsoleMode(handle, &old_mode))
136 return ENOTTY;
137
138 new_mode = old_mode;
139 new_mode |= ( ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT );
140 new_mode &= ~( ENABLE_ECHO_INPUT );
141
142 if (!SetConsoleMode(handle, new_mode))
143 return ENOTTY;
144
145 (void) fputs(prompt, stdout);
146 (void) fflush(stdout);
147 (void) memset(password, 0, *pwsize);
148
149 if (fgets(password, *pwsize, stdin) == NULL) {
150 (void) putchar('\n');
151 errcode = KRB5_LIBOS_CANTREADPWD;
152 goto cleanup;
153 }
154 (void) putchar('\n');
155
156 if ((ptr = strchr(password, '\n')))
157 *ptr = '\0';
158 else /* need to flush */
159 do {
160 scratchchar = getchar();
161 } while (scratchchar != EOF && scratchchar != '\n');
162
163 if (prompt2) {
164 if (! (tmpstr = (char *)malloc(*pwsize))) {
165 errcode = ENOMEM;
166 goto cleanup;
167 }
168 (void) fputs(prompt2, stdout);
169 (void) fflush(stdout);
170 if (fgets(tmpstr, *pwsize, stdin) == NULL) {
171 (void) putchar('\n');
172 errcode = KRB5_LIBOS_CANTREADPWD;
173 goto cleanup;
174 }
175 (void) putchar('\n');
176
177 if ((ptr = strchr(tmpstr, '\n')))
178 *ptr = '\0';
179 else /* need to flush */
180 do {
181 scratchchar = getchar();
182 } while (scratchchar != EOF && scratchchar != '\n');
183
184 if (strncmp(password, tmpstr, *pwsize)) {
185 errcode = KRB5_LIBOS_BADPWDMATCH;
186 goto cleanup;
187 }
188 }
189
190 cleanup:
191 (void) SetConsoleMode(handle, old_mode);
192 if (tmpstr) {
193 (void) memset(tmpstr, 0, *pwsize);
194 (void) free(tmpstr);
195 }
196 if (errcode)
197 (void) memset(password, 0, *pwsize);
198 else
199 *pwsize = strlen(password);
200 return errcode;
201 }
202 #endif
203
204 static int CALLBACK
read_pwd_proc(HWND hdlg,UINT msg,WPARAM wParam,LPARAM lParam)205 read_pwd_proc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
206 {
207 pwd_params *dp;
208
209 switch(msg) {
210 case WM_INITDIALOG:
211 dp = (pwd_params *) lParam;
212 SetWindowLongPtr(hdlg, DWLP_USER, lParam);
213 SetDlgItemText(hdlg, ID_READ_PWD_PROMPT, dp->pwd_prompt);
214 SetDlgItemText(hdlg, ID_READ_PWD_PROMPT2, dp->pwd_prompt2);
215 SetDlgItemText(hdlg, ID_READ_PWD_PWD, "");
216 center_dialog(hdlg);
217 return TRUE;
218
219 case WM_COMMAND:
220 dp = (pwd_params *) GetWindowLongPtr(hdlg, DWLP_USER);
221 switch (wParam) {
222 case IDOK:
223 *(dp->pwd_size_return) =
224 GetDlgItemText(hdlg, ID_READ_PWD_PWD,
225 dp->pwd_return_pwd, *(dp->pwd_size_return));
226 EndDialog(hdlg, TRUE);
227 break;
228
229 case IDCANCEL:
230 memset(dp->pwd_return_pwd, 0 , *(dp->pwd_size_return));
231 *(dp->pwd_size_return) = 0;
232 EndDialog(hdlg, FALSE);
233 break;
234 }
235 return TRUE;
236
237 default:
238 return FALSE;
239 }
240 }
241
242 krb5_error_code KRB5_CALLCONV
krb5_read_password(context,prompt,prompt2,return_pwd,size_return)243 krb5_read_password(context, prompt, prompt2, return_pwd, size_return)
244 krb5_context context;
245 const char *prompt;
246 const char *prompt2;
247 char *return_pwd;
248 int *size_return;
249 {
250 DLGPROC dlgproc;
251 HINSTANCE hinst;
252 pwd_params dps;
253 int rc;
254
255 #ifdef _WIN32
256 if (_isatty(_fileno(stdin)))
257 return(read_console_password
258 (context, prompt, prompt2, return_pwd, size_return));
259 #endif
260
261 dps.pwd_prompt = prompt;
262 dps.pwd_prompt2 = prompt2;
263 dps.pwd_return_pwd = return_pwd;
264 dps.pwd_size_return = size_return;
265
266 hinst = get_lib_instance();
267 #ifdef _WIN32
268 dlgproc = read_pwd_proc;
269 #else
270 dlgproc = (FARPROC) MakeProcInstance(read_pwd_proc, hinst);
271 #endif
272 rc = DialogBoxParam(hinst, MAKEINTRESOURCE(ID_READ_PWD_DIALOG), 0,
273 dlgproc, (LPARAM) &dps);
274 #ifndef _WIN32
275 FreeProcInstance ((FARPROC) dlgproc);
276 #endif
277 return 0;
278 }
279 #endif
280
281 #ifndef DEFINED_KRB5_READ_PASSWORD
282 #define DEFINED_KRB5_READ_PASSWORD
283 /*
284 * Don't expect to be called, just define it for sanity and the linker.
285 */
286 krb5_error_code KRB5_CALLCONV
krb5_read_password(context,prompt,prompt2,return_pwd,size_return)287 krb5_read_password(context, prompt, prompt2, return_pwd, size_return)
288 krb5_context context;
289 const char *prompt;
290 const char *prompt2;
291 char *return_pwd;
292 int *size_return;
293 {
294 *size_return = 0;
295 return KRB5_LIBOS_CANTREADPWD;
296 }
297 #endif
298