Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstr.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2006 Juan Lang for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 #include <stdarg.h> 00019 00020 #define NONAMELESSUNION 00021 00022 #include "windef.h" 00023 #include "winbase.h" 00024 #include "winnls.h" 00025 #include "winuser.h" 00026 #include "wincrypt.h" 00027 #include "wine/debug.h" 00028 #include "wine/unicode.h" 00029 00030 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00031 00032 DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, 00033 LPSTR psz, DWORD csz) 00034 { 00035 DWORD ret = 0, len; 00036 00037 TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz); 00038 00039 switch (dwValueType) 00040 { 00041 case CERT_RDN_ANY_TYPE: 00042 break; 00043 case CERT_RDN_NUMERIC_STRING: 00044 case CERT_RDN_PRINTABLE_STRING: 00045 case CERT_RDN_TELETEX_STRING: 00046 case CERT_RDN_VIDEOTEX_STRING: 00047 case CERT_RDN_IA5_STRING: 00048 case CERT_RDN_GRAPHIC_STRING: 00049 case CERT_RDN_VISIBLE_STRING: 00050 case CERT_RDN_GENERAL_STRING: 00051 len = pValue->cbData; 00052 if (!psz || !csz) 00053 ret = len; 00054 else 00055 { 00056 DWORD chars = min(len, csz - 1); 00057 00058 if (chars) 00059 { 00060 memcpy(psz, pValue->pbData, chars); 00061 ret += chars; 00062 csz -= chars; 00063 } 00064 } 00065 break; 00066 case CERT_RDN_BMP_STRING: 00067 case CERT_RDN_UTF8_STRING: 00068 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData, 00069 pValue->cbData / sizeof(WCHAR), NULL, 0, NULL, NULL); 00070 if (!psz || !csz) 00071 ret = len; 00072 else 00073 { 00074 DWORD chars = min(pValue->cbData / sizeof(WCHAR), csz - 1); 00075 00076 if (chars) 00077 { 00078 ret = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData, 00079 chars, psz, csz - 1, NULL, NULL); 00080 csz -= ret; 00081 } 00082 } 00083 break; 00084 default: 00085 FIXME("string type %d unimplemented\n", dwValueType); 00086 } 00087 if (psz && csz) 00088 { 00089 *(psz + ret) = '\0'; 00090 csz--; 00091 ret++; 00092 } 00093 else 00094 ret++; 00095 TRACE("returning %d (%s)\n", ret, debugstr_a(psz)); 00096 return ret; 00097 } 00098 00099 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, 00100 LPWSTR psz, DWORD csz) 00101 { 00102 DWORD ret = 0, len, i, strLen; 00103 00104 TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz); 00105 00106 switch (dwValueType) 00107 { 00108 case CERT_RDN_ANY_TYPE: 00109 break; 00110 case CERT_RDN_NUMERIC_STRING: 00111 case CERT_RDN_PRINTABLE_STRING: 00112 case CERT_RDN_TELETEX_STRING: 00113 case CERT_RDN_VIDEOTEX_STRING: 00114 case CERT_RDN_IA5_STRING: 00115 case CERT_RDN_GRAPHIC_STRING: 00116 case CERT_RDN_VISIBLE_STRING: 00117 case CERT_RDN_GENERAL_STRING: 00118 len = pValue->cbData; 00119 if (!psz || !csz) 00120 ret = len; 00121 else 00122 { 00123 WCHAR *ptr = psz; 00124 00125 for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++) 00126 *ptr = pValue->pbData[i]; 00127 ret = ptr - psz; 00128 } 00129 break; 00130 case CERT_RDN_BMP_STRING: 00131 case CERT_RDN_UTF8_STRING: 00132 strLen = len = pValue->cbData / sizeof(WCHAR); 00133 if (!psz || !csz) 00134 ret = len; 00135 else 00136 { 00137 WCHAR *ptr = psz; 00138 00139 for (i = 0; i < strLen && ptr - psz < csz; ptr++, i++) 00140 *ptr = ((LPCWSTR)pValue->pbData)[i]; 00141 ret = ptr - psz; 00142 } 00143 break; 00144 default: 00145 FIXME("string type %d unimplemented\n", dwValueType); 00146 } 00147 if (psz && csz) 00148 { 00149 *(psz + ret) = '\0'; 00150 csz--; 00151 ret++; 00152 } 00153 else 00154 ret++; 00155 TRACE("returning %d (%s)\n", ret, debugstr_w(psz)); 00156 return ret; 00157 } 00158 00159 static inline BOOL is_quotable_char(char c) 00160 { 00161 switch(c) 00162 { 00163 case '+': 00164 case ',': 00165 case '"': 00166 case '=': 00167 case '<': 00168 case '>': 00169 case ';': 00170 case '#': 00171 case '\n': 00172 return TRUE; 00173 default: 00174 return FALSE; 00175 } 00176 } 00177 00178 static DWORD quote_rdn_value_to_str_a(DWORD dwValueType, 00179 PCERT_RDN_VALUE_BLOB pValue, LPSTR psz, DWORD csz) 00180 { 00181 DWORD ret = 0, len, i; 00182 BOOL needsQuotes = FALSE; 00183 00184 TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz); 00185 00186 switch (dwValueType) 00187 { 00188 case CERT_RDN_ANY_TYPE: 00189 break; 00190 case CERT_RDN_NUMERIC_STRING: 00191 case CERT_RDN_PRINTABLE_STRING: 00192 case CERT_RDN_TELETEX_STRING: 00193 case CERT_RDN_VIDEOTEX_STRING: 00194 case CERT_RDN_IA5_STRING: 00195 case CERT_RDN_GRAPHIC_STRING: 00196 case CERT_RDN_VISIBLE_STRING: 00197 case CERT_RDN_GENERAL_STRING: 00198 len = pValue->cbData; 00199 if (pValue->cbData && isspace(pValue->pbData[0])) 00200 needsQuotes = TRUE; 00201 if (pValue->cbData && isspace(pValue->pbData[pValue->cbData - 1])) 00202 needsQuotes = TRUE; 00203 for (i = 0; i < pValue->cbData; i++) 00204 { 00205 if (is_quotable_char(pValue->pbData[i])) 00206 needsQuotes = TRUE; 00207 if (pValue->pbData[i] == '"') 00208 len += 1; 00209 } 00210 if (needsQuotes) 00211 len += 2; 00212 if (!psz || !csz) 00213 ret = len; 00214 else 00215 { 00216 char *ptr = psz; 00217 00218 if (needsQuotes) 00219 *ptr++ = '"'; 00220 for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++) 00221 { 00222 *ptr = pValue->pbData[i]; 00223 if (pValue->pbData[i] == '"' && ptr - psz < csz - 1) 00224 *(++ptr) = '"'; 00225 } 00226 if (needsQuotes && ptr - psz < csz) 00227 *ptr++ = '"'; 00228 ret = ptr - psz; 00229 } 00230 break; 00231 case CERT_RDN_BMP_STRING: 00232 case CERT_RDN_UTF8_STRING: 00233 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData, 00234 pValue->cbData / sizeof(WCHAR), NULL, 0, NULL, NULL); 00235 if (pValue->cbData && isspaceW(((LPCWSTR)pValue->pbData)[0])) 00236 needsQuotes = TRUE; 00237 if (pValue->cbData && 00238 isspaceW(((LPCWSTR)pValue->pbData)[pValue->cbData / sizeof(WCHAR)-1])) 00239 needsQuotes = TRUE; 00240 for (i = 0; i < pValue->cbData / sizeof(WCHAR); i++) 00241 { 00242 if (is_quotable_char(((LPCWSTR)pValue->pbData)[i])) 00243 needsQuotes = TRUE; 00244 if (((LPCWSTR)pValue->pbData)[i] == '"') 00245 len += 1; 00246 } 00247 if (needsQuotes) 00248 len += 2; 00249 if (!psz || !csz) 00250 ret = len; 00251 else 00252 { 00253 char *dst = psz; 00254 00255 if (needsQuotes) 00256 *dst++ = '"'; 00257 for (i = 0; i < pValue->cbData / sizeof(WCHAR) && 00258 dst - psz < csz; dst++, i++) 00259 { 00260 LPCWSTR src = (LPCWSTR)pValue->pbData + i; 00261 00262 WideCharToMultiByte(CP_ACP, 0, src, 1, dst, 00263 csz - (dst - psz) - 1, NULL, NULL); 00264 if (*src == '"' && dst - psz < csz - 1) 00265 *(++dst) = '"'; 00266 } 00267 if (needsQuotes && dst - psz < csz) 00268 *dst++ = '"'; 00269 ret = dst - psz; 00270 } 00271 break; 00272 default: 00273 FIXME("string type %d unimplemented\n", dwValueType); 00274 } 00275 if (psz && csz) 00276 { 00277 *(psz + ret) = '\0'; 00278 csz--; 00279 ret++; 00280 } 00281 else 00282 ret++; 00283 TRACE("returning %d (%s)\n", ret, debugstr_a(psz)); 00284 return ret; 00285 } 00286 00287 static DWORD quote_rdn_value_to_str_w(DWORD dwValueType, 00288 PCERT_RDN_VALUE_BLOB pValue, LPWSTR psz, DWORD csz) 00289 { 00290 DWORD ret = 0, len, i, strLen; 00291 BOOL needsQuotes = FALSE; 00292 00293 TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz); 00294 00295 switch (dwValueType) 00296 { 00297 case CERT_RDN_ANY_TYPE: 00298 break; 00299 case CERT_RDN_NUMERIC_STRING: 00300 case CERT_RDN_PRINTABLE_STRING: 00301 case CERT_RDN_TELETEX_STRING: 00302 case CERT_RDN_VIDEOTEX_STRING: 00303 case CERT_RDN_IA5_STRING: 00304 case CERT_RDN_GRAPHIC_STRING: 00305 case CERT_RDN_VISIBLE_STRING: 00306 case CERT_RDN_GENERAL_STRING: 00307 len = pValue->cbData; 00308 if (pValue->cbData && isspace(pValue->pbData[0])) 00309 needsQuotes = TRUE; 00310 if (pValue->cbData && isspace(pValue->pbData[pValue->cbData - 1])) 00311 needsQuotes = TRUE; 00312 for (i = 0; i < pValue->cbData; i++) 00313 { 00314 if (is_quotable_char(pValue->pbData[i])) 00315 needsQuotes = TRUE; 00316 if (pValue->pbData[i] == '"') 00317 len += 1; 00318 } 00319 if (needsQuotes) 00320 len += 2; 00321 if (!psz || !csz) 00322 ret = len; 00323 else 00324 { 00325 WCHAR *ptr = psz; 00326 00327 if (needsQuotes) 00328 *ptr++ = '"'; 00329 for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++) 00330 { 00331 *ptr = pValue->pbData[i]; 00332 if (pValue->pbData[i] == '"' && ptr - psz < csz - 1) 00333 *(++ptr) = '"'; 00334 } 00335 if (needsQuotes && ptr - psz < csz) 00336 *ptr++ = '"'; 00337 ret = ptr - psz; 00338 } 00339 break; 00340 case CERT_RDN_BMP_STRING: 00341 case CERT_RDN_UTF8_STRING: 00342 strLen = len = pValue->cbData / sizeof(WCHAR); 00343 if (pValue->cbData && isspace(pValue->pbData[0])) 00344 needsQuotes = TRUE; 00345 if (pValue->cbData && isspace(pValue->pbData[strLen - 1])) 00346 needsQuotes = TRUE; 00347 for (i = 0; i < strLen; i++) 00348 { 00349 if (is_quotable_char(((LPCWSTR)pValue->pbData)[i])) 00350 needsQuotes = TRUE; 00351 if (((LPCWSTR)pValue->pbData)[i] == '"') 00352 len += 1; 00353 } 00354 if (needsQuotes) 00355 len += 2; 00356 if (!psz || !csz) 00357 ret = len; 00358 else 00359 { 00360 WCHAR *ptr = psz; 00361 00362 if (needsQuotes) 00363 *ptr++ = '"'; 00364 for (i = 0; i < strLen && ptr - psz < csz; ptr++, i++) 00365 { 00366 *ptr = ((LPCWSTR)pValue->pbData)[i]; 00367 if (((LPCWSTR)pValue->pbData)[i] == '"' && ptr - psz < csz - 1) 00368 *(++ptr) = '"'; 00369 } 00370 if (needsQuotes && ptr - psz < csz) 00371 *ptr++ = '"'; 00372 ret = ptr - psz; 00373 } 00374 break; 00375 default: 00376 FIXME("string type %d unimplemented\n", dwValueType); 00377 } 00378 if (psz && csz) 00379 { 00380 *(psz + ret) = '\0'; 00381 csz--; 00382 ret++; 00383 } 00384 else 00385 ret++; 00386 TRACE("returning %d (%s)\n", ret, debugstr_w(psz)); 00387 return ret; 00388 } 00389 00390 /* Adds the prefix prefix to the string pointed to by psz, followed by the 00391 * character '='. Copies no more than csz characters. Returns the number of 00392 * characters copied. If psz is NULL, returns the number of characters that 00393 * would be copied. 00394 */ 00395 static DWORD CRYPT_AddPrefixA(LPCSTR prefix, LPSTR psz, DWORD csz) 00396 { 00397 DWORD chars; 00398 00399 TRACE("(%s, %p, %d)\n", debugstr_a(prefix), psz, csz); 00400 00401 if (psz) 00402 { 00403 chars = min(strlen(prefix), csz); 00404 memcpy(psz, prefix, chars); 00405 *(psz + chars) = '='; 00406 chars++; 00407 } 00408 else 00409 chars = lstrlenA(prefix) + 1; 00410 return chars; 00411 } 00412 00413 DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, 00414 DWORD dwStrType, LPSTR psz, DWORD csz) 00415 { 00416 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG | 00417 CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; 00418 static const char commaSep[] = ", "; 00419 static const char semiSep[] = "; "; 00420 static const char crlfSep[] = "\r\n"; 00421 static const char plusSep[] = " + "; 00422 static const char spaceSep[] = " "; 00423 DWORD ret = 0, bytes = 0; 00424 BOOL bRet; 00425 CERT_NAME_INFO *info; 00426 00427 TRACE("(%d, %p, %08x, %p, %d)\n", dwCertEncodingType, pName, dwStrType, 00428 psz, csz); 00429 if (dwStrType & unsupportedFlags) 00430 FIXME("unsupported flags: %08x\n", dwStrType & unsupportedFlags); 00431 00432 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData, 00433 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes); 00434 if (bRet) 00435 { 00436 DWORD i, j, sepLen, rdnSepLen; 00437 LPCSTR sep, rdnSep; 00438 BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG; 00439 const CERT_RDN *rdn = info->rgRDN; 00440 00441 if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1); 00442 00443 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG) 00444 sep = semiSep; 00445 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG) 00446 sep = crlfSep; 00447 else 00448 sep = commaSep; 00449 sepLen = strlen(sep); 00450 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG) 00451 rdnSep = spaceSep; 00452 else 00453 rdnSep = plusSep; 00454 rdnSepLen = strlen(rdnSep); 00455 for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++) 00456 { 00457 for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++) 00458 { 00459 DWORD chars; 00460 char prefixBuf[10]; /* big enough for GivenName */ 00461 LPCSTR prefix = NULL; 00462 00463 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR) 00464 prefix = rdn->rgRDNAttr[j].pszObjId; 00465 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) 00466 { 00467 PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo( 00468 CRYPT_OID_INFO_OID_KEY, 00469 rdn->rgRDNAttr[j].pszObjId, 00470 CRYPT_RDN_ATTR_OID_GROUP_ID); 00471 00472 if (oidInfo) 00473 { 00474 WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1, 00475 prefixBuf, sizeof(prefixBuf), NULL, NULL); 00476 prefix = prefixBuf; 00477 } 00478 else 00479 prefix = rdn->rgRDNAttr[j].pszObjId; 00480 } 00481 if (prefix) 00482 { 00483 /* - 1 is needed to account for the NULL terminator. */ 00484 chars = CRYPT_AddPrefixA(prefix, 00485 psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); 00486 ret += chars; 00487 } 00488 chars = quote_rdn_value_to_str_a( 00489 rdn->rgRDNAttr[j].dwValueType, 00490 &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, 00491 psz ? csz - ret : 0); 00492 if (chars) 00493 ret += chars - 1; 00494 if (j < rdn->cRDNAttr - 1) 00495 { 00496 if (psz && ret < csz - rdnSepLen - 1) 00497 memcpy(psz + ret, rdnSep, rdnSepLen); 00498 ret += rdnSepLen; 00499 } 00500 } 00501 if (i < info->cRDN - 1) 00502 { 00503 if (psz && ret < csz - sepLen - 1) 00504 memcpy(psz + ret, sep, sepLen); 00505 ret += sepLen; 00506 } 00507 if(reverse) rdn--; 00508 else rdn++; 00509 } 00510 LocalFree(info); 00511 } 00512 if (psz && csz) 00513 { 00514 *(psz + ret) = '\0'; 00515 ret++; 00516 } 00517 else 00518 ret++; 00519 TRACE("Returning %s\n", debugstr_a(psz)); 00520 return ret; 00521 } 00522 00523 /* Adds the prefix prefix to the wide-character string pointed to by psz, 00524 * followed by the character '='. Copies no more than csz characters. Returns 00525 * the number of characters copied. If psz is NULL, returns the number of 00526 * characters that would be copied. 00527 * Assumes the characters in prefix are ASCII (not multibyte characters.) 00528 */ 00529 static DWORD CRYPT_AddPrefixAToW(LPCSTR prefix, LPWSTR psz, DWORD csz) 00530 { 00531 DWORD chars; 00532 00533 TRACE("(%s, %p, %d)\n", debugstr_a(prefix), psz, csz); 00534 00535 if (psz) 00536 { 00537 DWORD i; 00538 00539 chars = min(strlen(prefix), csz); 00540 for (i = 0; i < chars; i++) 00541 *(psz + i) = prefix[i]; 00542 *(psz + chars) = '='; 00543 chars++; 00544 } 00545 else 00546 chars = lstrlenA(prefix) + 1; 00547 return chars; 00548 } 00549 00550 /* Adds the prefix prefix to the string pointed to by psz, followed by the 00551 * character '='. Copies no more than csz characters. Returns the number of 00552 * characters copied. If psz is NULL, returns the number of characters that 00553 * would be copied. 00554 */ 00555 static DWORD CRYPT_AddPrefixW(LPCWSTR prefix, LPWSTR psz, DWORD csz) 00556 { 00557 DWORD chars; 00558 00559 TRACE("(%s, %p, %d)\n", debugstr_w(prefix), psz, csz); 00560 00561 if (psz) 00562 { 00563 chars = min(strlenW(prefix), csz); 00564 memcpy(psz, prefix, chars * sizeof(WCHAR)); 00565 *(psz + chars) = '='; 00566 chars++; 00567 } 00568 else 00569 chars = lstrlenW(prefix) + 1; 00570 return chars; 00571 } 00572 00573 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 }; 00574 00575 DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indentLevel, 00576 const CERT_NAME_BLOB *pName, DWORD dwStrType, LPWSTR psz, DWORD csz) 00577 { 00578 static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG | 00579 CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG; 00580 static const WCHAR commaSep[] = { ',',' ',0 }; 00581 static const WCHAR semiSep[] = { ';',' ',0 }; 00582 static const WCHAR crlfSep[] = { '\r','\n',0 }; 00583 static const WCHAR plusSep[] = { ' ','+',' ',0 }; 00584 static const WCHAR spaceSep[] = { ' ',0 }; 00585 DWORD ret = 0, bytes = 0; 00586 BOOL bRet; 00587 CERT_NAME_INFO *info; 00588 00589 if (dwStrType & unsupportedFlags) 00590 FIXME("unsupported flags: %08x\n", dwStrType & unsupportedFlags); 00591 00592 bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData, 00593 pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes); 00594 if (bRet) 00595 { 00596 DWORD i, j, sepLen, rdnSepLen; 00597 LPCWSTR sep, rdnSep; 00598 BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG; 00599 const CERT_RDN *rdn = info->rgRDN; 00600 00601 if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1); 00602 00603 if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG) 00604 sep = semiSep; 00605 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG) 00606 sep = crlfSep; 00607 else 00608 sep = commaSep; 00609 sepLen = lstrlenW(sep); 00610 if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG) 00611 rdnSep = spaceSep; 00612 else 00613 rdnSep = plusSep; 00614 rdnSepLen = lstrlenW(rdnSep); 00615 for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++) 00616 { 00617 for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++) 00618 { 00619 DWORD chars; 00620 LPCSTR prefixA = NULL; 00621 LPCWSTR prefixW = NULL; 00622 00623 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR) 00624 prefixA = rdn->rgRDNAttr[j].pszObjId; 00625 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) 00626 { 00627 PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo( 00628 CRYPT_OID_INFO_OID_KEY, 00629 rdn->rgRDNAttr[j].pszObjId, 00630 CRYPT_RDN_ATTR_OID_GROUP_ID); 00631 00632 if (oidInfo) 00633 prefixW = oidInfo->pwszName; 00634 else 00635 prefixA = rdn->rgRDNAttr[j].pszObjId; 00636 } 00637 if (dwStrType & CERT_NAME_STR_CRLF_FLAG) 00638 { 00639 DWORD k; 00640 00641 for (k = 0; k < indentLevel; k++) 00642 { 00643 if (psz) 00644 { 00645 chars = min(strlenW(indent), csz - ret - 1); 00646 memcpy(psz + ret, indent, chars * sizeof(WCHAR)); 00647 } 00648 else 00649 chars = strlenW(indent); 00650 ret += chars; 00651 } 00652 } 00653 if (prefixW) 00654 { 00655 /* - 1 is needed to account for the NULL terminator. */ 00656 chars = CRYPT_AddPrefixW(prefixW, 00657 psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); 00658 ret += chars; 00659 } 00660 else if (prefixA) 00661 { 00662 /* - 1 is needed to account for the NULL terminator. */ 00663 chars = CRYPT_AddPrefixAToW(prefixA, 00664 psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); 00665 ret += chars; 00666 } 00667 chars = quote_rdn_value_to_str_w( 00668 rdn->rgRDNAttr[j].dwValueType, 00669 &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, 00670 psz ? csz - ret : 0); 00671 if (chars) 00672 ret += chars - 1; 00673 if (j < rdn->cRDNAttr - 1) 00674 { 00675 if (psz && ret < csz - rdnSepLen - 1) 00676 memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR)); 00677 ret += rdnSepLen; 00678 } 00679 } 00680 if (i < info->cRDN - 1) 00681 { 00682 if (psz && ret < csz - sepLen - 1) 00683 memcpy(psz + ret, sep, sepLen * sizeof(WCHAR)); 00684 ret += sepLen; 00685 } 00686 if(reverse) rdn--; 00687 else rdn++; 00688 } 00689 LocalFree(info); 00690 } 00691 if (psz && csz) 00692 { 00693 *(psz + ret) = '\0'; 00694 ret++; 00695 } 00696 else 00697 ret++; 00698 return ret; 00699 } 00700 00701 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, 00702 DWORD dwStrType, LPWSTR psz, DWORD csz) 00703 { 00704 BOOL ret; 00705 00706 TRACE("(%d, %p, %08x, %p, %d)\n", dwCertEncodingType, pName, dwStrType, 00707 psz, csz); 00708 00709 ret = cert_name_to_str_with_indent(dwCertEncodingType, 0, pName, dwStrType, 00710 psz, csz); 00711 TRACE("Returning %s\n", debugstr_w(psz)); 00712 return ret; 00713 } 00714 00715 BOOL WINAPI CertStrToNameA(DWORD dwCertEncodingType, LPCSTR pszX500, 00716 DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded, 00717 LPCSTR *ppszError) 00718 { 00719 BOOL ret; 00720 int len; 00721 00722 TRACE("(%08x, %s, %08x, %p, %p, %p, %p)\n", dwCertEncodingType, 00723 debugstr_a(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded, 00724 ppszError); 00725 00726 len = MultiByteToWideChar(CP_ACP, 0, pszX500, -1, NULL, 0); 00727 if (len) 00728 { 00729 LPWSTR x500, errorStr; 00730 00731 if ((x500 = CryptMemAlloc(len * sizeof(WCHAR)))) 00732 { 00733 MultiByteToWideChar(CP_ACP, 0, pszX500, -1, x500, len); 00734 ret = CertStrToNameW(dwCertEncodingType, x500, dwStrType, 00735 pvReserved, pbEncoded, pcbEncoded, 00736 ppszError ? (LPCWSTR *)&errorStr : NULL); 00737 if (ppszError) 00738 { 00739 if (!ret) 00740 { 00741 LONG i; 00742 00743 *ppszError = pszX500; 00744 for (i = 0; i < errorStr - x500; i++) 00745 *ppszError = CharNextA(*ppszError); 00746 } 00747 else 00748 *ppszError = NULL; 00749 } 00750 CryptMemFree(x500); 00751 } 00752 else 00753 { 00754 SetLastError(ERROR_OUTOFMEMORY); 00755 ret = FALSE; 00756 } 00757 } 00758 else 00759 { 00760 SetLastError(CRYPT_E_INVALID_X500_STRING); 00761 if (ppszError) 00762 *ppszError = pszX500; 00763 ret = FALSE; 00764 } 00765 return ret; 00766 } 00767 00768 struct KeynameKeeper 00769 { 00770 WCHAR buf[10]; /* big enough for L"GivenName" */ 00771 LPWSTR keyName; /* usually = buf, but may be allocated */ 00772 DWORD keyLen; 00773 }; 00774 00775 static void CRYPT_InitializeKeynameKeeper(struct KeynameKeeper *keeper) 00776 { 00777 keeper->keyName = keeper->buf; 00778 keeper->keyLen = sizeof(keeper->buf) / sizeof(keeper->buf[0]); 00779 } 00780 00781 static void CRYPT_FreeKeynameKeeper(struct KeynameKeeper *keeper) 00782 { 00783 if (keeper->keyName != keeper->buf) 00784 CryptMemFree(keeper->keyName); 00785 } 00786 00787 struct X500TokenW 00788 { 00789 LPCWSTR start; 00790 LPCWSTR end; 00791 }; 00792 00793 static void CRYPT_KeynameKeeperFromTokenW(struct KeynameKeeper *keeper, 00794 const struct X500TokenW *key) 00795 { 00796 DWORD len = key->end - key->start; 00797 00798 if (len > keeper->keyLen) 00799 { 00800 if (keeper->keyName == keeper->buf) 00801 keeper->keyName = CryptMemAlloc(len * sizeof(WCHAR)); 00802 else 00803 keeper->keyName = CryptMemRealloc(keeper->keyName, 00804 len * sizeof(WCHAR)); 00805 keeper->keyLen = len; 00806 } 00807 memcpy(keeper->keyName, key->start, (key->end - key->start) * 00808 sizeof(WCHAR)); 00809 keeper->keyName[len] = '\0'; 00810 TRACE("Keyname is %s\n", debugstr_w(keeper->keyName)); 00811 } 00812 00813 static BOOL CRYPT_GetNextKeyW(LPCWSTR str, struct X500TokenW *token, 00814 LPCWSTR *ppszError) 00815 { 00816 BOOL ret = TRUE; 00817 00818 while (*str && isspaceW(*str)) 00819 str++; 00820 if (*str) 00821 { 00822 token->start = str; 00823 while (*str && *str != '=' && !isspaceW(*str)) 00824 str++; 00825 if (*str && (*str == '=' || isspaceW(*str))) 00826 token->end = str; 00827 else 00828 { 00829 TRACE("missing equals char at %s\n", debugstr_w(token->start)); 00830 if (ppszError) 00831 *ppszError = token->start; 00832 SetLastError(CRYPT_E_INVALID_X500_STRING); 00833 ret = FALSE; 00834 } 00835 } 00836 else 00837 token->start = NULL; 00838 return ret; 00839 } 00840 00841 /* Assumes separators are characters in the 0-255 range */ 00842 static BOOL CRYPT_GetNextValueW(LPCWSTR str, DWORD dwFlags, LPCWSTR separators, 00843 struct X500TokenW *token, LPCWSTR *ppszError) 00844 { 00845 BOOL ret = TRUE; 00846 00847 TRACE("(%s, %s, %p, %p)\n", debugstr_w(str), debugstr_w(separators), token, 00848 ppszError); 00849 00850 while (*str && isspaceW(*str)) 00851 str++; 00852 if (*str) 00853 { 00854 token->start = str; 00855 if (!(dwFlags & CERT_NAME_STR_NO_QUOTING_FLAG) && *str == '"') 00856 { 00857 token->end = NULL; 00858 str++; 00859 while (!token->end && ret) 00860 { 00861 while (*str && *str != '"') 00862 str++; 00863 if (*str == '"') 00864 { 00865 if (*(str + 1) != '"') 00866 token->end = str + 1; 00867 else 00868 str += 2; 00869 } 00870 else 00871 { 00872 TRACE("unterminated quote at %s\n", debugstr_w(str)); 00873 if (ppszError) 00874 *ppszError = str; 00875 SetLastError(CRYPT_E_INVALID_X500_STRING); 00876 ret = FALSE; 00877 } 00878 } 00879 } 00880 else 00881 { 00882 WCHAR map[256] = { 0 }; 00883 00884 while (*separators) 00885 map[*separators++] = 1; 00886 while (*str && (*str >= 0xff || !map[*str])) 00887 str++; 00888 token->end = str; 00889 } 00890 } 00891 else 00892 { 00893 TRACE("missing value at %s\n", debugstr_w(str)); 00894 if (ppszError) 00895 *ppszError = str; 00896 SetLastError(CRYPT_E_INVALID_X500_STRING); 00897 ret = FALSE; 00898 } 00899 return ret; 00900 } 00901 00902 /* Encodes the string represented by value as the string type type into the 00903 * CERT_NAME_BLOB output. If there is an error and ppszError is not NULL, 00904 * *ppszError is set to the first failing character. If there is no error, 00905 * output's pbData must be freed with LocalFree. 00906 */ 00907 static BOOL CRYPT_EncodeValueWithType(DWORD dwCertEncodingType, 00908 const struct X500TokenW *value, PCERT_NAME_BLOB output, DWORD type, 00909 LPCWSTR *ppszError) 00910 { 00911 CERT_NAME_VALUE nameValue = { type, { 0, NULL } }; 00912 BOOL ret = TRUE; 00913 00914 if (value->end > value->start) 00915 { 00916 LONG i; 00917 LPWSTR ptr; 00918 00919 nameValue.Value.pbData = CryptMemAlloc((value->end - value->start + 1) * 00920 sizeof(WCHAR)); 00921 if (!nameValue.Value.pbData) 00922 { 00923 SetLastError(ERROR_OUTOFMEMORY); 00924 return FALSE; 00925 } 00926 ptr = (LPWSTR)nameValue.Value.pbData; 00927 for (i = 0; i < value->end - value->start; i++) 00928 { 00929 *ptr++ = value->start[i]; 00930 if (value->start[i] == '"') 00931 i++; 00932 } 00933 /* The string is NULL terminated because of a quirk in encoding 00934 * unicode names values: if the length is given as 0, the value is 00935 * assumed to be a NULL-terminated string. 00936 */ 00937 *ptr = 0; 00938 nameValue.Value.cbData = (LPBYTE)ptr - nameValue.Value.pbData; 00939 } 00940 ret = CryptEncodeObjectEx(dwCertEncodingType, X509_UNICODE_NAME_VALUE, 00941 &nameValue, CRYPT_ENCODE_ALLOC_FLAG, NULL, &output->pbData, 00942 &output->cbData); 00943 if (!ret && ppszError) 00944 { 00945 if (type == CERT_RDN_NUMERIC_STRING && 00946 GetLastError() == CRYPT_E_INVALID_NUMERIC_STRING) 00947 *ppszError = value->start + output->cbData; 00948 else if (type == CERT_RDN_PRINTABLE_STRING && 00949 GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING) 00950 *ppszError = value->start + output->cbData; 00951 else if (type == CERT_RDN_IA5_STRING && 00952 GetLastError() == CRYPT_E_INVALID_IA5_STRING) 00953 *ppszError = value->start + output->cbData; 00954 } 00955 CryptMemFree(nameValue.Value.pbData); 00956 return ret; 00957 } 00958 00959 static BOOL CRYPT_EncodeValue(DWORD dwCertEncodingType, 00960 const struct X500TokenW *value, PCERT_NAME_BLOB output, const DWORD *types, 00961 LPCWSTR *ppszError) 00962 { 00963 DWORD i; 00964 BOOL ret; 00965 00966 ret = FALSE; 00967 for (i = 0; !ret && types[i]; i++) 00968 ret = CRYPT_EncodeValueWithType(dwCertEncodingType, value, output, 00969 types[i], ppszError); 00970 return ret; 00971 } 00972 00973 static BOOL CRYPT_ValueToRDN(DWORD dwCertEncodingType, PCERT_NAME_INFO info, 00974 PCCRYPT_OID_INFO keyOID, struct X500TokenW *value, DWORD dwStrType, LPCWSTR *ppszError) 00975 { 00976 BOOL ret = FALSE; 00977 00978 TRACE("OID %s, value %s\n", debugstr_a(keyOID->pszOID), 00979 debugstr_wn(value->start, value->end - value->start)); 00980 00981 if (!info->rgRDN) 00982 info->rgRDN = CryptMemAlloc(sizeof(CERT_RDN)); 00983 else 00984 info->rgRDN = CryptMemRealloc(info->rgRDN, 00985 (info->cRDN + 1) * sizeof(CERT_RDN)); 00986 if (info->rgRDN) 00987 { 00988 /* FIXME: support multiple RDN attrs */ 00989 info->rgRDN[info->cRDN].rgRDNAttr = 00990 CryptMemAlloc(sizeof(CERT_RDN_ATTR)); 00991 if (info->rgRDN[info->cRDN].rgRDNAttr) 00992 { 00993 static const DWORD defaultTypes[] = { CERT_RDN_PRINTABLE_STRING, 00994 CERT_RDN_BMP_STRING, 0 }; 00995 const DWORD *types; 00996 00997 info->rgRDN[info->cRDN].cRDNAttr = 1; 00998 info->rgRDN[info->cRDN].rgRDNAttr[0].pszObjId = 00999 (LPSTR)keyOID->pszOID; 01000 info->rgRDN[info->cRDN].rgRDNAttr[0].dwValueType = 01001 CERT_RDN_ENCODED_BLOB; 01002 if (keyOID->ExtraInfo.cbData) 01003 types = (const DWORD *)keyOID->ExtraInfo.pbData; 01004 else 01005 types = defaultTypes; 01006 01007 /* Remove surrounding quotes */ 01008 if (value->start[0] == '"' && !(dwStrType & CERT_NAME_STR_NO_QUOTING_FLAG)) 01009 { 01010 value->start++; 01011 value->end--; 01012 } 01013 ret = CRYPT_EncodeValue(dwCertEncodingType, value, 01014 &info->rgRDN[info->cRDN].rgRDNAttr[0].Value, types, ppszError); 01015 } 01016 else 01017 SetLastError(ERROR_OUTOFMEMORY); 01018 info->cRDN++; 01019 } 01020 else 01021 SetLastError(ERROR_OUTOFMEMORY); 01022 return ret; 01023 } 01024 01025 BOOL WINAPI CertStrToNameW(DWORD dwCertEncodingType, LPCWSTR pszX500, 01026 DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded, 01027 LPCWSTR *ppszError) 01028 { 01029 CERT_NAME_INFO info = { 0, NULL }; 01030 LPCWSTR str; 01031 struct KeynameKeeper keeper; 01032 DWORD i; 01033 BOOL ret = TRUE; 01034 01035 TRACE("(%08x, %s, %08x, %p, %p, %p, %p)\n", dwCertEncodingType, 01036 debugstr_w(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded, 01037 ppszError); 01038 01039 CRYPT_InitializeKeynameKeeper(&keeper); 01040 str = pszX500; 01041 while (str && *str && ret) 01042 { 01043 struct X500TokenW token; 01044 01045 ret = CRYPT_GetNextKeyW(str, &token, ppszError); 01046 if (ret && token.start) 01047 { 01048 PCCRYPT_OID_INFO keyOID; 01049 01050 CRYPT_KeynameKeeperFromTokenW(&keeper, &token); 01051 keyOID = CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY, keeper.keyName, 01052 CRYPT_RDN_ATTR_OID_GROUP_ID); 01053 if (!keyOID) 01054 { 01055 if (ppszError) 01056 *ppszError = token.start; 01057 SetLastError(CRYPT_E_INVALID_X500_STRING); 01058 ret = FALSE; 01059 } 01060 else 01061 { 01062 str = token.end; 01063 while (isspace(*str)) 01064 str++; 01065 if (*str != '=') 01066 { 01067 if (ppszError) 01068 *ppszError = str; 01069 SetLastError(CRYPT_E_INVALID_X500_STRING); 01070 ret = FALSE; 01071 } 01072 else 01073 { 01074 static const WCHAR commaSep[] = { ',',0 }; 01075 static const WCHAR semiSep[] = { ';',0 }; 01076 static const WCHAR crlfSep[] = { '\r','\n',0 }; 01077 static const WCHAR allSepsWithoutPlus[] = { ',',';','\r','\n',0 }; 01078 static const WCHAR allSeps[] = { '+',',',';','\r','\n',0 }; 01079 LPCWSTR sep; 01080 01081 str++; 01082 if (dwStrType & CERT_NAME_STR_COMMA_FLAG) 01083 sep = commaSep; 01084 else if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG) 01085 sep = semiSep; 01086 else if (dwStrType & CERT_NAME_STR_CRLF_FLAG) 01087 sep = crlfSep; 01088 else if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG) 01089 sep = allSepsWithoutPlus; 01090 else 01091 sep = allSeps; 01092 ret = CRYPT_GetNextValueW(str, dwStrType, sep, &token, 01093 ppszError); 01094 if (ret) 01095 { 01096 str = token.end; 01097 ret = CRYPT_ValueToRDN(dwCertEncodingType, &info, 01098 keyOID, &token, dwStrType, ppszError); 01099 } 01100 } 01101 } 01102 } 01103 } 01104 CRYPT_FreeKeynameKeeper(&keeper); 01105 if (ret) 01106 { 01107 if (ppszError) 01108 *ppszError = NULL; 01109 ret = CryptEncodeObjectEx(dwCertEncodingType, X509_NAME, &info, 01110 0, NULL, pbEncoded, pcbEncoded); 01111 } 01112 for (i = 0; i < info.cRDN; i++) 01113 { 01114 DWORD j; 01115 01116 for (j = 0; j < info.rgRDN[i].cRDNAttr; j++) 01117 LocalFree(info.rgRDN[i].rgRDNAttr[j].Value.pbData); 01118 CryptMemFree(info.rgRDN[i].rgRDNAttr); 01119 } 01120 CryptMemFree(info.rgRDN); 01121 return ret; 01122 } 01123 01124 DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, 01125 DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString) 01126 { 01127 DWORD ret; 01128 01129 TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType, dwFlags, 01130 pvTypePara, pszNameString, cchNameString); 01131 01132 if (pszNameString) 01133 { 01134 LPWSTR wideName; 01135 DWORD nameLen; 01136 01137 nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, 01138 NULL, 0); 01139 wideName = CryptMemAlloc(nameLen * sizeof(WCHAR)); 01140 if (wideName) 01141 { 01142 CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, 01143 wideName, nameLen); 01144 nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen, 01145 pszNameString, cchNameString, NULL, NULL); 01146 if (nameLen <= cchNameString) 01147 ret = nameLen; 01148 else 01149 { 01150 pszNameString[cchNameString - 1] = '\0'; 01151 ret = cchNameString; 01152 } 01153 CryptMemFree(wideName); 01154 } 01155 else 01156 { 01157 *pszNameString = '\0'; 01158 ret = 1; 01159 } 01160 } 01161 else 01162 ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, 01163 NULL, 0); 01164 return ret; 01165 } 01166 01167 /* Searches cert's extensions for the alternate name extension with OID 01168 * altNameOID, and if found, searches it for the alternate name type entryType. 01169 * If found, returns a pointer to the entry, otherwise returns NULL. 01170 * Regardless of whether an entry of the desired type is found, if the 01171 * alternate name extension is present, sets *info to the decoded alternate 01172 * name extension, which you must free using LocalFree. 01173 * The return value is a pointer within *info, so don't free *info before 01174 * you're done with the return value. 01175 */ 01176 static PCERT_ALT_NAME_ENTRY cert_find_alt_name_entry(PCCERT_CONTEXT cert, 01177 LPCSTR altNameOID, DWORD entryType, PCERT_ALT_NAME_INFO *info) 01178 { 01179 PCERT_ALT_NAME_ENTRY entry = NULL; 01180 PCERT_EXTENSION ext = CertFindExtension(altNameOID, 01181 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension); 01182 01183 if (ext) 01184 { 01185 DWORD bytes = 0; 01186 01187 if (CryptDecodeObjectEx(cert->dwCertEncodingType, X509_ALTERNATE_NAME, 01188 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, 01189 info, &bytes)) 01190 { 01191 DWORD i; 01192 01193 for (i = 0; !entry && i < (*info)->cAltEntry; i++) 01194 if ((*info)->rgAltEntry[i].dwAltNameChoice == entryType) 01195 entry = &(*info)->rgAltEntry[i]; 01196 } 01197 } 01198 else 01199 *info = NULL; 01200 return entry; 01201 } 01202 01203 static DWORD cert_get_name_from_rdn_attr(DWORD encodingType, 01204 const CERT_NAME_BLOB *name, LPCSTR oid, LPWSTR pszNameString, DWORD cchNameString) 01205 { 01206 CERT_NAME_INFO *nameInfo; 01207 DWORD bytes = 0, ret = 0; 01208 01209 if (CryptDecodeObjectEx(encodingType, X509_NAME, name->pbData, 01210 name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo, &bytes)) 01211 { 01212 PCERT_RDN_ATTR nameAttr; 01213 01214 if (!oid) 01215 oid = szOID_RSA_emailAddr; 01216 nameAttr = CertFindRDNAttr(oid, nameInfo); 01217 if (nameAttr) 01218 ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value, 01219 pszNameString, cchNameString); 01220 LocalFree(nameInfo); 01221 } 01222 return ret; 01223 } 01224 01225 DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, 01226 DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString) 01227 { 01228 DWORD ret = 0; 01229 PCERT_NAME_BLOB name; 01230 LPCSTR altNameOID; 01231 01232 TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType, 01233 dwFlags, pvTypePara, pszNameString, cchNameString); 01234 01235 if (!pCertContext) 01236 goto done; 01237 01238 if (dwFlags & CERT_NAME_ISSUER_FLAG) 01239 { 01240 name = &pCertContext->pCertInfo->Issuer; 01241 altNameOID = szOID_ISSUER_ALT_NAME; 01242 } 01243 else 01244 { 01245 name = &pCertContext->pCertInfo->Subject; 01246 altNameOID = szOID_SUBJECT_ALT_NAME; 01247 } 01248 01249 switch (dwType) 01250 { 01251 case CERT_NAME_EMAIL_TYPE: 01252 { 01253 CERT_ALT_NAME_INFO *info; 01254 PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, 01255 altNameOID, CERT_ALT_NAME_RFC822_NAME, &info); 01256 01257 if (entry) 01258 { 01259 if (!pszNameString) 01260 ret = strlenW(entry->u.pwszRfc822Name) + 1; 01261 else if (cchNameString) 01262 { 01263 ret = min(strlenW(entry->u.pwszRfc822Name), cchNameString - 1); 01264 memcpy(pszNameString, entry->u.pwszRfc822Name, 01265 ret * sizeof(WCHAR)); 01266 pszNameString[ret++] = 0; 01267 } 01268 } 01269 if (info) 01270 LocalFree(info); 01271 if (!ret) 01272 ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, 01273 name, szOID_RSA_emailAddr, pszNameString, cchNameString); 01274 break; 01275 } 01276 case CERT_NAME_RDN_TYPE: 01277 { 01278 DWORD type = pvTypePara ? *(DWORD *)pvTypePara : 0; 01279 01280 if (name->cbData) 01281 ret = CertNameToStrW(pCertContext->dwCertEncodingType, name, 01282 type, pszNameString, cchNameString); 01283 else 01284 { 01285 CERT_ALT_NAME_INFO *info; 01286 PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, 01287 altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &info); 01288 01289 if (entry) 01290 ret = CertNameToStrW(pCertContext->dwCertEncodingType, 01291 &entry->u.DirectoryName, type, pszNameString, cchNameString); 01292 if (info) 01293 LocalFree(info); 01294 } 01295 break; 01296 } 01297 case CERT_NAME_ATTR_TYPE: 01298 ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, 01299 name, pvTypePara, pszNameString, cchNameString); 01300 if (!ret) 01301 { 01302 CERT_ALT_NAME_INFO *altInfo; 01303 PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, 01304 altNameOID, CERT_ALT_NAME_DIRECTORY_NAME, &altInfo); 01305 01306 if (entry) 01307 ret = cert_name_to_str_with_indent(X509_ASN_ENCODING, 0, 01308 &entry->u.DirectoryName, 0, pszNameString, cchNameString); 01309 if (altInfo) 01310 LocalFree(altInfo); 01311 } 01312 break; 01313 case CERT_NAME_SIMPLE_DISPLAY_TYPE: 01314 { 01315 static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME, 01316 szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME, 01317 szOID_RSA_emailAddr }; 01318 CERT_NAME_INFO *nameInfo = NULL; 01319 DWORD bytes = 0, i; 01320 01321 if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME, 01322 name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo, 01323 &bytes)) 01324 { 01325 PCERT_RDN_ATTR nameAttr = NULL; 01326 01327 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) / 01328 sizeof(simpleAttributeOIDs[0]); i++) 01329 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], nameInfo); 01330 if (nameAttr) 01331 ret = CertRDNValueToStrW(nameAttr->dwValueType, 01332 &nameAttr->Value, pszNameString, cchNameString); 01333 LocalFree(nameInfo); 01334 } 01335 if (!ret) 01336 { 01337 CERT_ALT_NAME_INFO *altInfo; 01338 PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, 01339 altNameOID, CERT_ALT_NAME_RFC822_NAME, &altInfo); 01340 01341 if (altInfo) 01342 { 01343 if (!entry && altInfo->cAltEntry) 01344 entry = &altInfo->rgAltEntry[0]; 01345 if (entry) 01346 { 01347 if (!pszNameString) 01348 ret = strlenW(entry->u.pwszRfc822Name) + 1; 01349 else if (cchNameString) 01350 { 01351 ret = min(strlenW(entry->u.pwszRfc822Name), 01352 cchNameString - 1); 01353 memcpy(pszNameString, entry->u.pwszRfc822Name, 01354 ret * sizeof(WCHAR)); 01355 pszNameString[ret++] = 0; 01356 } 01357 } 01358 LocalFree(altInfo); 01359 } 01360 } 01361 break; 01362 } 01363 case CERT_NAME_FRIENDLY_DISPLAY_TYPE: 01364 { 01365 DWORD cch = cchNameString; 01366 01367 if (CertGetCertificateContextProperty(pCertContext, 01368 CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch)) 01369 ret = cch; 01370 else 01371 ret = CertGetNameStringW(pCertContext, 01372 CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString, 01373 cchNameString); 01374 break; 01375 } 01376 case CERT_NAME_DNS_TYPE: 01377 { 01378 CERT_ALT_NAME_INFO *info; 01379 PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, 01380 altNameOID, CERT_ALT_NAME_DNS_NAME, &info); 01381 01382 if (entry) 01383 { 01384 if (!pszNameString) 01385 ret = strlenW(entry->u.pwszDNSName) + 1; 01386 else if (cchNameString) 01387 { 01388 ret = min(strlenW(entry->u.pwszDNSName), cchNameString - 1); 01389 memcpy(pszNameString, entry->u.pwszDNSName, ret * sizeof(WCHAR)); 01390 pszNameString[ret++] = 0; 01391 } 01392 } 01393 if (info) 01394 LocalFree(info); 01395 if (!ret) 01396 ret = cert_get_name_from_rdn_attr(pCertContext->dwCertEncodingType, 01397 name, szOID_COMMON_NAME, pszNameString, cchNameString); 01398 break; 01399 } 01400 case CERT_NAME_URL_TYPE: 01401 { 01402 CERT_ALT_NAME_INFO *info; 01403 PCERT_ALT_NAME_ENTRY entry = cert_find_alt_name_entry(pCertContext, 01404 altNameOID, CERT_ALT_NAME_URL, &info); 01405 01406 if (entry) 01407 { 01408 if (!pszNameString) 01409 ret = strlenW(entry->u.pwszURL) + 1; 01410 else if (cchNameString) 01411 { 01412 ret = min(strlenW(entry->u.pwszURL), cchNameString - 1); 01413 memcpy(pszNameString, entry->u.pwszURL, ret * sizeof(WCHAR)); 01414 pszNameString[ret++] = 0; 01415 } 01416 } 01417 if (info) 01418 LocalFree(info); 01419 break; 01420 } 01421 default: 01422 FIXME("unimplemented for type %d\n", dwType); 01423 ret = 0; 01424 } 01425 done: 01426 if (!ret) 01427 { 01428 if (!pszNameString) 01429 ret = 1; 01430 else if (cchNameString) 01431 { 01432 pszNameString[0] = 0; 01433 ret = 1; 01434 } 01435 } 01436 return ret; 01437 } Generated on Mon May 28 2012 04:22:58 for ReactOS by
1.7.6.1
|