~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/crypt32/str.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Copyright 2006 Juan Lang for CodeWeavers
  3  *
  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.
  8  *
  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.
 13  *
 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
 17  */
 18 #include <stdarg.h>
 19 #include "windef.h"
 20 #include "winbase.h"
 21 #include "winnls.h"
 22 #include "winuser.h"
 23 #include "wincrypt.h"
 24 #include "wine/debug.h"
 25 #include "wine/unicode.h"
 26 
 27 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 28 
 29 DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
 30  LPSTR psz, DWORD csz)
 31 {
 32     DWORD ret = 0;
 33 
 34     TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz);
 35 
 36     switch (dwValueType)
 37     {
 38     case CERT_RDN_ANY_TYPE:
 39         break;
 40     case CERT_RDN_NUMERIC_STRING:
 41     case CERT_RDN_PRINTABLE_STRING:
 42     case CERT_RDN_TELETEX_STRING:
 43     case CERT_RDN_VIDEOTEX_STRING:
 44     case CERT_RDN_IA5_STRING:
 45     case CERT_RDN_GRAPHIC_STRING:
 46     case CERT_RDN_VISIBLE_STRING:
 47     case CERT_RDN_GENERAL_STRING:
 48         if (!psz || !csz)
 49             ret = pValue->cbData;
 50         else
 51         {
 52             DWORD chars = min(pValue->cbData, csz - 1);
 53 
 54             if (chars)
 55             {
 56                 memcpy(psz, pValue->pbData, chars);
 57                 ret += chars;
 58                 csz -= chars;
 59             }
 60         }
 61         break;
 62     case CERT_RDN_UTF8_STRING:
 63         if (!psz || !csz)
 64             ret = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)pValue->pbData,
 65              pValue->cbData / sizeof(WCHAR) + 1, NULL, 0, NULL, NULL);
 66         else
 67         {
 68             ret = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)pValue->pbData,
 69              pValue->cbData / sizeof(WCHAR) + 1, psz, csz - 1, NULL, NULL);
 70             csz -= ret;
 71         }
 72         break;
 73     default:
 74         FIXME("string type %d unimplemented\n", dwValueType);
 75     }
 76     if (psz && csz)
 77     {
 78         *(psz + ret) = '\0';
 79         csz--;
 80         ret++;
 81     }
 82     else
 83         ret++;
 84     TRACE("returning %d (%s)\n", ret, debugstr_a(psz));
 85     return ret;
 86 }
 87 
 88 DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
 89  LPWSTR psz, DWORD csz)
 90 {
 91     DWORD ret = 0;
 92 
 93     TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz);
 94 
 95     switch (dwValueType)
 96     {
 97     case CERT_RDN_ANY_TYPE:
 98         break;
 99     case CERT_RDN_NUMERIC_STRING:
100     case CERT_RDN_PRINTABLE_STRING:
101     case CERT_RDN_TELETEX_STRING:
102     case CERT_RDN_VIDEOTEX_STRING:
103     case CERT_RDN_IA5_STRING:
104     case CERT_RDN_GRAPHIC_STRING:
105     case CERT_RDN_VISIBLE_STRING:
106     case CERT_RDN_GENERAL_STRING:
107         if (!psz || !csz)
108             ret = pValue->cbData;
109         else
110         {
111             DWORD chars = min(pValue->cbData, csz - 1);
112 
113             if (chars)
114             {
115                 DWORD i;
116 
117                 for (i = 0; i < chars; i++)
118                     psz[i] = pValue->pbData[i];
119                 ret += chars;
120                 csz -= chars;
121             }
122         }
123         break;
124     case CERT_RDN_UTF8_STRING:
125         if (!psz || !csz)
126             ret = pValue->cbData / sizeof(WCHAR);
127         else
128         {
129             DWORD chars = min(pValue->cbData / sizeof(WCHAR), csz - 1);
130 
131             if (chars)
132             {
133                 DWORD i;
134 
135                 for (i = 0; i < chars; i++)
136                     psz[i] = *((LPWSTR)pValue->pbData + i);
137                 ret += chars;
138                 csz -= chars;
139             }
140         }
141         break;
142     default:
143         FIXME("string type %d unimplemented\n", dwValueType);
144     }
145     if (psz && csz)
146     {
147         *(psz + ret) = '\0';
148         csz--;
149         ret++;
150     }
151     else
152         ret++;
153     TRACE("returning %d (%s)\n", ret, debugstr_w(psz));
154     return ret;
155 }
156 
157 /* Adds the prefix prefix to the string pointed to by psz, followed by the
158  * character '='.  Copies no more than csz characters.  Returns the number of
159  * characters copied.  If psz is NULL, returns the number of characters that
160  * would be copied.
161  */
162 static DWORD CRYPT_AddPrefixA(LPCSTR prefix, LPSTR psz, DWORD csz)
163 {
164     DWORD chars;
165 
166     TRACE("(%s, %p, %d)\n", debugstr_a(prefix), psz, csz);
167 
168     if (psz)
169     {
170         chars = min(lstrlenA(prefix), csz);
171         memcpy(psz, prefix, chars);
172         *(psz + chars) = '=';
173         chars++;
174     }
175     else
176         chars = lstrlenA(prefix) + 1;
177     return chars;
178 }
179 
180 DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
181  DWORD dwStrType, LPSTR psz, DWORD csz)
182 {
183     static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
184      CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
185     static const char commaSep[] = ", ";
186     static const char semiSep[] = "; ";
187     static const char crlfSep[] = "\r\n";
188     static const char plusSep[] = " + ";
189     static const char spaceSep[] = " ";
190     DWORD ret = 0, bytes = 0;
191     BOOL bRet;
192     CERT_NAME_INFO *info;
193 
194     TRACE("(%d, %p, %08x, %p, %d)\n", dwCertEncodingType, pName, dwStrType,
195      psz, csz);
196     if (dwStrType & unsupportedFlags)
197         FIXME("unsupported flags: %08x\n", dwStrType & unsupportedFlags);
198 
199     bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
200      pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
201     if (bRet)
202     {
203         DWORD i, j, sepLen, rdnSepLen;
204         LPCSTR sep, rdnSep;
205         BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG;
206         const CERT_RDN *rdn = info->rgRDN;
207 
208         if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1);
209 
210         if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
211             sep = semiSep;
212         else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
213             sep = crlfSep;
214         else
215             sep = commaSep;
216         sepLen = strlen(sep);
217         if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
218             rdnSep = spaceSep;
219         else
220             rdnSep = plusSep;
221         rdnSepLen = strlen(rdnSep);
222         for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
223         {
224             for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++)
225             {
226                 DWORD chars;
227                 char prefixBuf[10]; /* big enough for GivenName */
228                 LPCSTR prefix = NULL;
229 
230                 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
231                     prefix = rdn->rgRDNAttr[j].pszObjId;
232                 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
233                 {
234                     PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
235                      CRYPT_OID_INFO_OID_KEY,
236                      rdn->rgRDNAttr[j].pszObjId,
237                      CRYPT_RDN_ATTR_OID_GROUP_ID);
238 
239                     if (oidInfo)
240                     {
241                         WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1,
242                          prefixBuf, sizeof(prefixBuf), NULL, NULL);
243                         prefix = prefixBuf;
244                     }
245                     else
246                         prefix = rdn->rgRDNAttr[j].pszObjId;
247                 }
248                 if (prefix)
249                 {
250                     /* - 1 is needed to account for the NULL terminator. */
251                     chars = CRYPT_AddPrefixA(prefix,
252                      psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
253                     ret += chars;
254                 }
255                 /* FIXME: handle quoting */
256                 chars = CertRDNValueToStrA(
257                  rdn->rgRDNAttr[j].dwValueType,
258                  &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL,
259                  psz ? csz - ret : 0);
260                 if (chars)
261                     ret += chars - 1;
262                 if (j < rdn->cRDNAttr - 1)
263                 {
264                     if (psz && ret < csz - rdnSepLen - 1)
265                         memcpy(psz + ret, rdnSep, rdnSepLen);
266                     ret += rdnSepLen;
267                 }
268             }
269             if (i < info->cRDN - 1)
270             {
271                 if (psz && ret < csz - sepLen - 1)
272                     memcpy(psz + ret, sep, sepLen);
273                 ret += sepLen;
274             }
275             if(reverse) rdn--;
276             else rdn++;
277         }
278         LocalFree(info);
279     }
280     if (psz && csz)
281     {
282         *(psz + ret) = '\0';
283         ret++;
284     }
285     else
286         ret++;
287     TRACE("Returning %s\n", debugstr_a(psz));
288     return ret;
289 }
290 
291 /* Adds the prefix prefix to the wide-character string pointed to by psz,
292  * followed by the character '='.  Copies no more than csz characters.  Returns
293  * the number of characters copied.  If psz is NULL, returns the number of
294  * characters that would be copied.
295  * Assumes the characters in prefix are ASCII (not multibyte characters.)
296  */
297 static DWORD CRYPT_AddPrefixAToW(LPCSTR prefix, LPWSTR psz, DWORD csz)
298 {
299     DWORD chars;
300 
301     TRACE("(%s, %p, %d)\n", debugstr_a(prefix), psz, csz);
302 
303     if (psz)
304     {
305         DWORD i;
306 
307         chars = min(lstrlenA(prefix), csz);
308         for (i = 0; i < chars; i++)
309             *(psz + i) = prefix[i];
310         *(psz + chars) = '=';
311         chars++;
312     }
313     else
314         chars = lstrlenA(prefix) + 1;
315     return chars;
316 }
317 
318 /* Adds the prefix prefix to the string pointed to by psz, followed by the
319  * character '='.  Copies no more than csz characters.  Returns the number of
320  * characters copied.  If psz is NULL, returns the number of characters that
321  * would be copied.
322  */
323 static DWORD CRYPT_AddPrefixW(LPCWSTR prefix, LPWSTR psz, DWORD csz)
324 {
325     DWORD chars;
326 
327     TRACE("(%s, %p, %d)\n", debugstr_w(prefix), psz, csz);
328 
329     if (psz)
330     {
331         chars = min(lstrlenW(prefix), csz);
332         memcpy(psz, prefix, chars * sizeof(WCHAR));
333         *(psz + chars) = '=';
334         chars++;
335     }
336     else
337         chars = lstrlenW(prefix) + 1;
338     return chars;
339 }
340 
341 DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
342  DWORD dwStrType, LPWSTR psz, DWORD csz)
343 {
344     static const DWORD unsupportedFlags = CERT_NAME_STR_NO_QUOTING_FLAG |
345      CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
346     static const WCHAR commaSep[] = { ',',' ',0 };
347     static const WCHAR semiSep[] = { ';',' ',0 };
348     static const WCHAR crlfSep[] = { '\r','\n',0 };
349     static const WCHAR plusSep[] = { ' ','+',' ',0 };
350     static const WCHAR spaceSep[] = { ' ',0 };
351     DWORD ret = 0, bytes = 0;
352     BOOL bRet;
353     CERT_NAME_INFO *info;
354 
355     TRACE("(%d, %p, %08x, %p, %d)\n", dwCertEncodingType, pName, dwStrType,
356      psz, csz);
357     if (dwStrType & unsupportedFlags)
358         FIXME("unsupported flags: %08x\n", dwStrType & unsupportedFlags);
359 
360     bRet = CryptDecodeObjectEx(dwCertEncodingType, X509_NAME, pName->pbData,
361      pName->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &bytes);
362     if (bRet)
363     {
364         DWORD i, j, sepLen, rdnSepLen;
365         LPCWSTR sep, rdnSep;
366         BOOL reverse = dwStrType & CERT_NAME_STR_REVERSE_FLAG;
367         const CERT_RDN *rdn = info->rgRDN;
368 
369         if(reverse && info->cRDN > 1) rdn += (info->cRDN - 1);
370 
371         if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
372             sep = semiSep;
373         else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
374             sep = crlfSep;
375         else
376             sep = commaSep;
377         sepLen = lstrlenW(sep);
378         if (dwStrType & CERT_NAME_STR_NO_PLUS_FLAG)
379             rdnSep = spaceSep;
380         else
381             rdnSep = plusSep;
382         rdnSepLen = lstrlenW(rdnSep);
383         for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
384         {
385             for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++)
386             {
387                 DWORD chars;
388                 LPCSTR prefixA = NULL;
389                 LPCWSTR prefixW = NULL;
390 
391                 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
392                     prefixA = rdn->rgRDNAttr[j].pszObjId;
393                 else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
394                 {
395                     PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
396                      CRYPT_OID_INFO_OID_KEY,
397                      rdn->rgRDNAttr[j].pszObjId,
398                      CRYPT_RDN_ATTR_OID_GROUP_ID);
399 
400                     if (oidInfo)
401                         prefixW = oidInfo->pwszName;
402                     else
403                         prefixA = rdn->rgRDNAttr[j].pszObjId;
404                 }
405                 if (prefixW)
406                 {
407                     /* - 1 is needed to account for the NULL terminator. */
408                     chars = CRYPT_AddPrefixW(prefixW,
409                      psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
410                     ret += chars;
411                 }
412                 else if (prefixA)
413                 {
414                     /* - 1 is needed to account for the NULL terminator. */
415                     chars = CRYPT_AddPrefixAToW(prefixA,
416                      psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
417                     ret += chars;
418                 }
419                 /* FIXME: handle quoting */
420                 chars = CertRDNValueToStrW(
421                  rdn->rgRDNAttr[j].dwValueType,
422                  &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL,
423                  psz ? csz - ret : 0);
424                 if (chars)
425                     ret += chars - 1;
426                 if (j < rdn->cRDNAttr - 1)
427                 {
428                     if (psz && ret < csz - rdnSepLen - 1)
429                         memcpy(psz + ret, rdnSep, rdnSepLen * sizeof(WCHAR));
430                     ret += rdnSepLen;
431                 }
432             }
433             if (i < info->cRDN - 1)
434             {
435                 if (psz && ret < csz - sepLen - 1)
436                     memcpy(psz + ret, sep, sepLen * sizeof(WCHAR));
437                 ret += sepLen;
438             }
439             if(reverse) rdn--;
440             else rdn++;
441         }
442         LocalFree(info);
443     }
444     if (psz && csz)
445     {
446         *(psz + ret) = '\0';
447         ret++;
448     }
449     else
450         ret++;
451     TRACE("Returning %s\n", debugstr_w(psz));
452     return ret;
453 }
454 
455 BOOL WINAPI CertStrToNameA(DWORD dwCertEncodingType, LPCSTR pszX500,
456  DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded,
457  LPCSTR *ppszError)
458 {
459     BOOL ret;
460     int len;
461 
462     TRACE("(%08x, %s, %08x, %p, %p, %p, %p)\n", dwCertEncodingType,
463      debugstr_a(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded,
464      ppszError);
465 
466     len = MultiByteToWideChar(CP_ACP, 0, pszX500, -1, NULL, 0);
467     if (len)
468     {
469         LPWSTR x500, errorStr;
470 
471         if ((x500 = CryptMemAlloc(len * sizeof(WCHAR))))
472         {
473             MultiByteToWideChar(CP_ACP, 0, pszX500, -1, x500, len);
474             ret = CertStrToNameW(dwCertEncodingType, x500, dwStrType,
475              pvReserved, pbEncoded, pcbEncoded,
476              ppszError ? (LPCWSTR *)&errorStr : NULL);
477             if (ppszError)
478             {
479                 if (!ret)
480                 {
481                     DWORD i;
482 
483                     *ppszError = pszX500;
484                     for (i = 0; i < errorStr - x500; i++)
485                         *ppszError = CharNextA(*ppszError);
486                 }
487                 else
488                     *ppszError = NULL;
489             }
490             CryptMemFree(x500);
491         }
492         else
493         {
494             SetLastError(ERROR_OUTOFMEMORY);
495             ret = FALSE;
496         }
497     }
498     else
499     {
500         SetLastError(CRYPT_E_INVALID_X500_STRING);
501         if (ppszError)
502             *ppszError = pszX500;
503         ret = FALSE;
504     }
505     return ret;
506 }
507 
508 struct KeynameKeeper
509 {
510     WCHAR  buf[10]; /* big enough for L"GivenName" */
511     LPWSTR keyName; /* usually = buf, but may be allocated */
512     DWORD  keyLen;
513 };
514 
515 static void CRYPT_InitializeKeynameKeeper(struct KeynameKeeper *keeper)
516 {
517     keeper->keyName = keeper->buf;
518     keeper->keyLen = sizeof(keeper->buf) / sizeof(keeper->buf[0]);
519 }
520 
521 static void CRYPT_FreeKeynameKeeper(struct KeynameKeeper *keeper)
522 {
523     if (keeper->keyName != keeper->buf)
524         CryptMemFree(keeper->keyName);
525 }
526 
527 struct X500TokenW
528 {
529     LPCWSTR start;
530     LPCWSTR end;
531 };
532 
533 static void CRYPT_KeynameKeeperFromTokenW(struct KeynameKeeper *keeper,
534  const struct X500TokenW *key)
535 {
536     DWORD len = key->end - key->start;
537 
538     if (len > keeper->keyLen)
539     {
540         if (keeper->keyName == keeper->buf)
541             keeper->keyName = CryptMemAlloc(len * sizeof(WCHAR));
542         else
543             keeper->keyName = CryptMemRealloc(keeper->keyName,
544              len * sizeof(WCHAR));
545         keeper->keyLen = len;
546     }
547     memcpy(keeper->keyName, key->start, (key->end - key->start) *
548      sizeof(WCHAR));
549     keeper->keyName[len] = '\0';
550     TRACE("Keyname is %s\n", debugstr_w(keeper->keyName));
551 }
552 
553 static BOOL CRYPT_GetNextKeyW(LPCWSTR str, struct X500TokenW *token,
554  LPCWSTR *ppszError)
555 {
556     BOOL ret = TRUE;
557 
558     while (*str && isspaceW(*str))
559         str++;
560     if (*str)
561     {
562         token->start = str;
563         while (*str && *str != '=' && !isspaceW(*str))
564             str++;
565         if (*str && (*str == '=' || isspaceW(*str)))
566             token->end = str;
567         else
568         {
569             TRACE("missing equals char at %s\n", debugstr_w(token->start));
570             if (ppszError)
571                 *ppszError = token->start;
572             SetLastError(CRYPT_E_INVALID_X500_STRING);
573             ret = FALSE;
574         }
575     }
576     else
577         token->start = NULL;
578     return ret;
579 }
580 
581 /* Assumes separators are characters in the 0-255 range */
582 static BOOL CRYPT_GetNextValueW(LPCWSTR str, DWORD dwFlags, LPCWSTR separators,
583  struct X500TokenW *token, LPCWSTR *ppszError)
584 {
585     BOOL ret = TRUE;
586 
587     TRACE("(%s, %s, %p, %p)\n", debugstr_w(str), debugstr_w(separators), token,
588      ppszError);
589 
590     while (*str && isspaceW(*str))
591         str++;
592     if (*str)
593     {
594         token->start = str;
595         if (!(dwFlags & CERT_NAME_STR_NO_QUOTING_FLAG) && *str == '"')
596         {
597             token->end = NULL;
598             str++;
599             while (!token->end && ret)
600             {
601                 while (*str && *str != '"')
602                     str++;
603                 if (*str == '"')
604                 {
605                     if (*(str + 1) != '"')
606                         token->end = str + 1;
607                     else
608                         str += 2;
609                 }
610                 else
611                 {
612                     TRACE("unterminated quote at %s\n", debugstr_w(str));
613                     if (ppszError)
614                         *ppszError = str;
615                     SetLastError(CRYPT_E_INVALID_X500_STRING);
616                     ret = FALSE;
617                 }
618             }
619         }
620         else
621         {
622             WCHAR map[256] = { 0 };
623 
624             while (*separators)
625                 map[*separators++] = 1;
626             while (*str && (*str >= 0xff || !map[*str]))
627                 str++;
628             token->end = str;
629         }
630     }
631     else
632     {
633         TRACE("missing value at %s\n", debugstr_w(str));
634         if (ppszError)
635             *ppszError = str;
636         SetLastError(CRYPT_E_INVALID_X500_STRING);
637         ret = FALSE;
638     }
639     return ret;
640 }
641 
642 /* Encodes the string represented by value as the string type type into the
643  * CERT_NAME_BLOB output.  If there is an error and ppszError is not NULL,
644  * *ppszError is set to the first failing character.  If there is no error,
645  * output's pbData must be freed with LocalFree.
646  */
647 static BOOL CRYPT_EncodeValueWithType(DWORD dwCertEncodingType,
648  const struct X500TokenW *value, PCERT_NAME_BLOB output, DWORD type,
649  LPCWSTR *ppszError)
650 {
651     CERT_NAME_VALUE nameValue = { type, { 0, NULL } };
652     BOOL ret = TRUE;
653 
654     if (value->end > value->start)
655     {
656         nameValue.Value.pbData = CryptMemAlloc((value->end - value->start) *
657          sizeof(WCHAR));
658         if (!nameValue.Value.pbData)
659         {
660             SetLastError(ERROR_OUTOFMEMORY);
661             ret = FALSE;
662         }
663     }
664     if (ret)
665     {
666         if (value->end > value->start)
667         {
668             DWORD i;
669             LPWSTR ptr = (LPWSTR)nameValue.Value.pbData;
670 
671             for (i = 0; i < value->end - value->start; i++)
672             {
673                 *ptr++ = value->start[i];
674                 if (value->start[i] == '"')
675                     i++;
676             }
677             nameValue.Value.cbData = (LPBYTE)ptr - nameValue.Value.pbData;
678         }
679         ret = CryptEncodeObjectEx(dwCertEncodingType, X509_UNICODE_NAME_VALUE,
680          &nameValue, CRYPT_ENCODE_ALLOC_FLAG, NULL, &output->pbData,
681          &output->cbData);
682         if (!ret && ppszError)
683         {
684             if (type == CERT_RDN_NUMERIC_STRING &&
685              GetLastError() == CRYPT_E_INVALID_NUMERIC_STRING)
686                 *ppszError = value->start + output->cbData;
687             else if (type == CERT_RDN_PRINTABLE_STRING &&
688              GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING)
689                 *ppszError = value->start + output->cbData;
690             else if (type == CERT_RDN_IA5_STRING &&
691              GetLastError() == CRYPT_E_INVALID_IA5_STRING)
692                 *ppszError = value->start + output->cbData;
693         }
694         CryptMemFree(nameValue.Value.pbData);
695     }
696     return ret;
697 }
698 
699 static BOOL CRYPT_EncodeValue(DWORD dwCertEncodingType,
700  const struct X500TokenW *value, PCERT_NAME_BLOB output, const DWORD *types,
701  LPCWSTR *ppszError)
702 {
703     DWORD i;
704     BOOL ret;
705 
706     ret = FALSE;
707     for (i = 0; !ret && types[i]; i++)
708         ret = CRYPT_EncodeValueWithType(dwCertEncodingType, value, output,
709          types[i], ppszError);
710     return ret;
711 }
712 
713 static BOOL CRYPT_ValueToRDN(DWORD dwCertEncodingType, PCERT_NAME_INFO info,
714  PCCRYPT_OID_INFO keyOID, struct X500TokenW *value, LPCWSTR *ppszError)
715 {
716     BOOL ret = FALSE;
717 
718     TRACE("OID %s, value %s\n", debugstr_a(keyOID->pszOID),
719      debugstr_wn(value->start, value->end - value->start));
720 
721     if (!info->rgRDN)
722         info->rgRDN = CryptMemAlloc(sizeof(CERT_RDN));
723     else
724         info->rgRDN = CryptMemRealloc(info->rgRDN,
725          (info->cRDN + 1) * sizeof(CERT_RDN));
726     if (info->rgRDN)
727     {
728         /* FIXME: support multiple RDN attrs */
729         info->rgRDN[info->cRDN].rgRDNAttr =
730          CryptMemAlloc(sizeof(CERT_RDN_ATTR));
731         if (info->rgRDN[info->cRDN].rgRDNAttr)
732         {
733             static const DWORD defaultTypes[] = { CERT_RDN_PRINTABLE_STRING,
734              CERT_RDN_BMP_STRING, 0 };
735             const DWORD *types;
736 
737             info->rgRDN[info->cRDN].cRDNAttr = 1;
738             info->rgRDN[info->cRDN].rgRDNAttr[0].pszObjId =
739              (LPSTR)keyOID->pszOID;
740             info->rgRDN[info->cRDN].rgRDNAttr[0].dwValueType =
741              CERT_RDN_ENCODED_BLOB;
742             if (keyOID->ExtraInfo.cbData)
743                 types = (const DWORD *)keyOID->ExtraInfo.pbData;
744             else
745                 types = defaultTypes;
746 
747             /* Remove surrounding quotes */
748             if (value->start[0] == '"')
749             {
750                 value->start++;
751                 value->end--;
752             }
753             ret = CRYPT_EncodeValue(dwCertEncodingType, value,
754              &info->rgRDN[info->cRDN].rgRDNAttr[0].Value, types, ppszError);
755         }
756         else
757             SetLastError(ERROR_OUTOFMEMORY);
758         info->cRDN++;
759     }
760     else
761         SetLastError(ERROR_OUTOFMEMORY);
762     return ret;
763 }
764 
765 BOOL WINAPI CertStrToNameW(DWORD dwCertEncodingType, LPCWSTR pszX500,
766  DWORD dwStrType, void *pvReserved, BYTE *pbEncoded, DWORD *pcbEncoded,
767  LPCWSTR *ppszError)
768 {
769     CERT_NAME_INFO info = { 0, NULL };
770     LPCWSTR str;
771     struct KeynameKeeper keeper;
772     DWORD i;
773     BOOL ret = TRUE;
774 
775     TRACE("(%08x, %s, %08x, %p, %p, %p, %p)\n", dwCertEncodingType,
776      debugstr_w(pszX500), dwStrType, pvReserved, pbEncoded, pcbEncoded,
777      ppszError);
778 
779     CRYPT_InitializeKeynameKeeper(&keeper);
780     str = pszX500;
781     while (str && *str && ret)
782     {
783         struct X500TokenW token;
784 
785         ret = CRYPT_GetNextKeyW(str, &token, ppszError);
786         if (ret && token.start)
787         {
788             PCCRYPT_OID_INFO keyOID;
789 
790             CRYPT_KeynameKeeperFromTokenW(&keeper, &token);
791             keyOID = CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY, keeper.keyName,
792              CRYPT_RDN_ATTR_OID_GROUP_ID);
793             if (!keyOID)
794             {
795                 if (ppszError)
796                     *ppszError = token.start;
797                 SetLastError(CRYPT_E_INVALID_X500_STRING);
798                 ret = FALSE;
799             }
800             else
801             {
802                 str = token.end;
803                 while (isspace(*str))
804                     str++;
805                 if (*str != '=')
806                 {
807                     if (ppszError)
808                         *ppszError = str;
809                     SetLastError(CRYPT_E_INVALID_X500_STRING);
810                     ret = FALSE;
811                 }
812                 else
813                 {
814                     static const WCHAR commaSep[] = { ',',0 };
815                     static const WCHAR semiSep[] = { ';',0 };
816                     static const WCHAR crlfSep[] = { '\r','\n',0 };
817                     static const WCHAR allSeps[] = { ',',';','\r','\n',0 };
818                     LPCWSTR sep;
819 
820                     str++;
821                     if (dwStrType & CERT_NAME_STR_COMMA_FLAG)
822                         sep = commaSep;
823                     else if (dwStrType & CERT_NAME_STR_SEMICOLON_FLAG)
824                         sep = semiSep;
825                     else if (dwStrType & CERT_NAME_STR_CRLF_FLAG)
826                         sep = crlfSep;
827                     else
828                         sep = allSeps;
829                     ret = CRYPT_GetNextValueW(str, dwStrType, sep, &token,
830                      ppszError);
831                     if (ret)
832                     {
833                         str = token.end;
834                         ret = CRYPT_ValueToRDN(dwCertEncodingType, &info,
835                          keyOID, &token, ppszError);
836                     }
837                 }
838             }
839         }
840     }
841     CRYPT_FreeKeynameKeeper(&keeper);
842     if (ret)
843     {
844         if (ppszError)
845             *ppszError = NULL;
846         ret = CryptEncodeObjectEx(dwCertEncodingType, X509_NAME, &info,
847          0, NULL, pbEncoded, pcbEncoded);
848     }
849     for (i = 0; i < info.cRDN; i++)
850     {
851         DWORD j;
852 
853         for (j = 0; j < info.rgRDN[i].cRDNAttr; j++)
854             LocalFree(info.rgRDN[i].rgRDNAttr[j].Value.pbData);
855         CryptMemFree(info.rgRDN[i].rgRDNAttr);
856     }
857     CryptMemFree(info.rgRDN);
858     return ret;
859 }
860 
861 DWORD WINAPI CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
862  DWORD dwFlags, void *pvTypePara, LPSTR pszNameString, DWORD cchNameString)
863 {
864     DWORD ret;
865 
866     TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType, dwFlags,
867      pvTypePara, pszNameString, cchNameString);
868 
869     if (pszNameString)
870     {
871         LPWSTR wideName;
872         DWORD nameLen;
873 
874         nameLen = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
875          NULL, 0);
876         wideName = CryptMemAlloc(nameLen * sizeof(WCHAR));
877         if (wideName)
878         {
879             CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
880              wideName, nameLen);
881             nameLen = WideCharToMultiByte(CP_ACP, 0, wideName, nameLen,
882              pszNameString, cchNameString, NULL, NULL);
883             if (nameLen <= cchNameString)
884                 ret = nameLen;
885             else
886             {
887                 pszNameString[cchNameString - 1] = '\0';
888                 ret = cchNameString;
889             }
890             CryptMemFree(wideName);
891         }
892         else
893         {
894             *pszNameString = '\0';
895             ret = 1;
896         }
897     }
898     else
899         ret = CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara,
900          NULL, 0);
901     return ret;
902 }
903 
904 DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType,
905  DWORD dwFlags, void *pvTypePara, LPWSTR pszNameString, DWORD cchNameString)
906 {
907     DWORD ret;
908     PCERT_NAME_BLOB name;
909     LPCSTR altNameOID;
910 
911     TRACE("(%p, %d, %08x, %p, %p, %d)\n", pCertContext, dwType,
912      dwFlags, pvTypePara, pszNameString, cchNameString);
913 
914     if (dwFlags & CERT_NAME_ISSUER_FLAG)
915     {
916         name = &pCertContext->pCertInfo->Issuer;
917         altNameOID = szOID_ISSUER_ALT_NAME;
918     }
919     else
920     {
921         name = &pCertContext->pCertInfo->Subject;
922         altNameOID = szOID_SUBJECT_ALT_NAME;
923     }
924 
925     switch (dwType)
926     {
927     case CERT_NAME_SIMPLE_DISPLAY_TYPE:
928     {
929         static const LPCSTR simpleAttributeOIDs[] = { szOID_COMMON_NAME,
930          szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME,
931          szOID_RSA_emailAddr };
932         CERT_NAME_INFO *info = NULL;
933         PCERT_RDN_ATTR nameAttr = NULL;
934         DWORD bytes = 0, i;
935 
936         if (CryptDecodeObjectEx(pCertContext->dwCertEncodingType, X509_NAME,
937          name->pbData, name->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &info,
938          &bytes))
939         {
940             for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
941              sizeof(simpleAttributeOIDs[0]); i++)
942                 nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
943         }
944         if (!nameAttr)
945         {
946             PCERT_EXTENSION ext = CertFindExtension(altNameOID,
947              pCertContext->pCertInfo->cExtension,
948              pCertContext->pCertInfo->rgExtension);
949 
950             if (ext)
951             {
952                 for (i = 0; !nameAttr && i < sizeof(simpleAttributeOIDs) /
953                  sizeof(simpleAttributeOIDs[0]); i++)
954                     nameAttr = CertFindRDNAttr(simpleAttributeOIDs[i], info);
955                 if (!nameAttr)
956                 {
957                     /* FIXME: gotta then look for a rfc822Name choice in ext.
958                      * Failing that, look for the first attribute.
959                      */
960                     FIXME("CERT_NAME_SIMPLE_DISPLAY_TYPE: stub\n");
961                 }
962             }
963         }
964         if (nameAttr)
965             ret = CertRDNValueToStrW(nameAttr->dwValueType, &nameAttr->Value,
966                                      pszNameString, cchNameString);
967         else
968             ret = 0;
969         if (info)
970             LocalFree(info);
971         break;
972     }
973     case CERT_NAME_FRIENDLY_DISPLAY_TYPE:
974     {
975         DWORD cch = cchNameString;
976 
977         if (CertGetCertificateContextProperty(pCertContext,
978          CERT_FRIENDLY_NAME_PROP_ID, pszNameString, &cch))
979             ret = cch;
980         else
981             ret = CertGetNameStringW(pCertContext,
982              CERT_NAME_SIMPLE_DISPLAY_TYPE, dwFlags, pvTypePara, pszNameString,
983              cchNameString);
984         break;
985     }
986     default:
987         FIXME("unimplemented for type %d\n", dwType);
988         ret = 0;
989     }
990     return ret;
991 }
992 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.