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