21#include <winpr/config.h>
23#include <winpr/cred.h>
24#include <winpr/error.h>
25#include <winpr/wlog.h>
28#define TAG WINPR_TAG("Cred")
37static BYTE wchar_decode(WCHAR c)
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);
52static BOOL cred_decode(
const WCHAR* cred,
size_t len, BYTE* buf)
55 const WCHAR* p = cred;
59 BYTE c0 = wchar_decode(p[0]);
63 BYTE c1 = wchar_decode(p[1]);
67 BYTE c2 = wchar_decode(p[2]);
71 BYTE c3 = wchar_decode(p[3]);
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));
85 BYTE c0 = wchar_decode(p[0]);
89 BYTE c1 = wchar_decode(p[1]);
93 BYTE c2 = wchar_decode(p[2]);
97 buf[i + 0] = (BYTE)((c1 << 6) | c0);
98 buf[i + 1] = (BYTE)((c2 << 4) | (c1 >> 2));
102 BYTE c0 = wchar_decode(p[0]);
106 BYTE c1 = wchar_decode(p[1]);
110 buf[i + 0] = (BYTE)((c1 << 6) | c0);
114 WLog_ERR(TAG,
"invalid string length");
120static size_t cred_encode(
const BYTE* bin,
size_t len, WCHAR* cred)
122 static const WCHAR encodingChars[] = {
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,
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,
130 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
138 cred[n++] = encodingChars[bin[0] & 0x3f];
139 BYTE x = (bin[0] & 0xc0) >> 6;
142 cred[n++] = encodingChars[x];
146 cred[n++] = encodingChars[((bin[1] & 0xf) << 2) | x];
147 x = (bin[1] & 0xf0) >> 4;
150 cred[n++] = encodingChars[x];
154 cred[n++] = encodingChars[((bin[2] & 0x3) << 4) | x];
155 cred[n++] = encodingChars[(bin[2] & 0xfc) >> 2];
162BOOL CredMarshalCredentialW(CRED_MARSHAL_TYPE CredType, PVOID cred, LPWSTR* MarshaledCredential)
167 if (!cred || (CredType == CertCredential && cert->cbSize <
sizeof(*cert)))
169 SetLastError(ERROR_INVALID_PARAMETER);
177 size_t size = (
sizeof(cert->rgbHashOfCert) + 2) * 4 / 3;
178 if (!(p = malloc((size + 4) *
sizeof(WCHAR))))
182 p[2] = (WCHAR)(
'A' + CredType);
183 size_t len = cred_encode(cert->rgbHashOfCert,
sizeof(cert->rgbHashOfCert), p + 3);
188 WLog_ERR(TAG,
"unhandled type 0x%x", CredType);
189 SetLastError(ERROR_INVALID_PARAMETER);
193 *MarshaledCredential = p;
197BOOL CredMarshalCredentialA(CRED_MARSHAL_TYPE CredType, PVOID Credential,
198 LPSTR* MarshaledCredential)
201 if (!CredMarshalCredentialW(CredType, Credential, &b) || !b)
204 *MarshaledCredential = ConvertWCharNToUtf8Alloc(b, _wcslen(b), NULL);
206 return (*MarshaledCredential != NULL);
209BOOL CredUnmarshalCredentialW(LPCWSTR cred, PCRED_MARSHAL_TYPE pcredType, PVOID* out)
211 if (!cred || !pcredType || !out || cred[0] !=
'@' || cred[1] !=
'@')
213 SetLastError(ERROR_INVALID_PARAMETER);
217 BYTE b = wchar_decode(cred[2]);
218 if (!b || b > BinaryBlobForSystem)
220 SetLastError(ERROR_INVALID_PARAMETER);
224 *pcredType = (CRED_MARSHAL_TYPE)b;
226 size_t len = _wcslen(cred + 3);
231 BYTE hash[CERT_HASH_LENGTH];
233 if (len != 27 || !cred_decode(cred + 3, len, hash))
235 SetLastError(ERROR_INVALID_PARAMETER);
243 memcpy(cert->rgbHashOfCert, hash,
sizeof(cert->rgbHashOfCert));
244 cert->cbSize =
sizeof(*cert);
249 WLog_ERR(TAG,
"unhandled credType 0x%x", *pcredType);
250 SetLastError(ERROR_INVALID_PARAMETER);
256BOOL CredUnmarshalCredentialA(LPCSTR cred, PCRED_MARSHAL_TYPE CredType, PVOID* Credential)
258 WCHAR* b = ConvertUtf8NToWCharAlloc(cred, strlen(cred), NULL);
262 BOOL ret = CredUnmarshalCredentialW(b, CredType, Credential);
267BOOL CredIsMarshaledCredentialW(LPCWSTR MarshaledCredential)
269 CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
272 BOOL ret = CredUnmarshalCredentialW(MarshaledCredential, &t, &out);
279BOOL CredIsMarshaledCredentialA(LPCSTR MarshaledCredential)
281 CRED_MARSHAL_TYPE t = BinaryBlobForSystem;
283 BOOL ret = CredUnmarshalCredentialA(MarshaledCredential, &t, &out);
290VOID CredFree(PVOID Buffer)