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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
);