[PATCH v2 7/7] crypt32: Reimplement CertNameToStrA() on top of CertNameToStrW().
Paul Gofman
pgofman at codeweavers.com
Thu Apr 14 12:57:08 CDT 2022
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/crypt32/str.c | 250 ++++-----------------------------------
dlls/crypt32/tests/str.c | 107 ++++++++---------
2 files changed, 72 insertions(+), 285 deletions(-)
diff --git a/dlls/crypt32/str.c b/dlls/crypt32/str.c
index 29882ab771e..2c667542dc8 100644
--- a/dlls/crypt32/str.c
+++ b/dlls/crypt32/str.c
@@ -141,115 +141,6 @@ static inline BOOL is_quotable_char(WCHAR c)
}
}
-static DWORD quote_rdn_value_to_str_a(DWORD dwValueType,
- PCERT_RDN_VALUE_BLOB pValue, LPSTR psz, DWORD csz)
-{
- DWORD ret = 0, len, i;
- BOOL needsQuotes = FALSE;
-
- TRACE("(%ld, %p, %p, %ld)\n", dwValueType, pValue, psz, csz);
-
- switch (dwValueType)
- {
- case CERT_RDN_ANY_TYPE:
- break;
- case CERT_RDN_NUMERIC_STRING:
- case CERT_RDN_PRINTABLE_STRING:
- case CERT_RDN_TELETEX_STRING:
- case CERT_RDN_VIDEOTEX_STRING:
- case CERT_RDN_IA5_STRING:
- case CERT_RDN_GRAPHIC_STRING:
- case CERT_RDN_VISIBLE_STRING:
- case CERT_RDN_GENERAL_STRING:
- len = pValue->cbData;
- if (pValue->cbData && isspace(pValue->pbData[0]))
- needsQuotes = TRUE;
- if (pValue->cbData && isspace(pValue->pbData[pValue->cbData - 1]))
- needsQuotes = TRUE;
- for (i = 0; i < pValue->cbData; i++)
- {
- if (is_quotable_char(pValue->pbData[i]))
- needsQuotes = TRUE;
- if (pValue->pbData[i] == '"')
- len += 1;
- }
- if (needsQuotes)
- len += 2;
- if (!psz || !csz)
- ret = len;
- else
- {
- char *ptr = psz;
-
- if (needsQuotes)
- *ptr++ = '"';
- for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++)
- {
- *ptr = pValue->pbData[i];
- if (pValue->pbData[i] == '"' && ptr - psz < csz - 1)
- *(++ptr) = '"';
- }
- if (needsQuotes && ptr - psz < csz)
- *ptr++ = '"';
- ret = ptr - psz;
- }
- break;
- case CERT_RDN_BMP_STRING:
- case CERT_RDN_UTF8_STRING:
- len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData,
- pValue->cbData / sizeof(WCHAR), NULL, 0, NULL, NULL);
- if (pValue->cbData && iswspace(((LPCWSTR)pValue->pbData)[0]))
- needsQuotes = TRUE;
- if (pValue->cbData &&
- iswspace(((LPCWSTR)pValue->pbData)[pValue->cbData / sizeof(WCHAR)-1]))
- needsQuotes = TRUE;
- for (i = 0; i < pValue->cbData / sizeof(WCHAR); i++)
- {
- if (is_quotable_char(((LPCWSTR)pValue->pbData)[i]))
- needsQuotes = TRUE;
- if (((LPCWSTR)pValue->pbData)[i] == '"')
- len += 1;
- }
- if (needsQuotes)
- len += 2;
- if (!psz || !csz)
- ret = len;
- else
- {
- char *dst = psz;
-
- if (needsQuotes)
- *dst++ = '"';
- for (i = 0; i < pValue->cbData / sizeof(WCHAR) &&
- dst - psz < csz; dst++, i++)
- {
- LPCWSTR src = (LPCWSTR)pValue->pbData + i;
-
- WideCharToMultiByte(CP_ACP, 0, src, 1, dst,
- csz - (dst - psz) - 1, NULL, NULL);
- if (*src == '"' && dst - psz < csz - 1)
- *(++dst) = '"';
- }
- if (needsQuotes && dst - psz < csz)
- *dst++ = '"';
- ret = dst - psz;
- }
- break;
- default:
- FIXME("string type %ld unimplemented\n", dwValueType);
- }
- if (psz && csz)
- {
- *(psz + ret) = '\0';
- csz--;
- ret++;
- }
- else
- ret++;
- TRACE("returning %ld (%s)\n", ret, debugstr_a(psz));
- return ret;
-}
-
static DWORD quote_rdn_value_to_str_w(DWORD dwValueType,
PCERT_RDN_VALUE_BLOB pValue, LPWSTR psz, DWORD csz)
{
@@ -345,136 +236,37 @@ static DWORD quote_rdn_value_to_str_w(DWORD dwValueType,
return ret;
}
-/* Adds the prefix prefix to the string pointed to by psz, followed by the
- * character '='. Copies no more than csz characters. Returns the number of
- * characters copied. If psz is NULL, returns the number of characters that
- * would be copied.
- */
-static DWORD CRYPT_AddPrefixA(LPCSTR prefix, LPSTR psz, DWORD csz)
+DWORD WINAPI CertNameToStrA(DWORD encoding_type, PCERT_NAME_BLOB name_blob, DWORD str_type, LPSTR str, DWORD str_len)
{
- DWORD chars;
+ DWORD len, len_mb, ret;
+ LPWSTR strW;
- TRACE("(%s, %p, %ld)\n", debugstr_a(prefix), psz, csz);
+ TRACE("(%ld, %p, %08lx, %p, %ld)\n", encoding_type, name_blob, str_type, str, str_len);
- if (psz)
+ len = CertNameToStrW(encoding_type, name_blob, str_type, NULL, 0);
+
+ if (!(strW = CryptMemAlloc(len * sizeof(*strW))))
{
- chars = min(strlen(prefix), csz);
- memcpy(psz, prefix, chars);
- *(psz + chars) = '=';
- chars++;
+ ERR("No memory.\n");
+ if (str && str_len) *str = 0;
+ return 1;
}
- else
- chars = lstrlenA(prefix) + 1;
- return chars;
-}
-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_ENABLE_T61_UNICODE_FLAG;
- static const char commaSep[] = ", ";
- static const char semiSep[] = "; ";
- static const char crlfSep[] = "\r\n";
- static const char plusSep[] = " + ";
- static const char spaceSep[] = " ";
- DWORD ret = 0, bytes = 0;
- BOOL bRet;
- CERT_NAME_INFO *info;
-
- TRACE("(%ld, %p, %08lx, %p, %ld)\n", dwCertEncodingType, pName, dwStrType,
- psz, csz);
- if (dwStrType & unsupportedFlags)
- FIXME("unsupported flags: %08lx\n", dwStrType & unsupportedFlags);
-
- bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
- pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
- if (bRet)
+ len = CertNameToStrW(encoding_type, name_blob, str_type, strW, len);
+ len_mb = WideCharToMultiByte(CP_ACP, 0, strW, len, NULL, 0, NULL, NULL);
+ if (!str || !str_len)
{
- 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;
- else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
- sep = crlfSep;
- else
- sep = commaSep;
- sepLen = strlen(sep);
- if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
- rdnSep = spaceSep;
- else
- rdnSep = plusSep;
- rdnSepLen = strlen(rdnSep);
- for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
- {
- for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++)
- {
- DWORD chars;
- char prefixBuf[13]; /* big enough for SERIALNUMBER */
- LPCSTR prefix = NULL;
-
- if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
- prefix = rdn->rgRDNAttr[j].pszObjId;
- else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
- {
- PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
- CRYPT_OID_INFO_OID_KEY,
- rdn->rgRDNAttr[j].pszObjId,
- CRYPT_RDN_ATTR_OID_GROUP_ID);
-
- if (oidInfo)
- {
- WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1,
- prefixBuf, sizeof(prefixBuf), NULL, NULL);
- prefix = prefixBuf;
- }
- else
- prefix = rdn->rgRDNAttr[j].pszObjId;
- }
- if (prefix)
- {
- /* - 1 is needed to account for the NULL terminator. */
- chars = CRYPT_AddPrefixA(prefix,
- psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
- ret += chars;
- }
- chars = quote_rdn_value_to_str_a(
- rdn->rgRDNAttr[j].dwValueType,
- &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL,
- psz ? csz - ret : 0);
- if (chars)
- ret += chars - 1;
- if (j < rdn->cRDNAttr - 1)
- {
- if (psz && ret < csz - rdnSepLen - 1)
- memcpy(psz + ret, rdnSep, rdnSepLen);
- ret += rdnSepLen;
- }
- }
- if (i < info->cRDN - 1)
- {
- if (psz && ret < csz - sepLen - 1)
- memcpy(psz + ret, sep, sepLen);
- ret += sepLen;
- }
- if(reverse) rdn--;
- else rdn++;
- }
- LocalFree(info);
+ CryptMemFree(strW);
+ return len_mb;
}
- if (psz && csz)
+
+ ret = WideCharToMultiByte(CP_ACP, 0, strW, len, str, str_len, NULL, NULL);
+ if (ret < len_mb)
{
- *(psz + ret) = '\0';
- ret++;
+ str[0] = 0;
+ ret = 1;
}
- else
- ret++;
- TRACE("Returning %s\n", debugstr_a(psz));
+ CryptMemFree(strW);
return ret;
}
diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c
index 41ae96d4c4e..057146df19b 100644
--- a/dlls/crypt32/tests/str.c
+++ b/dlls/crypt32/tests/str.c
@@ -276,24 +276,27 @@ static void test_CertRDNValueToStrW(void)
wine_dbgstr_w(ePKIW), wine_dbgstr_w(buffer));
}
-static void test_NameToStrConversionA(PCERT_NAME_BLOB pName, DWORD dwStrType,
- LPCSTR expected, BOOL todo)
+#define test_NameToStrConversionA(a, b, c) test_NameToStrConversionA_(__LINE__, a, b, c)
+static void test_NameToStrConversionA_(unsigned int line, PCERT_NAME_BLOB pName, DWORD dwStrType, LPCSTR expected)
{
- char buffer[2000] = { 0 };
- DWORD i;
-
- i = CertNameToStrA(X509_ASN_ENCODING, pName, dwStrType, NULL, 0);
- todo_wine_if (todo)
- ok(i == strlen(expected) + 1, "Expected %d chars, got %ld\n",
- lstrlenA(expected) + 1, i);
- i = CertNameToStrA(X509_ASN_ENCODING,pName, dwStrType, buffer,
- sizeof(buffer));
- todo_wine_if (todo)
- ok(i == strlen(expected) + 1, "Expected %d chars, got %ld\n",
- lstrlenA(expected) + 1, i);
- todo_wine_if (todo)
- ok(!strcmp(buffer, expected), "Expected %s, got %s\n", expected,
- buffer);
+ char buffer[2000];
+ DWORD len, retlen;
+
+ len = CertNameToStrA(X509_ASN_ENCODING, pName, dwStrType, NULL, 0);
+ ok(len == strlen(expected) + 1, "line %u: Expected %d chars, got %ld.\n", line, lstrlenA(expected) + 1, len);
+ len = CertNameToStrA(X509_ASN_ENCODING,pName, dwStrType, buffer, sizeof(buffer));
+ ok(len == strlen(expected) + 1, "line %u: Expected %d chars, got %ld.\n", line, lstrlenA(expected) + 1, len);
+ ok(!strcmp(buffer, expected), "line %u: Expected %s, got %s.\n", line, expected, buffer);
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ retlen = CertNameToStrA(X509_ASN_ENCODING, pName, dwStrType, buffer, len - 1);
+ ok(retlen == 1, "line %u: expected 1, got %lu\n", line, retlen);
+ ok(!buffer[0], "line %u: string is not zero terminated.\n", line);
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ retlen = CertNameToStrA(X509_ASN_ENCODING, pName, dwStrType, buffer, 0);
+ ok(retlen == len, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen);
+ ok((unsigned char)buffer[0] == 0xcc, "line %u: got %s\n", line, wine_dbgstr_a(buffer));
}
static BYTE encodedSimpleCN[] = {
@@ -366,79 +369,71 @@ static void test_CertNameToStrA(void)
"Expected positive return and ERROR_SUCCESS, got %ld - %08lx\n",
ret, GetLastError());
+ test_NameToStrConversionA(&context->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, issuerStr);
test_NameToStrConversionA(&context->pCertInfo->Issuer,
- CERT_SIMPLE_NAME_STR, issuerStr, FALSE);
- test_NameToStrConversionA(&context->pCertInfo->Issuer,
- CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
- issuerStrSemicolon, FALSE);
+ CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG, issuerStrSemicolon);
test_NameToStrConversionA(&context->pCertInfo->Issuer,
- CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- issuerStrCRLF, FALSE);
+ CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG, issuerStrCRLF);
+ test_NameToStrConversionA(&context->pCertInfo->Subject, CERT_OID_NAME_STR, subjectStr);
test_NameToStrConversionA(&context->pCertInfo->Subject,
- CERT_OID_NAME_STR, subjectStr, FALSE);
+ CERT_OID_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG, subjectStrSemicolon);
test_NameToStrConversionA(&context->pCertInfo->Subject,
- CERT_OID_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
- subjectStrSemicolon, FALSE);
- test_NameToStrConversionA(&context->pCertInfo->Subject,
- CERT_OID_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- subjectStrCRLF, FALSE);
+ CERT_OID_NAME_STR | CERT_NAME_STR_CRLF_FLAG, subjectStrCRLF);
test_NameToStrConversionA(&context->pCertInfo->Subject,
- CERT_X500_NAME_STR, x500SubjectStr, FALSE);
+ 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, FALSE);
+ x500SubjectStrSemicolonReverse);
CertFreeCertificateContext(context);
}
blob.pbData = encodedSimpleCN;
blob.cbData = sizeof(encodedSimpleCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=1", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=1");
blob.pbData = encodedSingleQuotedCN;
blob.cbData = sizeof(encodedSingleQuotedCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN='1'", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "'1'", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN='1'");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "'1'");
blob.pbData = encodedSpacedCN;
blob.cbData = sizeof(encodedSpacedCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\" 1 \"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\" 1 \"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\" 1 \"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\" 1 \"");
blob.pbData = encodedQuotedCN;
blob.cbData = sizeof(encodedQuotedCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"\"\"1\"\"\"",
- FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"\"\"1\"\"\"",
- FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"\"\"1\"\"\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"\"\"1\"\"\"");
blob.pbData = encodedMultipleAttrCN;
blob.cbData = sizeof(encodedMultipleAttrCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"1+2\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"1+2\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"1+2\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"1+2\"");
blob.pbData = encodedCommaCN;
blob.cbData = sizeof(encodedCommaCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"a,b\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a,b\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"a,b\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a,b\"");
blob.pbData = encodedEqualCN;
blob.cbData = sizeof(encodedEqualCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"a=b\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a=b\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"a=b\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a=b\"");
blob.pbData = encodedLessThanCN;
blob.cbData = sizeof(encodedLessThanCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"<\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"<\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"<\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"<\"");
blob.pbData = encodedGreaterThanCN;
blob.cbData = sizeof(encodedGreaterThanCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\">\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\">\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\">\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\">\"");
blob.pbData = encodedHashCN;
blob.cbData = sizeof(encodedHashCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"#\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"#\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"#\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"#\"");
blob.pbData = encodedSemiCN;
blob.cbData = sizeof(encodedSemiCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\";\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\";\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\";\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\";\"");
blob.pbData = encodedNewlineCN;
blob.cbData = sizeof(encodedNewlineCN);
- test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"a\nb\"", FALSE);
- test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a\nb\"", FALSE);
+ test_NameToStrConversionA(&blob, CERT_X500_NAME_STR, "CN=\"a\nb\"");
+ test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a\nb\"");
}
#define test_NameToStrConversionW(a, b, c) test_NameToStrConversionW_(__LINE__, a, b, c)
--
2.35.1
More information about the wine-devel
mailing list