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