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