diff --git a/dlls/crypt32/str.c b/dlls/crypt32/str.c index d574790f052..7a739a87e96 100644 --- a/dlls/crypt32/str.c +++ b/dlls/crypt32/str.c @@ -181,7 +181,7 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, DWORD dwStrType, LPSTR psz, DWORD csz) { static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG | - CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; + CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; static const char commaSep[] = ", "; static const char semiSep[] = "; "; static const char crlfSep[] = "\r\n"; @@ -202,6 +202,10 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, { DWORD i, j, sepLen, rdnSepLen; LPCSTR sep, rdnSep; + BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG; + const CERT_RDN *rdn = info->rgRDN; + + if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1); if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG) sep = semiSep; @@ -217,19 +221,19 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, rdnSepLen = strlen(rdnSep); for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++) { - for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++) + for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++) { DWORD chars; char prefixBuf[10]; /* big enough for GivenName */ LPCSTR prefix = NULL; if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR) - prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId; + prefix = rdn->rgRDNAttr[j].pszObjId; else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) { PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, - info->rgRDN[i].rgRDNAttr[j].pszObjId, + rdn->rgRDNAttr[j].pszObjId, CRYPT_RDN_ATTR_OID_GROUP_ID); if (oidInfo) @@ -239,7 +243,7 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, prefix = prefixBuf; } else - prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId; + prefix = rdn->rgRDNAttr[j].pszObjId; } if (prefix) { @@ -250,12 +254,12 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, } /* FIXME: handle quoting */ chars = CertRDNValueToStrA( - info->rgRDN[i].rgRDNAttr[j].dwValueType, - &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL, + rdn->rgRDNAttr[j].dwValueType, + &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, psz ? csz - ret : 0); if (chars) ret += chars - 1; - if (j < info->rgRDN[i].cRDNAttr - 1) + if (j < rdn->cRDNAttr - 1) { if (psz && ret < csz - rdnSepLen - 1) memcpy(psz + ret, rdnSep, rdnSepLen); @@ -268,6 +272,8 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, memcpy(psz + ret, sep, sepLen); ret += sepLen; } + if(reverse) rdn--; + else rdn++; } LocalFree(info); } @@ -336,7 +342,7 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, DWORD dwStrType, LPWSTR psz, DWORD csz) { static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG | - CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; + CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; static const WCHAR commaSep[] = { ',',' ',0 }; static const WCHAR semiSep[] = { ';',' ',0 }; static const WCHAR crlfSep[] = { '\r','\n',0 }; @@ -357,6 +363,10 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, { DWORD i, j, sepLen, rdnSepLen; LPCWSTR sep, rdnSep; + BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG; + const CERT_RDN *rdn = info->rgRDN; + + if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1); if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG) sep = semiSep; @@ -372,25 +382,25 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, rdnSepLen = lstrlenW(rdnSep); for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++) { - for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++) + for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++) { DWORD chars; LPCSTR prefixA = NULL; LPCWSTR prefixW = NULL; if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR) - prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId; + prefixA = rdn->rgRDNAttr[j].pszObjId; else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) { PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, - info->rgRDN[i].rgRDNAttr[j].pszObjId, + rdn->rgRDNAttr[j].pszObjId, CRYPT_RDN_ATTR_OID_GROUP_ID); if (oidInfo) prefixW = oidInfo->pwszName; else - prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId; + prefixA = rdn->rgRDNAttr[j].pszObjId; } if (prefixW) { @@ -408,12 +418,12 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, } /* FIXME: handle quoting */ chars = CertRDNValueToStrW( - info->rgRDN[i].rgRDNAttr[j].dwValueType, - &info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL, + rdn->rgRDNAttr[j].dwValueType, + &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, psz ? csz - ret : 0); if (chars) ret += chars - 1; - if (j < info->rgRDN[i].cRDNAttr - 1) + if (j < rdn->cRDNAttr - 1) { if (psz && ret < csz - rdnSepLen - 1) memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR)); @@ -426,6 +436,8 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, memcpy(psz + ret, sep, sepLen * sizeof(WCHAR)); ret += sepLen; } + if(reverse) rdn--; + else rdn++; } LocalFree(info); } diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c index e4cdb77a3aa..5b2e0253e95 100644 --- a/dlls/crypt32/tests/str.c +++ b/dlls/crypt32/tests/str.c @@ -119,6 +119,7 @@ static char subjectStrSemicolon[] = static char subjectStrCRLF[] = "2.5.4.6=US\r\n2.5.4.8=Minnesota\r\n2.5.4.7=Minneapolis\r\n2.5.4.10=CodeWeavers\r\n2.5.4.11=Wine Development\r\n2.5.4.3=localhost\r\n1.2.840.113549.1.9.1=aric@codeweavers.com"; static char x500SubjectStr[] = "C=US, S=Minnesota, L=Minneapolis, O=CodeWeavers, OU=Wine Development, CN=localhost, E=aric@codeweavers.com"; +static char x500SubjectStrSemicolonReverse[] = "E=aric@codeweavers.com; CN=localhost; OU=Wine Development; O=CodeWeavers; L=Minneapolis; S=Minnesota; C=US"; static WCHAR issuerStrW[] = { 'U','S',',',' ','M','i','n','n','e','s','o','t','a',',',' ','M','i','n','n', 'e','a','p','o','l','i','s',',',' ','C','o','d','e','W','e','a','v','e','r', @@ -167,6 +168,13 @@ static WCHAR subjectStrCRLFW[] = { 'h','o','s','t','\r','\n','1','.','2','.','8','4','0','.','1','1','3','5','4', '9','.','1','.','9','.','1','=','a','r','i','c','@','c','o','d','e','w','e', 'a','v','e','r','s','.','c','o','m',0 }; +static WCHAR x500SubjectStrSemicolonReverseW[] = { + 'E','=','a','r','i','c','@','c','o','d','e','w','e','a','v','e','r','s','.','c', + 'o','m',';',' ','C','N','=','l','o','c','a','l','h','o','s','t',';',' ','O','U', + '=','W','i','n','e',' ','D','e','v','e','l','o','p','m','e','n','t',';',' ','O', + '=','C','o','d','e','W','e','a','v','e','r','s',';',' ','L','=','M','i','n','n', + 'e','a','p','o','l','i','s',';',' ','S','=','M','i','n','n','e','s','o','t','a', + ';',' ','C','=','U','S',0 }; typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *, DWORD, DWORD, void *, DWORD *); @@ -371,6 +379,8 @@ static void test_CertNameToStrA(void) subjectStrCRLF); test_NameToStrConversionA(&context->pCertInfo->Subject, CERT_X500_NAME_STR, x500SubjectStr); + test_NameToStrConversionA(&context->pCertInfo->Subject, + CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG | CERT_NAME_STR_REVERSE_FLAG, x500SubjectStrSemicolonReverse); CertFreeCertificateContext(context); } @@ -446,6 +456,8 @@ static void test_CertNameToStrW(void) test_NameToStrConversionW(&context->pCertInfo->Subject, CERT_OID_NAME_STR | CERT_NAME_STR_CRLF_FLAG, subjectStrCRLFW); + test_NameToStrConversionW(&context->pCertInfo->Subject, + CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG | CERT_NAME_STR_REVERSE_FLAG, x500SubjectStrSemicolonReverseW); CertFreeCertificateContext(context); }