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 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 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 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 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 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 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