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 char_decode(char 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 char* cred, size_t len, BYTE* buf)
53{
54 size_t i = 0;
55 const char* p = cred;
56
57 while (len >= 4)
58 {
59 BYTE c0 = char_decode(p[0]);
60 if (c0 > 63)
61 return FALSE;
62
63 BYTE c1 = char_decode(p[1]);
64 if (c1 > 63)
65 return FALSE;
66
67 BYTE c2 = char_decode(p[2]);
68 if (c2 > 63)
69 return FALSE;
70
71 BYTE c3 = char_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 = char_decode(p[0]);
86 if (c0 > 63)
87 return FALSE;
88
89 BYTE c1 = char_decode(p[1]);
90 if (c1 > 63)
91 return FALSE;
92
93 BYTE c2 = char_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 = char_decode(p[0]);
103 if (c0 > 63)
104 return FALSE;
105
106 BYTE c1 = char_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, char* cred, size_t credlen)
121{
122 static const char encodingChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
123 "abcdefghijklmnopqrstuvwxyz"
124 "0123456789"
125 "#-";
126 size_t n = 0;
127 size_t offset = 0;
128 while (offset < len)
129 {
130 if (n >= credlen)
131 break;
132
133 cred[n++] = encodingChars[bin[offset] & 0x3f];
134 BYTE x = (bin[offset] & 0xc0) >> 6;
135 offset++;
136
137 if (offset >= len)
138 {
139 cred[n++] = encodingChars[x];
140 break;
141 }
142
143 if (n >= credlen)
144 break;
145 cred[n++] = encodingChars[((bin[offset] & 0xf) << 2) | x];
146 x = (bin[offset] & 0xf0) >> 4;
147 offset++;
148
149 if (offset >= len)
150 {
151 cred[n++] = encodingChars[x];
152 break;
153 }
154
155 if (n >= credlen)
156 break;
157 cred[n++] = encodingChars[((bin[offset] & 0x3) << 4) | x];
158
159 if (n >= credlen)
160 break;
161 cred[n++] = encodingChars[(bin[offset] & 0xfc) >> 2];
162 offset++;
163 }
164 return n;
165}
166
167BOOL CredMarshalCredentialW(CRED_MARSHAL_TYPE CredType, PVOID Credential,
168 LPWSTR* MarshaledCredential)
169{
170 char* b = NULL;
171 if (!CredMarshalCredentialA(CredType, Credential, &b) || !b)
172 return FALSE;
173
174 *MarshaledCredential = ConvertUtf8ToWCharAlloc(b, NULL);
175 free(b);
176 return (*MarshaledCredential != NULL);
177}
178
179BOOL CredMarshalCredentialA(CRED_MARSHAL_TYPE CredType, PVOID Credential,
180 LPSTR* MarshaledCredential)
181{
182 CERT_CREDENTIAL_INFO* cert = Credential;
183
184 if (!cert || ((CredType == CertCredential) && (cert->cbSize < sizeof(CERT_CREDENTIAL_INFO))) ||
185 !MarshaledCredential)
186 {
187 SetLastError(ERROR_INVALID_PARAMETER);
188 return FALSE;
189 }
190
191 switch (CredType)
192 {
193 case CertCredential:
194 {
195 char buffer[3ULL + (sizeof(cert->rgbHashOfCert) * 4 / 3) +
196 1ULL /* rounding error */] = { 0 };
197
198 const char c = WINPR_ASSERTING_INT_CAST(char, 'A' + CredType);
199 (void)_snprintf(buffer, sizeof(buffer), "@@%c", c);
200 size_t len = cred_encode(cert->rgbHashOfCert, sizeof(cert->rgbHashOfCert), &buffer[3],
201 sizeof(buffer) - 3);
202 *MarshaledCredential = strndup(buffer, len + 3);
203 return TRUE;
204 }
205 default:
206 WLog_ERR(TAG, "unhandled type 0x%x", CredType);
207 SetLastError(ERROR_INVALID_PARAMETER);
208 return FALSE;
209 }
210}
211
212BOOL CredUnmarshalCredentialW(LPCWSTR cred, PCRED_MARSHAL_TYPE pcredType, PVOID* out)
213{
214 char* str = NULL;
215 if (cred)
216 str = ConvertWCharToUtf8Alloc(cred, NULL);
217 const BOOL rc = CredUnmarshalCredentialA(str, pcredType, out);
218 free(str);
219 return rc;
220}
221
222BOOL CredUnmarshalCredentialA(LPCSTR cred, PCRED_MARSHAL_TYPE CredType, PVOID* Credential)
223{
224 if (!cred)
225 {
226 SetLastError(ERROR_INVALID_PARAMETER);
227 return FALSE;
228 }
229
230 const size_t len = strlen(cred);
231 if ((len < 3) || !CredType || !Credential || (cred[0] != '@') || (cred[1] != '@'))
232 {
233 SetLastError(ERROR_INVALID_PARAMETER);
234 return FALSE;
235 }
236
237 BYTE b = char_decode(cred[2]);
238 if (!b || (b > BinaryBlobForSystem))
239 {
240 SetLastError(ERROR_INVALID_PARAMETER);
241 return FALSE;
242 }
243
244 *CredType = (CRED_MARSHAL_TYPE)b;
245
246 switch (*CredType)
247 {
248 case CertCredential:
249 {
250 BYTE hash[CERT_HASH_LENGTH] = { 0 };
251
252 if ((len != 30) || !cred_decode(&cred[3], len - 3, hash))
253 {
254 SetLastError(ERROR_INVALID_PARAMETER);
255 return FALSE;
256 }
257
258 CERT_CREDENTIAL_INFO* cert = calloc(1, sizeof(CERT_CREDENTIAL_INFO));
259 if (!cert)
260 return FALSE;
261
262 cert->cbSize = sizeof(CERT_CREDENTIAL_INFO);
263 memcpy(cert->rgbHashOfCert, hash, sizeof(cert->rgbHashOfCert));
264 *Credential = cert;
265 break;
266 }
267 default:
268 WLog_ERR(TAG, "unhandled credType 0x%x", *CredType);
269 SetLastError(ERROR_INVALID_PARAMETER);
270 return FALSE;
271 }
272 return TRUE;
273}
274
275BOOL CredIsMarshaledCredentialW(LPCWSTR MarshaledCredential)
276{
277 CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
278 void* out = NULL;
279
280 BOOL ret = CredUnmarshalCredentialW(MarshaledCredential, &t, &out);
281 if (out)
282 CredFree(out);
283
284 return ret;
285}
286
287BOOL CredIsMarshaledCredentialA(LPCSTR MarshaledCredential)
288{
289 CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
290 void* out = NULL;
291 BOOL ret = CredUnmarshalCredentialA(MarshaledCredential, &t, &out);
292 if (out)
293 CredFree(out);
294
295 return ret;
296}
297
298VOID CredFree(PVOID Buffer)
299{
300 free(Buffer);
301}
302
303#endif /* _WIN32 */