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);
68 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
69 LPWSTR psz, DWORD csz)
73 TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
77 case CERT_RDN_ANY_TYPE:
79 case CERT_RDN_PRINTABLE_STRING:
80 case CERT_RDN_IA5_STRING:
85 DWORD chars = min(pValue->cbData, csz - 1);
91 for (i = 0; i < chars; i++)
92 psz[i] = pValue->pbData[i];
99 FIXME("string type %ld unimplemented\n", dwValueType);
112 DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
113 DWORD dwStrType, LPSTR psz, DWORD csz)
115 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
116 CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
117 static const char commaSep[] = ", ";
118 static const char semiSep[] = "; ";
119 static const char crlfSep[] = "\r\n";
120 static const char plusSep[] = " + ";
121 static const char spaceSep[] = " ";
122 DWORD ret = 0, bytes = 0;
124 CERT_NAME_INFO *info;
126 TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
128 if (dwStrType & unsupportedFlags)
129 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
131 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
132 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
135 DWORD i, j, sepLen, rdnSepLen;
138 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
140 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
144 sepLen = strlen(sep);
145 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
149 rdnSepLen = strlen(rdnSep);
150 for (i = 0; ret < csz && i < info->cRDN; i++)
152 for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
156 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
158 /* - 1 is needed to account for the NULL terminator. */
160 lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
163 memcpy(psz + ret, info->rgRDN[i].rgRDNAttr[j].pszObjId,
175 /* FIXME: handle quoting */
176 chars = CertRDNValueToStrA(
177 info->rgRDN[i].rgRDNAttr[j].dwValueType,
178 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
182 if (j < info->rgRDN[i].cRDNAttr - 1)
184 if (psz && ret < csz - rdnSepLen - 1)
185 memcpy(psz + ret, rdnSep, rdnSepLen);
189 if (i < info->cRDN - 1)
191 if (psz && ret < csz - sepLen - 1)
192 memcpy(psz + ret, sep, sepLen);
209 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
210 DWORD dwStrType, LPWSTR psz, DWORD csz)
212 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
213 CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
214 static const WCHAR commaSep[] = { ',',' ',0 };
215 static const WCHAR semiSep[] = { ';',' ',0 };
216 static const WCHAR crlfSep[] = { '\r','\n',0 };
217 static const WCHAR plusSep[] = { ' ','+',' ',0 };
218 static const WCHAR spaceSep[] = { ' ',0 };
219 DWORD ret = 0, bytes = 0;
221 CERT_NAME_INFO *info;
223 TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
225 if (dwStrType & unsupportedFlags)
226 FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
228 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
229 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
232 DWORD i, j, sepLen, rdnSepLen;
235 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
237 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
241 sepLen = lstrlenW(sep);
242 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
246 rdnSepLen = lstrlenW(rdnSep);
247 for (i = 0; ret < csz && i < info->cRDN; i++)
249 for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
253 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
255 /* - 1 is needed to account for the NULL terminator. */
257 lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
263 for (k = 0; k < chars; k++)
265 info->rgRDN[i].rgRDNAttr[j].pszObjId[k];
277 /* FIXME: handle quoting */
278 chars = CertRDNValueToStrW(
279 info->rgRDN[i].rgRDNAttr[j].dwValueType,
280 &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
284 if (j < info->rgRDN[i].cRDNAttr - 1)
286 if (psz && ret < csz - rdnSepLen - 1)
287 memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR));
291 if (i < info->cRDN - 1)
293 if (psz && ret < csz - sepLen - 1)
294 memcpy(psz + ret, sep, sepLen * sizeof(WCHAR));
311 DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
312 DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString)
316 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType, dwFlags,
317 pvTypePara, pszNameString, cchNameString);
324 nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
326 wideName = CryptMemAlloc(nameLen * sizeof(WCHAR));
329 CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
331 nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen,
332 pszNameString, cchNameString, NULL, NULL);
333 if (nameLen <= cchNameString)
337 pszNameString[cchNameString - 1] = '\0';
340 CryptMemFree(wideName);
344 *pszNameString = '\0';
349 ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
354 DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
355 DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
358 PCERT_NAME_BLOB name;
361 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext, dwType,
362 dwFlags, pvTypePara, pszNameString, cchNameString);
364 if (dwFlags & CERT_NAME_ISSUER_FLAG)
366 name = &pCertContext->pCertInfo->Issuer;
367 altNameOID = szOID_ISSUER_ALT_NAME;
371 name = &pCertContext->pCertInfo->Subject;
372 altNameOID = szOID_SUBJECT_ALT_NAME;
377 case CERT_NAME_SIMPLE_DISPLAY_TYPE:
379 static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME,
380 szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME,
381 szOID_RSA_emailAddr };
382 CERT_NAME_INFO *info = NULL;
383 PCERT_RDN_ATTR nameAttr = NULL;
386 if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME,
387 name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info,
390 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
391 sizeof(simpleAttributeOIDs[0]); i++)
392 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
398 PCERT_EXTENSION ext = CertFindExtension(altNameOID,
399 pCertContext->pCertInfo->cExtension,
400 pCertContext->pCertInfo->rgExtension);
404 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
405 sizeof(simpleAttributeOIDs[0]); i++)
406 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
409 /* FIXME: gotta then look for a rfc822Name choice in ext.
410 * Failing that, look for the first attribute.
412 FIXME("CERT_NAME_SIMPLE_DISPLAY_TYPE: stub\n");
417 ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value,
418 pszNameString, cchNameString);
423 case CERT_NAME_FRIENDLY_DISPLAY_TYPE:
425 DWORD cch = cchNameString;
427 if (CertGetCertificateContextProperty(pCertContext,
428 CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch))
431 ret = CertGetNameStringW(pCertContext,
432 CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString,
437 FIXME("unimplemented for type %ld\n", dwType);