#include "k5-int.h" #if (!defined(_WIN32) || (defined(_WIN32) && defined(__CYGWIN32__))) && !defined(macintosh) #include #include #include #include #ifdef __vxworks #define ECHO_PASSWORD #endif #ifndef ECHO_PASSWORD #include #endif /* ECHO_PASSWORD */ static jmp_buf pwd_jump; static krb5_sigtype intr_routine(int signo) { longjmp(pwd_jump, 1); /*NOTREACHED*/ } krb5_error_code KRB5_CALLCONV krb5_prompter_posix(krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts[]) { /* adapted from Kerberos v5 krb5_read_password() */ register char *ptr; int scratchchar; krb5_sigtype (*volatile ointrfunc)(); volatile krb5_error_code errcode; volatile int i = 0; #ifndef ECHO_PASSWORD struct termios echo_control, save_control; volatile int fd; #endif if (name) { fputs(name, stdout); fputs("\n", stdout); } if (banner) { fputs(banner, stdout); fputs("\n", stdout); } if (setjmp(pwd_jump)) { errcode = KRB5_LIBOS_PWDINTR; /* we were interrupted... */ goto cleanup; } /* save intrfunc */ ointrfunc = signal(SIGINT, intr_routine); for (i=0; idata, 0, prompts[i].reply->length); if (fgets(prompts[i].reply->data, (int) prompts[i].reply->length, stdin) == NULL) { if (prompts[i].hidden) (void) putchar('\n'); errcode = KRB5_LIBOS_CANTREADPWD; goto cleanup; } if (prompts[i].hidden) (void) putchar('\n'); /* fgets always null-terminates the returned string */ /* replace newline with null */ if ((ptr = strchr(prompts[i].reply->data, '\n'))) *ptr = '\0'; else /* flush rest of input line */ do { scratchchar = getchar(); } while (scratchchar != EOF && scratchchar != '\n'); prompts[i].reply->length = strlen(prompts[i].reply->data); #ifndef ECHO_PASSWORD if (prompts[i].hidden && (isatty(fd) == 1)) if ((tcsetattr(fd, TCSANOW, &save_control) == -1) && (errcode == 0)) return errno; #endif } errcode = 0; cleanup: (void) signal(SIGINT, ointrfunc); #ifndef ECHO_PASSWORD if (i < num_prompts) { if (prompts[i].hidden) { (void)putchar('\n'); if (isatty(fd) == 1) { if ((tcsetattr(fd, TCSANOW, &save_control) == -1 && errcode == 0)) return errno; } } } #endif return(errcode); } #else /* non-Cygwin Windows, or Mac */ #if defined(_WIN32) #include krb5_error_code KRB5_CALLCONV krb5_prompter_posix(krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts[]) { HANDLE handle; DWORD old_mode, new_mode; char *ptr; int scratchchar; krb5_error_code errcode = 0; int i; handle = GetStdHandle(STD_INPUT_HANDLE); if (handle == INVALID_HANDLE_VALUE) return ENOTTY; if (!GetConsoleMode(handle, &old_mode)) return ENOTTY; new_mode = old_mode; new_mode |= ( ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT ); new_mode &= ~( ENABLE_ECHO_INPUT ); if (!SetConsoleMode(handle, new_mode)) return ENOTTY; if (!SetConsoleMode(handle, old_mode)) return ENOTTY; if (name) { fputs(name, stdout); fputs("\n", stdout); } if (banner) { fputs(banner, stdout); fputs("\n", stdout); } for (i = 0; i < num_prompts; i++) { if (prompts[i].hidden) { if (!SetConsoleMode(handle, new_mode)) { errcode = ENOTTY; goto cleanup; } } fputs(prompts[i].prompt,stdout); fputs(": ", stdout); fflush(stdout); memset(prompts[i].reply->data, 0, prompts[i].reply->length); if (fgets(prompts[i].reply->data, prompts[i].reply->length, stdin) == NULL) { if (prompts[i].hidden) putchar('\n'); errcode = KRB5_LIBOS_CANTREADPWD; goto cleanup; } if (prompts[i].hidden) putchar('\n'); /* fgets always null-terminates the returned string */ /* replace newline with null */ if ((ptr = strchr(prompts[i].reply->data, '\n'))) *ptr = '\0'; else /* flush rest of input line */ do { scratchchar = getchar(); } while (scratchchar != EOF && scratchchar != '\n'); prompts[i].reply->length = strlen(prompts[i].reply->data); if (!SetConsoleMode(handle, old_mode)) { errcode = ENOTTY; goto cleanup; } } cleanup: if (errcode) { for (i = 0; i < num_prompts; i++) { memset(prompts[i].reply->data, 0, prompts[i].reply->length); } } return errcode; } #else /* !_WIN32 */ krb5_error_code KRB5_CALLCONV krb5_prompter_posix(krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts[]) { return(EINVAL); } #endif /* !_WIN32 */ #endif /* Windows or Mac */ void krb5int_set_prompt_types(krb5_context context, krb5_prompt_type *types) { context->prompt_types = types; } krb5_prompt_type* KRB5_CALLCONV krb5_get_prompt_types(krb5_context context) { return context->prompt_types; }