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