xref: /freebsd/contrib/libfido2/openbsd-compat/readpassphrase_win32.c (revision 0afa8e065e14bb8fd338d75690e0238c00167d40)
1 /*
2 * Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
3 *
4 * Author: Bryan Berns <berns@uwalumni.com>
5 *   Modified group detection use s4u token information
6 *
7 * Copyright(c) 2016 Microsoft Corp.
8 * All rights reserved
9 *
10 * Misc Unix POSIX routine implementations for Windows
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met :
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and / or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 #define UMDF_USING_NTSTATUS
35 #define SECURITY_WIN32
36 #include <windows.h>
37 #include <stdio.h>
38 #include <time.h>
39 #include <shlwapi.h>
40 #include <conio.h>
41 #include <lm.h>
42 #include <sddl.h>
43 #include <aclapi.h>
44 #include <ntsecapi.h>
45 #include <security.h>
46 #include <ntstatus.h>
47 #include <wchar.h>
48 
49 #include "openbsd-compat.h"
50 
51 #ifndef HAVE_READPASSPHRASE
52 
53 /*on error returns NULL and sets errno*/
54 static wchar_t *
utf8_to_utf16(const char * utf8)55 utf8_to_utf16(const char *utf8)
56 {
57 	int needed = 0;
58 	wchar_t* utf16 = NULL;
59 	if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
60 	    (utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
61 	    MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0) {
62 		/* debug3("failed to convert utf8 payload:%s error:%d", utf8, GetLastError()); */
63 		errno = ENOMEM;
64 		return NULL;
65 	}
66 
67 	return utf16;
68 }
69 
70 char *
readpassphrase(const char * prompt,char * outBuf,size_t outBufLen,int flags)71 readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
72 {
73 	size_t current_index = 0;
74 	char ch;
75 	wchar_t* wtmp = NULL;
76 
77 	if (outBufLen == 0) {
78 		errno = EINVAL;
79 		return NULL;
80 	}
81 
82 	while (_kbhit()) (void)_getch();
83 
84 	wtmp = utf8_to_utf16(prompt);
85 	if (wtmp == NULL)
86 		errx(1, "unable to alloc memory");
87 
88 	_cputws(wtmp);
89 	free(wtmp);
90 
91 	while (current_index < outBufLen - 1) {
92 		ch = (char)_getch();
93 
94 		if (ch == '\r') {
95 			if (_kbhit()) (void)_getch(); /* read linefeed if its there */
96 			break;
97 		} else if (ch == '\n') {
98 			break;
99 		} else if (ch == '\b') { /* backspace */
100 			if (current_index > 0) {
101 				if (flags & RPP_ECHO_ON)
102 					printf_s("%c \b", ch);
103 
104 				current_index--; /* overwrite last character */
105 			}
106 		} else if (ch == '\003') { /* exit on Ctrl+C */
107 			errx(1, "");
108 		} else {
109 			if (flags & RPP_SEVENBIT)
110 				ch &= 0x7f;
111 
112 			if (isalpha((unsigned char)ch)) {
113 				if(flags & RPP_FORCELOWER)
114 					ch = (char)tolower((unsigned char)ch);
115 				if(flags & RPP_FORCEUPPER)
116 					ch = (char)toupper((unsigned char)ch);
117 			}
118 
119 			outBuf[current_index++] = ch;
120 			if(flags & RPP_ECHO_ON)
121 				printf_s("%c", ch);
122 		}
123 	}
124 
125 	outBuf[current_index] = '\0';
126 	_cputs("\n");
127 
128 	return outBuf;
129 }
130 
131 #endif /* HAVE_READPASSPHRASE */
132