FreeRDP
Loading...
Searching...
No Matches
credentials.c
1
21#include <winpr/config.h>
22#include <winpr/crt.h>
23#include <winpr/cred.h>
24#include <winpr/error.h>
25#include <winpr/wlog.h>
26#include "../log.h"
27
28#define TAG WINPR_TAG("Cred")
29
30/*
31 * Low-Level Credentials Management Functions:
32 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa374731(v=vs.85).aspx#low_level_credentials_management_functions
33 */
34
35#ifndef _WIN32
36
37static BYTE wchar_decode(WCHAR c)
38{
39 if (c >= 'A' && c <= 'Z')
40 return (BYTE)(c - 'A');
41 if (c >= 'a' && c <= 'z')
42 return (BYTE)(c - 'a' + 26);
43 if (c >= '0' && c <= '9')
44 return (BYTE)(c - '0' + 52);
45 if (c == '#')
46 return 62;
47 if (c == '-')
48 return 63;
49 return 64;
50}
51
52static BOOL cred_decode(const WCHAR* cred, size_t len, BYTE* buf)
53{
54 size_t i = 0;
55 const WCHAR* p = cred;
56
57 while (len >= 4)
58 {
59 BYTE c0 = wchar_decode(p[0]);
60 if (c0 > 63)
61 return FALSE;
62
63 BYTE c1 = wchar_decode(p[1]);
64 if (c1 > 63)
65 return FALSE;
66
67 BYTE c2 = wchar_decode(p[2]);
68 if (c2 > 63)
69 return FALSE;
70
71 BYTE c3 = wchar_decode(p[3]);
72 if (c3 > 63)
73 return FALSE;
74
75 buf[i + 0] = (BYTE)((c1 << 6) | c0);
76 buf[i + 1] = (BYTE)((c2 << 4) | (c1 >> 2));
77 buf[i + 2] = (BYTE)((c3 << 2) | (c2 >> 4));
78 len -= 4;
79 i += 3;
80 p += 4;
81 }
82
83 if (len == 3)
84 {
85 BYTE c0 = wchar_decode(p[0]);
86 if (c0 > 63)
87 return FALSE;
88
89 BYTE c1 = wchar_decode(p[1]);
90 if (c1 > 63)
91 return FALSE;
92
93 BYTE c2 = wchar_decode(p[2]);
94 if (c2 > 63)
95 return FALSE;
96
97 buf[i + 0] = (BYTE)((c1 << 6) | c0);
98 buf[i + 1] = (BYTE)((c2 << 4) | (c1 >> 2));
99 }
100 else if (len == 2)
101 {
102 BYTE c0 = wchar_decode(p[0]);
103 if (c0 > 63)
104 return FALSE;
105
106 BYTE c1 = wchar_decode(p[1]);
107 if (c1 > 63)
108 return FALSE;
109
110 buf[i + 0] = (BYTE)((c1 << 6) | c0);
111 }
112 else if (len == 1)
113 {
114 WLog_ERR(TAG, "invalid string length");
115 return FALSE;
116 }
117 return TRUE;
118}
119
120static size_t cred_encode(const BYTE* bin, size_t len, WCHAR* cred)
121{
122 static const WCHAR encodingChars[] = {
123 /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
124 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
125 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
126 /* abcdefghijklmnopqrstuvwxyz */
127 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
128 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
129 /* 0123456789 */
130 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
131 /* #- */
132 0x23, 0x2d
133 };
134 size_t n = 0;
135
136 while (len > 0)
137 {
138 cred[n++] = encodingChars[bin[0] & 0x3f];
139 BYTE x = (bin[0] & 0xc0) >> 6;
140 if (len == 1)
141 {
142 cred[n++] = encodingChars[x];
143 break;
144 }
145
146 cred[n++] = encodingChars[((bin[1] & 0xf) << 2) | x];
147 x = (bin[1] & 0xf0) >> 4;
148 if (len == 2)
149 {
150 cred[n++] = encodingChars[x];
151 break;
152 }
153
154 cred[n++] = encodingChars[((bin[2] & 0x3) << 4) | x];
155 cred[n++] = encodingChars[(bin[2] & 0xfc) >> 2];
156 bin += 3;
157 len -= 3;
158 }
159 return n;
160}
161
162BOOL CredMarshalCredentialW(CRED_MARSHAL_TYPE CredType, PVOID cred, LPWSTR* MarshaledCredential)
163{
164 CERT_CREDENTIAL_INFO* cert = cred;
165 WCHAR* p = NULL;
166
167 if (!cred || (CredType == CertCredential && cert->cbSize < sizeof(*cert)))
168 {
169 SetLastError(ERROR_INVALID_PARAMETER);
170 return FALSE;
171 }
172
173 switch (CredType)
174 {
175 case CertCredential:
176 {
177 size_t size = (sizeof(cert->rgbHashOfCert) + 2) * 4 / 3;
178 if (!(p = malloc((size + 4) * sizeof(WCHAR))))
179 return FALSE;
180 p[0] = '@';
181 p[1] = '@';
182 p[2] = (WCHAR)('A' + CredType);
183 size_t len = cred_encode(cert->rgbHashOfCert, sizeof(cert->rgbHashOfCert), p + 3);
184 p[len + 3] = 0;
185 break;
186 }
187 default:
188 WLog_ERR(TAG, "unhandled type 0x%x", CredType);
189 SetLastError(ERROR_INVALID_PARAMETER);
190 return FALSE;
191 }
192
193 *MarshaledCredential = p;
194 return TRUE;
195}
196
197BOOL CredMarshalCredentialA(CRED_MARSHAL_TYPE CredType, PVOID Credential,
198 LPSTR* MarshaledCredential)
199{
200 WCHAR* b = NULL;
201 if (!CredMarshalCredentialW(CredType, Credential, &b) || !b)
202 return FALSE;
203
204 *MarshaledCredential = ConvertWCharNToUtf8Alloc(b, _wcslen(b), NULL);
205 free(b);
206 return (*MarshaledCredential != NULL);
207}
208
209BOOL CredUnmarshalCredentialW(LPCWSTR cred, PCRED_MARSHAL_TYPE pcredType, PVOID* out)
210{
211 if (!cred || !pcredType || !out || cred[0] != '@' || cred[1] != '@')
212 {
213 SetLastError(ERROR_INVALID_PARAMETER);
214 return FALSE;
215 }
216
217 BYTE b = wchar_decode(cred[2]);
218 if (!b || b > BinaryBlobForSystem)
219 {
220 SetLastError(ERROR_INVALID_PARAMETER);
221 return FALSE;
222 }
223
224 *pcredType = (CRED_MARSHAL_TYPE)b;
225
226 size_t len = _wcslen(cred + 3);
227 switch (*pcredType)
228 {
229 case CertCredential:
230 {
231 BYTE hash[CERT_HASH_LENGTH];
232
233 if (len != 27 || !cred_decode(cred + 3, len, hash))
234 {
235 SetLastError(ERROR_INVALID_PARAMETER);
236 return FALSE;
237 }
238
239 CERT_CREDENTIAL_INFO* cert = malloc(sizeof(*cert));
240 if (!cert)
241 return FALSE;
242
243 memcpy(cert->rgbHashOfCert, hash, sizeof(cert->rgbHashOfCert));
244 cert->cbSize = sizeof(*cert);
245 *out = cert;
246 break;
247 }
248 default:
249 WLog_ERR(TAG, "unhandled credType 0x%x", *pcredType);
250 SetLastError(ERROR_INVALID_PARAMETER);
251 return FALSE;
252 }
253 return TRUE;
254}
255
256BOOL CredUnmarshalCredentialA(LPCSTR cred, PCRED_MARSHAL_TYPE CredType, PVOID* Credential)
257{
258 WCHAR* b = ConvertUtf8NToWCharAlloc(cred, strlen(cred), NULL);
259 if (!b)
260 return FALSE;
261
262 BOOL ret = CredUnmarshalCredentialW(b, CredType, Credential);
263 free(b);
264 return ret;
265}
266
267BOOL CredIsMarshaledCredentialW(LPCWSTR MarshaledCredential)
268{
269 CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
270 void* out = NULL;
271
272 BOOL ret = CredUnmarshalCredentialW(MarshaledCredential, &t, &out);
273 if (out)
274 CredFree(out);
275
276 return ret;
277}
278
279BOOL CredIsMarshaledCredentialA(LPCSTR MarshaledCredential)
280{
281 CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
282 void* out = NULL;
283 BOOL ret = CredUnmarshalCredentialA(MarshaledCredential, &t, &out);
284 if (out)
285 CredFree(out);
286
287 return ret;
288}
289
290VOID CredFree(PVOID Buffer)
291{
292 free(Buffer);
293}
294
295#endif /* _WIN32 */