2 * Copyright 2006 Juan Lang for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27 DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
32 TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
36 case CERT_RDN_ANY_TYPE:
38 case CERT_RDN_PRINTABLE_STRING:
39 case CERT_RDN_IA5_STRING:
44 DWORD chars = min(pValue->cbData, csz - 1);
48 memcpy(psz, pValue->pbData, chars);
55 FIXME("string type %ld unimplemented\n", dwValueType);
65 TRACE("returning %ld (%s)\n", ret, debugstr_a(psz));
69 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
70 LPWSTR psz, DWORD csz)
74 TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
78 case CERT_RDN_ANY_TYPE:
80 case CERT_RDN_PRINTABLE_STRING:
81 case CERT_RDN_IA5_STRING:
86 DWORD chars = min(pValue->cbData, csz - 1);
92 for (i = 0; i < chars; i++)
93 psz[i] = pValue->pbData[i];
100 FIXME("string type %ld unimplemented\n", dwValueType);
110 TRACE("returning %ld (%s)\n", ret, debugstr_w(psz));
114 /* Adds the prefix prefix to the string pointed to by psz, followed by the
115 * character '='. Copies no more than csz characters. Returns the number of
116 * characters copied. If psz is NULL, returns the number of characters that
119 static DWORD CRYPT_AddPrefixA(LPCSTR prefix, LPSTR psz, DWORD csz)
123 TRACE("(%s, %p, %ld)\n", debugstr_a(prefix), psz, csz);
127 chars = min(lstrlenA(prefix), csz);
128 memcpy(psz, prefix, chars);
130 *(psz + chars) = '=';
135 chars = lstrlenA(prefix) + 1;
139 DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
140 DWORD dwStrType, LPSTR psz, DWORD csz)
142 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
143 CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
144 static const char commaSep[] = ", ";
145 static const char semiSep[] = "; ";
146 static const char crlfSep[] = "\r\n";
147 static const char plusSep[] = " + ";
148 static const char spaceSep[] = " ";
149 DWORD ret = 0, bytes = 0;
151 CERT_NAME_INFO *info;
153 TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
155 if (dwStrType & unsupportedFlags)
156 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
158 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
159 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
162 DWORD i, j, sepLen, rdnSepLen;
165 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
167 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
171 sepLen = strlen(sep);
172 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
176 rdnSepLen = strlen(rdnSep);
177 for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
179 for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++)
182 char prefixBuf[10]; /* big enough for GivenName */
183 LPCSTR prefix = NULL;
185 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
186 prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId;
187 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
189 PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
190 CRYPT_OID_INFO_OID_KEY,
191 info->rgRDN[i].rgRDNAttr[j].pszObjId,
192 CRYPT_RDN_ATTR_OID_GROUP_ID);
196 WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1,
197 prefixBuf, sizeof(prefixBuf), NULL, NULL);
201 prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId;
205 /* - 1 is needed to account for the NULL terminator. */
206 chars = CRYPT_AddPrefixA(prefix,
207 psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
211 /* FIXME: handle quoting */
212 chars = CertRDNValueToStrA(
213 info->rgRDN[i].rgRDNAttr[j].dwValueType,
214 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
215 psz ? csz - ret : 0);
218 if (j < info->rgRDN[i].cRDNAttr - 1)
220 if (psz && ret < csz - rdnSepLen - 1)
221 memcpy(psz + ret, rdnSep, rdnSepLen);
225 if (i < info->cRDN - 1)
227 if (psz && ret < csz - sepLen - 1)
228 memcpy(psz + ret, sep, sepLen);
242 TRACE("Returning %s\n", debugstr_a(psz));
246 /* Adds the prefix prefix to the wide-character string pointed to by psz,
247 * followed by the character '='. Copies no more than csz characters. Returns
248 * the number of characters copied. If psz is NULL, returns the number of
249 * characters that would be copied.
250 * Assumes the characters in prefix are ASCII (not multibyte characters.)
252 static DWORD CRYPT_AddPrefixAToW(LPCSTR prefix, LPWSTR psz, DWORD csz)
256 TRACE("(%s, %p, %ld)\n", debugstr_a(prefix), psz, csz);
262 chars = min(lstrlenA(prefix), csz);
263 for (i = 0; i < chars; i++)
264 *(psz + i) = prefix[i];
266 *(psz + chars) = '=';
271 chars = lstrlenA(prefix) + 1;
275 /* Adds the prefix prefix to the string pointed to by psz, followed by the
276 * character '='. Copies no more than csz characters. Returns the number of
277 * characters copied. If psz is NULL, returns the number of characters that
280 static DWORD CRYPT_AddPrefixW(LPCWSTR prefix, LPWSTR psz, DWORD csz)
284 TRACE("(%s, %p, %ld)\n", debugstr_w(prefix), psz, csz);
288 chars = min(lstrlenW(prefix), csz);
289 memcpy(psz, prefix, chars * sizeof(WCHAR));
291 *(psz + chars) = '=';
296 chars = lstrlenW(prefix) + 1;
300 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
301 DWORD dwStrType, LPWSTR psz, DWORD csz)
303 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
304 CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
305 static const WCHAR commaSep[] = { ',',' ',0 };
306 static const WCHAR semiSep[] = { ';',' ',0 };
307 static const WCHAR crlfSep[] = { '\r','\n',0 };
308 static const WCHAR plusSep[] = { ' ','+',' ',0 };
309 static const WCHAR spaceSep[] = { ' ',0 };
310 DWORD ret = 0, bytes = 0;
312 CERT_NAME_INFO *info;
314 TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
316 if (dwStrType & unsupportedFlags)
317 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
319 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
320 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
323 DWORD i, j, sepLen, rdnSepLen;
326 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
328 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
332 sepLen = lstrlenW(sep);
333 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
337 rdnSepLen = lstrlenW(rdnSep);
338 for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
340 for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++)
343 LPCSTR prefixA = NULL;
344 LPCWSTR prefixW = NULL;
346 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
347 prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId;
348 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
350 PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
351 CRYPT_OID_INFO_OID_KEY,
352 info->rgRDN[i].rgRDNAttr[j].pszObjId,
353 CRYPT_RDN_ATTR_OID_GROUP_ID);
356 prefixW = oidInfo->pwszName;
358 prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId;
362 /* - 1 is needed to account for the NULL terminator. */
363 chars = CRYPT_AddPrefixW(prefixW,
364 psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
370 /* - 1 is needed to account for the NULL terminator. */
371 chars = CRYPT_AddPrefixAToW(prefixA,
372 psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
376 /* FIXME: handle quoting */
377 chars = CertRDNValueToStrW(
378 info->rgRDN[i].rgRDNAttr[j].dwValueType,
379 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
380 psz ? csz - ret : 0);
383 if (j < info->rgRDN[i].cRDNAttr - 1)
385 if (psz && ret < csz - rdnSepLen - 1)
386 memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR));
390 if (i < info->cRDN - 1)
392 if (psz && ret < csz - sepLen - 1)
393 memcpy(psz + ret, sep, sepLen * sizeof(WCHAR));
407 TRACE("Returning %s\n", debugstr_w(psz));
411 DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
412 DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString)
416 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType, dwFlags,
417 pvTypePara, pszNameString, cchNameString);
424 nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
426 wideName = CryptMemAlloc(nameLen * sizeof(WCHAR));
429 CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
431 nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen,
432 pszNameString, cchNameString, NULL, NULL);
433 if (nameLen <= cchNameString)
437 pszNameString[cchNameString - 1] = '\0';
440 CryptMemFree(wideName);
444 *pszNameString = '\0';
449 ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
454 DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
455 DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
458 PCERT_NAME_BLOB name;
461 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType,
462 dwFlags, pvTypePara, pszNameString, cchNameString);
464 if (dwFlags & CERT_NAME_ISSUER_FLAG)
466 name = &pCertContext->pCertInfo->Issuer;
467 altNameOID = szOID_ISSUER_ALT_NAME;
471 name = &pCertContext->pCertInfo->Subject;
472 altNameOID = szOID_SUBJECT_ALT_NAME;
477 case CERT_NAME_SIMPLE_DISPLAY_TYPE:
479 static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME,
480 szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME,
481 szOID_RSA_emailAddr };
482 CERT_NAME_INFO *info = NULL;
483 PCERT_RDN_ATTR nameAttr = NULL;
486 if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME,
487 name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info,
490 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
491 sizeof(simpleAttributeOIDs[0]); i++)
492 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
498 PCERT_EXTENSION ext = CertFindExtension(altNameOID,
499 pCertContext->pCertInfo->cExtension,
500 pCertContext->pCertInfo->rgExtension);
504 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
505 sizeof(simpleAttributeOIDs[0]); i++)
506 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
509 /* FIXME: gotta then look for a rfc822Name choice in ext.
510 * Failing that, look for the first attribute.
512 FIXME("CERT_NAME_SIMPLE_DISPLAY_TYPE: stub\n");
517 ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value,
518 pszNameString, cchNameString);
523 case CERT_NAME_FRIENDLY_DISPLAY_TYPE:
525 DWORD cch = cchNameString;
527 if (CertGetCertificateContextProperty(pCertContext,
528 CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch))
531 ret = CertGetNameStringW(pCertContext,
532 CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString,
537 FIXME("unimplemented for type %ld\n", dwType);