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