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 /* Adds the prefix prefix to the string pointed to by psz, followed by the
113 * character '='. Copies no more than csz characters. Returns the number of
114 * characters copied. If psz is NULL, returns the number of characters that
117 static DWORD
CRYPT_AddPrefixA(LPCSTR prefix
, LPSTR psz
, DWORD csz
)
119 DWORD chars
= min(lstrlenA(prefix
), csz
);
121 TRACE("(%s, %p, %ld)\n", debugstr_a(prefix
), psz
, csz
);
124 memcpy(psz
, prefix
, chars
);
129 *(psz
+ chars
) = '=';
136 DWORD WINAPI
CertNameToStrA(DWORD dwCertEncodingType
, PCERT_NAME_BLOB pName
,
137 DWORD dwStrType
, LPSTR psz
, DWORD csz
)
139 static const DWORD unsupportedFlags
= CERT_NAME_STR_NO_QUOTING_FLAG
|
140 CERT_NAME_STR_REVERSE_FLAG
| CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG
;
141 static const char commaSep
[] = ", ";
142 static const char semiSep
[] = "; ";
143 static const char crlfSep
[] = "\r\n";
144 static const char plusSep
[] = " + ";
145 static const char spaceSep
[] = " ";
146 DWORD ret
= 0, bytes
= 0;
148 CERT_NAME_INFO
*info
;
150 TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType
, pName
, dwStrType
,
152 if (dwStrType
& unsupportedFlags
)
153 FIXME("unsupported flags: %08lx\n", dwStrType
& unsupportedFlags
);
155 bRet
= CryptDecodeObjectEx(dwCertEncodingType
, X509_NAME
, pName
->pbData
,
156 pName
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &bytes
);
159 DWORD i
, j
, sepLen
, rdnSepLen
;
162 if (dwStrType
& CERT_NAME_STR_SEMICOLON_FLAG
)
164 else if (dwStrType
& CERT_NAME_STR_CRLF_FLAG
)
168 sepLen
= strlen(sep
);
169 if (dwStrType
& CERT_NAME_STR_NO_PLUS_FLAG
)
173 rdnSepLen
= strlen(rdnSep
);
174 for (i
= 0; ret
< csz
&& i
< info
->cRDN
; i
++)
176 for (j
= 0; ret
< csz
&& j
< info
->rgRDN
[i
].cRDNAttr
; j
++)
179 char prefixBuf
[10]; /* big enough for GivenName */
180 LPCSTR prefix
= NULL
;
182 if ((dwStrType
& 0x000000ff) == CERT_OID_NAME_STR
)
183 prefix
= info
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
;
184 else if ((dwStrType
& 0x000000ff) == CERT_X500_NAME_STR
)
186 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(
187 CRYPT_OID_INFO_OID_KEY
,
188 info
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
,
189 CRYPT_RDN_ATTR_OID_GROUP_ID
);
193 WideCharToMultiByte(CP_ACP
, 0, oidInfo
->pwszName
, -1,
194 prefixBuf
, sizeof(prefixBuf
), NULL
, NULL
);
198 prefix
= info
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
;
202 /* - 1 is needed to account for the NULL terminator. */
203 chars
= CRYPT_AddPrefixA(prefix
, psz
+ ret
, csz
- ret
- 1);
207 /* FIXME: handle quoting */
208 chars
= CertRDNValueToStrA(
209 info
->rgRDN
[i
].rgRDNAttr
[j
].dwValueType
,
210 &info
->rgRDN
[i
].rgRDNAttr
[j
].Value
, psz
? psz
+ ret
: NULL
,
214 if (j
< info
->rgRDN
[i
].cRDNAttr
- 1)
216 if (psz
&& ret
< csz
- rdnSepLen
- 1)
217 memcpy(psz
+ ret
, rdnSep
, rdnSepLen
);
221 if (i
< info
->cRDN
- 1)
223 if (psz
&& ret
< csz
- sepLen
- 1)
224 memcpy(psz
+ ret
, sep
, sepLen
);
241 /* Adds the prefix prefix to the wide-character string pointed to by psz,
242 * followed by the character '='. Copies no more than csz characters. Returns
243 * the number of characters copied. If psz is NULL, returns the number of
244 * characters that would be copied.
245 * Assumes the characters in prefix are ASCII (not multibyte characters.)
247 static DWORD
CRYPT_AddPrefixAToW(LPCSTR prefix
, LPWSTR psz
, DWORD csz
)
249 DWORD chars
= min(lstrlenA(prefix
), csz
);
251 TRACE("(%s, %p, %ld)\n", debugstr_a(prefix
), psz
, csz
);
257 for (i
= 0; i
< chars
; i
++)
258 *(psz
+ i
) = prefix
[i
];
264 *(psz
+ chars
) = '=';
271 /* Adds the prefix prefix to the string pointed to by psz, followed by the
272 * character '='. Copies no more than csz characters. Returns the number of
273 * characters copied. If psz is NULL, returns the number of characters that
276 static DWORD
CRYPT_AddPrefixW(LPCWSTR prefix
, LPWSTR psz
, DWORD csz
)
278 DWORD chars
= min(lstrlenW(prefix
), csz
);
280 TRACE("(%s, %p, %ld)\n", debugstr_w(prefix
), psz
, csz
);
283 memcpy(psz
, prefix
, chars
* sizeof(WCHAR
));
288 *(psz
+ chars
) = '=';
295 DWORD WINAPI
CertNameToStrW(DWORD dwCertEncodingType
, PCERT_NAME_BLOB pName
,
296 DWORD dwStrType
, LPWSTR psz
, DWORD csz
)
298 static const DWORD unsupportedFlags
= CERT_NAME_STR_NO_QUOTING_FLAG
|
299 CERT_NAME_STR_REVERSE_FLAG
| CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG
;
300 static const WCHAR commaSep
[] = { ',',' ',0 };
301 static const WCHAR semiSep
[] = { ';',' ',0 };
302 static const WCHAR crlfSep
[] = { '\r','\n',0 };
303 static const WCHAR plusSep
[] = { ' ','+',' ',0 };
304 static const WCHAR spaceSep
[] = { ' ',0 };
305 DWORD ret
= 0, bytes
= 0;
307 CERT_NAME_INFO
*info
;
309 TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType
, pName
, dwStrType
,
311 if (dwStrType
& unsupportedFlags
)
312 FIXME("unsupported flags: %08lx\n", dwStrType
& unsupportedFlags
);
314 bRet
= CryptDecodeObjectEx(dwCertEncodingType
, X509_NAME
, pName
->pbData
,
315 pName
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &bytes
);
318 DWORD i
, j
, sepLen
, rdnSepLen
;
321 if (dwStrType
& CERT_NAME_STR_SEMICOLON_FLAG
)
323 else if (dwStrType
& CERT_NAME_STR_CRLF_FLAG
)
327 sepLen
= lstrlenW(sep
);
328 if (dwStrType
& CERT_NAME_STR_NO_PLUS_FLAG
)
332 rdnSepLen
= lstrlenW(rdnSep
);
333 for (i
= 0; ret
< csz
&& i
< info
->cRDN
; i
++)
335 for (j
= 0; ret
< csz
&& j
< info
->rgRDN
[i
].cRDNAttr
; j
++)
338 LPCSTR prefixA
= NULL
;
339 LPCWSTR prefixW
= NULL
;
341 if ((dwStrType
& 0x000000ff) == CERT_OID_NAME_STR
)
342 prefixA
= info
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
;
343 else if ((dwStrType
& 0x000000ff) == CERT_X500_NAME_STR
)
345 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(
346 CRYPT_OID_INFO_OID_KEY
,
347 info
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
,
348 CRYPT_RDN_ATTR_OID_GROUP_ID
);
351 prefixW
= oidInfo
->pwszName
;
353 prefixA
= info
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
;
357 /* - 1 is needed to account for the NULL terminator. */
358 chars
= CRYPT_AddPrefixW(prefixW
, psz
+ ret
, csz
- ret
- 1);
364 /* - 1 is needed to account for the NULL terminator. */
365 chars
= CRYPT_AddPrefixAToW(prefixA
, psz
+ ret
,
370 /* FIXME: handle quoting */
371 chars
= CertRDNValueToStrW(
372 info
->rgRDN
[i
].rgRDNAttr
[j
].dwValueType
,
373 &info
->rgRDN
[i
].rgRDNAttr
[j
].Value
, psz
? psz
+ ret
: NULL
,
377 if (j
< info
->rgRDN
[i
].cRDNAttr
- 1)
379 if (psz
&& ret
< csz
- rdnSepLen
- 1)
380 memcpy(psz
+ ret
, rdnSep
, rdnSepLen
* sizeof(WCHAR
));
384 if (i
< info
->cRDN
- 1)
386 if (psz
&& ret
< csz
- sepLen
- 1)
387 memcpy(psz
+ ret
, sep
, sepLen
* sizeof(WCHAR
));
404 DWORD WINAPI
CertGetNameStringA(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
405 DWORD dwFlags
, void *pvTypePara
, LPSTR pszNameString
, DWORD cchNameString
)
409 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext
, dwType
, dwFlags
,
410 pvTypePara
, pszNameString
, cchNameString
);
417 nameLen
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, pvTypePara
,
419 wideName
= CryptMemAlloc(nameLen
* sizeof(WCHAR
));
422 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, pvTypePara
,
424 nameLen
= WideCharToMultiByte(CP_ACP
, 0, wideName
, nameLen
,
425 pszNameString
, cchNameString
, NULL
, NULL
);
426 if (nameLen
<= cchNameString
)
430 pszNameString
[cchNameString
- 1] = '\0';
433 CryptMemFree(wideName
);
437 *pszNameString
= '\0';
442 ret
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, pvTypePara
,
447 DWORD WINAPI
CertGetNameStringW(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
448 DWORD dwFlags
, void *pvTypePara
, LPWSTR pszNameString
, DWORD cchNameString
)
451 PCERT_NAME_BLOB name
;
454 TRACE("(%p, %ld, %08lx, %p, %p, %ld)\n", pCertContext
, dwType
,
455 dwFlags
, pvTypePara
, pszNameString
, cchNameString
);
457 if (dwFlags
& CERT_NAME_ISSUER_FLAG
)
459 name
= &pCertContext
->pCertInfo
->Issuer
;
460 altNameOID
= szOID_ISSUER_ALT_NAME
;
464 name
= &pCertContext
->pCertInfo
->Subject
;
465 altNameOID
= szOID_SUBJECT_ALT_NAME
;
470 case CERT_NAME_SIMPLE_DISPLAY_TYPE
:
472 static const LPCSTR simpleAttributeOIDs
[] = { szOID_COMMON_NAME
,
473 szOID_ORGANIZATIONAL_UNIT_NAME
, szOID_ORGANIZATION_NAME
,
474 szOID_RSA_emailAddr
};
475 CERT_NAME_INFO
*info
= NULL
;
476 PCERT_RDN_ATTR nameAttr
= NULL
;
479 if (CryptDecodeObjectEx(pCertContext
->dwCertEncodingType
, X509_NAME
,
480 name
->pbData
, name
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
,
483 for (i
= 0; !nameAttr
&& i
< sizeof(simpleAttributeOIDs
) /
484 sizeof(simpleAttributeOIDs
[0]); i
++)
485 nameAttr
= CertFindRDNAttr(simpleAttributeOIDs
[i
], info
);
491 PCERT_EXTENSION ext
= CertFindExtension(altNameOID
,
492 pCertContext
->pCertInfo
->cExtension
,
493 pCertContext
->pCertInfo
->rgExtension
);
497 for (i
= 0; !nameAttr
&& i
< sizeof(simpleAttributeOIDs
) /
498 sizeof(simpleAttributeOIDs
[0]); i
++)
499 nameAttr
= CertFindRDNAttr(simpleAttributeOIDs
[i
], info
);
502 /* FIXME: gotta then look for a rfc822Name choice in ext.
503 * Failing that, look for the first attribute.
505 FIXME("CERT_NAME_SIMPLE_DISPLAY_TYPE: stub\n");
510 ret
= CertRDNValueToStrW(nameAttr
->dwValueType
, &nameAttr
->Value
,
511 pszNameString
, cchNameString
);
516 case CERT_NAME_FRIENDLY_DISPLAY_TYPE
:
518 DWORD cch
= cchNameString
;
520 if (CertGetCertificateContextProperty(pCertContext
,
521 CERT_FRIENDLY_NAME_PROP_ID
, pszNameString
, &cch
))
524 ret
= CertGetNameStringW(pCertContext
,
525 CERT_NAME_SIMPLE_DISPLAY_TYPE
, dwFlags
, pvTypePara
, pszNameString
,
530 FIXME("unimplemented for type %ld\n", dwType
);