xref: /freebsd/crypto/krb5/src/lib/krb5/os/read_pwd.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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