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