00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
00026 defined(USE_CYASSL) || defined(USE_SCHANNEL)
00027
00028 #include <curl/curl.h>
00029 #include "urldata.h"
00030 #include "strcase.h"
00031 #include "hostcheck.h"
00032 #include "vtls/vtls.h"
00033 #include "sendf.h"
00034 #include "inet_pton.h"
00035 #include "curl_base64.h"
00036 #include "x509asn1.h"
00037
00038
00039 #include "curl_printf.h"
00040 #include "curl_memory.h"
00041 #include "memdebug.h"
00042
00043
00044 #define CURL_SIZE_T_MAX ((size_t)-1)
00045
00046
00047
00048 static const char cnOID[] = "2.5.4.3";
00049 static const char sanOID[] = "2.5.29.17";
00050
00051 static const curl_OID OIDtable[] = {
00052 { "1.2.840.10040.4.1", "dsa" },
00053 { "1.2.840.10040.4.3", "dsa-with-sha1" },
00054 { "1.2.840.10045.2.1", "ecPublicKey" },
00055 { "1.2.840.10045.3.0.1", "c2pnb163v1" },
00056 { "1.2.840.10045.4.1", "ecdsa-with-SHA1" },
00057 { "1.2.840.10046.2.1", "dhpublicnumber" },
00058 { "1.2.840.113549.1.1.1", "rsaEncryption" },
00059 { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" },
00060 { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" },
00061 { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" },
00062 { "1.2.840.113549.1.1.10", "RSASSA-PSS" },
00063 { "1.2.840.113549.1.1.14", "sha224WithRSAEncryption" },
00064 { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" },
00065 { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" },
00066 { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" },
00067 { "1.2.840.113549.2.2", "md2" },
00068 { "1.2.840.113549.2.5", "md5" },
00069 { "1.3.14.3.2.26", "sha1" },
00070 { cnOID, "CN" },
00071 { "2.5.4.4", "SN" },
00072 { "2.5.4.5", "serialNumber" },
00073 { "2.5.4.6", "C" },
00074 { "2.5.4.7", "L" },
00075 { "2.5.4.8", "ST" },
00076 { "2.5.4.9", "streetAddress" },
00077 { "2.5.4.10", "O" },
00078 { "2.5.4.11", "OU" },
00079 { "2.5.4.12", "title" },
00080 { "2.5.4.13", "description" },
00081 { "2.5.4.17", "postalCode" },
00082 { "2.5.4.41", "name" },
00083 { "2.5.4.42", "givenName" },
00084 { "2.5.4.43", "initials" },
00085 { "2.5.4.44", "generationQualifier" },
00086 { "2.5.4.45", "X500UniqueIdentifier" },
00087 { "2.5.4.46", "dnQualifier" },
00088 { "2.5.4.65", "pseudonym" },
00089 { "1.2.840.113549.1.9.1", "emailAddress" },
00090 { "2.5.4.72", "role" },
00091 { sanOID, "subjectAltName" },
00092 { "2.5.29.18", "issuerAltName" },
00093 { "2.5.29.19", "basicConstraints" },
00094 { "2.16.840.1.101.3.4.2.4", "sha224" },
00095 { "2.16.840.1.101.3.4.2.1", "sha256" },
00096 { "2.16.840.1.101.3.4.2.2", "sha384" },
00097 { "2.16.840.1.101.3.4.2.3", "sha512" },
00098 { (const char *) NULL, (const char *) NULL }
00099 };
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 const char *Curl_getASN1Element(curl_asn1Element *elem,
00112 const char *beg, const char *end)
00113 {
00114 unsigned char b;
00115 unsigned long len;
00116 curl_asn1Element lelem;
00117
00118
00119
00120
00121
00122 if(!beg || !end || beg >= end || !*beg ||
00123 (size_t)(end - beg) > CURL_ASN1_MAX)
00124 return (const char *) NULL;
00125
00126
00127 elem->header = beg;
00128 b = (unsigned char) *beg++;
00129 elem->constructed = (b & 0x20) != 0;
00130 elem->class = (b >> 6) & 3;
00131 b &= 0x1F;
00132 if(b == 0x1F)
00133 return (const char *) NULL;
00134 elem->tag = b;
00135
00136
00137 if(beg >= end)
00138 return (const char *) NULL;
00139 b = (unsigned char) *beg++;
00140 if(!(b & 0x80))
00141 len = b;
00142 else if(!(b &= 0x7F)) {
00143
00144
00145 if(!elem->constructed)
00146 return (const char *) NULL;
00147 elem->beg = beg;
00148 while(beg < end && *beg) {
00149 beg = Curl_getASN1Element(&lelem, beg, end);
00150 if(!beg)
00151 return (const char *) NULL;
00152 }
00153 if(beg >= end)
00154 return (const char *) NULL;
00155 elem->end = beg;
00156 return beg + 1;
00157 }
00158 else if((unsigned)b > (size_t)(end - beg))
00159 return (const char *) NULL;
00160 else {
00161
00162 len = 0;
00163 do {
00164 if(len & 0xFF000000L)
00165 return (const char *) NULL;
00166 len = (len << 8) | (unsigned char) *beg++;
00167 } while(--b);
00168 }
00169 if(len > (size_t)(end - beg))
00170 return (const char *) NULL;
00171 elem->beg = beg;
00172 elem->end = beg + len;
00173 return elem->end;
00174 }
00175
00176 static const curl_OID * searchOID(const char *oid)
00177 {
00178 const curl_OID *op;
00179
00180
00181
00182
00183 for(op = OIDtable; op->numoid; op++)
00184 if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid))
00185 return op;
00186
00187 return (const curl_OID *) NULL;
00188 }
00189
00190 static const char *bool2str(const char *beg, const char *end)
00191 {
00192
00193
00194
00195
00196 if(end - beg != 1)
00197 return (const char *) NULL;
00198 return strdup(*beg? "TRUE": "FALSE");
00199 }
00200
00201 static const char *octet2str(const char *beg, const char *end)
00202 {
00203 size_t n = end - beg;
00204 char *buf = NULL;
00205
00206
00207
00208
00209 if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
00210 buf = malloc(3 * n + 1);
00211 if(buf)
00212 for(n = 0; beg < end; n += 3)
00213 snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
00214 }
00215 return buf;
00216 }
00217
00218 static const char *bit2str(const char *beg, const char *end)
00219 {
00220
00221
00222
00223 if(++beg > end)
00224 return (const char *) NULL;
00225 return octet2str(beg, end);
00226 }
00227
00228 static const char *int2str(const char *beg, const char *end)
00229 {
00230 long val = 0;
00231 size_t n = end - beg;
00232
00233
00234
00235
00236
00237 if(!n)
00238 return (const char *) NULL;
00239
00240 if(n > 4)
00241 return octet2str(beg, end);
00242
00243
00244 if(*beg & 0x80)
00245 val = ~val;
00246
00247 do
00248 val = (val << 8) | *(const unsigned char *) beg++;
00249 while(beg < end);
00250 return curl_maprintf("%s%lx", (val < 0 || val >= 10)? "0x": "", val);
00251 }
00252
00253 static ssize_t
00254 utf8asn1str(char **to, int type, const char *from, const char *end)
00255 {
00256 size_t inlength = end - from;
00257 int size = 1;
00258 size_t outlength;
00259 int charsize;
00260 unsigned int wc;
00261 char *buf;
00262
00263
00264
00265
00266
00267
00268
00269 *to = (char *) NULL;
00270 switch(type) {
00271 case CURL_ASN1_BMP_STRING:
00272 size = 2;
00273 break;
00274 case CURL_ASN1_UNIVERSAL_STRING:
00275 size = 4;
00276 break;
00277 case CURL_ASN1_NUMERIC_STRING:
00278 case CURL_ASN1_PRINTABLE_STRING:
00279 case CURL_ASN1_TELETEX_STRING:
00280 case CURL_ASN1_IA5_STRING:
00281 case CURL_ASN1_VISIBLE_STRING:
00282 case CURL_ASN1_UTF8_STRING:
00283 break;
00284 default:
00285 return -1;
00286 }
00287
00288 if(inlength % size)
00289 return -1;
00290 if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4)
00291 return -1;
00292 buf = malloc(4 * (inlength / size) + 1);
00293 if(!buf)
00294 return -1;
00295
00296 if(type == CURL_ASN1_UTF8_STRING) {
00297
00298 outlength = inlength;
00299 if(outlength)
00300 memcpy(buf, from, outlength);
00301 }
00302 else {
00303 for(outlength = 0; from < end;) {
00304 wc = 0;
00305 switch(size) {
00306 case 4:
00307 wc = (wc << 8) | *(const unsigned char *) from++;
00308 wc = (wc << 8) | *(const unsigned char *) from++;
00309
00310 case 2:
00311 wc = (wc << 8) | *(const unsigned char *) from++;
00312
00313 default:
00314 wc = (wc << 8) | *(const unsigned char *) from++;
00315 }
00316 charsize = 1;
00317 if(wc >= 0x00000080) {
00318 if(wc >= 0x00000800) {
00319 if(wc >= 0x00010000) {
00320 if(wc >= 0x00200000) {
00321 free(buf);
00322 return -1;
00323 }
00324 buf[outlength + 3] = (char) (0x80 | (wc & 0x3F));
00325 wc = (wc >> 6) | 0x00010000;
00326 charsize++;
00327 }
00328 buf[outlength + 2] = (char) (0x80 | (wc & 0x3F));
00329 wc = (wc >> 6) | 0x00000800;
00330 charsize++;
00331 }
00332 buf[outlength + 1] = (char) (0x80 | (wc & 0x3F));
00333 wc = (wc >> 6) | 0x000000C0;
00334 charsize++;
00335 }
00336 buf[outlength] = (char) wc;
00337 outlength += charsize;
00338 }
00339 }
00340 buf[outlength] = '\0';
00341 *to = buf;
00342 return outlength;
00343 }
00344
00345 static const char *string2str(int type, const char *beg, const char *end)
00346 {
00347 char *buf;
00348
00349
00350
00351
00352 if(utf8asn1str(&buf, type, beg, end) < 0)
00353 return (const char *) NULL;
00354 return buf;
00355 }
00356
00357 static int encodeUint(char *buf, int n, unsigned int x)
00358 {
00359 int i = 0;
00360 unsigned int y = x / 10;
00361
00362
00363
00364
00365 if(y) {
00366 i += encodeUint(buf, n, y);
00367 x -= y * 10;
00368 }
00369 if(i < n)
00370 buf[i] = (char) ('0' + x);
00371 i++;
00372 if(i < n)
00373 buf[i] = '\0';
00374 return i;
00375 }
00376
00377 static int encodeOID(char *buf, int n, const char *beg, const char *end)
00378 {
00379 int i = 0;
00380 unsigned int x;
00381 unsigned int y;
00382
00383
00384
00385
00386
00387
00388 y = *(const unsigned char *) beg++;
00389 x = y / 40;
00390 y -= x * 40;
00391 i += encodeUint(buf + i, n - i, x);
00392 if(i < n)
00393 buf[i] = '.';
00394 i++;
00395 i += encodeUint(buf + i, n - i, y);
00396
00397
00398 while(beg < end) {
00399 if(i < n)
00400 buf[i] = '.';
00401 i++;
00402 x = 0;
00403 do {
00404 if(x & 0xFF000000)
00405 return -1;
00406 y = *(const unsigned char *) beg++;
00407 x = (x << 7) | (y & 0x7F);
00408 } while(y & 0x80);
00409 i += encodeUint(buf + i, n - i, x);
00410 }
00411 if(i < n)
00412 buf[i] = '\0';
00413 return i;
00414 }
00415
00416 static const char *OID2str(const char *beg, const char *end, bool symbolic)
00417 {
00418 char *buf = (char *) NULL;
00419 const curl_OID * op;
00420 int n;
00421
00422
00423
00424
00425 if(beg < end) {
00426 n = encodeOID((char *) NULL, -1, beg, end);
00427 if(n >= 0) {
00428 buf = malloc(n + 1);
00429 if(buf) {
00430 encodeOID(buf, n, beg, end);
00431 buf[n] = '\0';
00432
00433 if(symbolic) {
00434 op = searchOID(buf);
00435 if(op) {
00436 free(buf);
00437 buf = strdup(op->textoid);
00438 }
00439 }
00440 }
00441 }
00442 }
00443 return buf;
00444 }
00445
00446 static const char *GTime2str(const char *beg, const char *end)
00447 {
00448 const char *tzp;
00449 const char *fracp;
00450 char sec1, sec2;
00451 size_t fracl;
00452 size_t tzl;
00453 const char *sep = "";
00454
00455
00456
00457
00458 for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++)
00459 ;
00460
00461
00462 sec1 = '0';
00463 switch(fracp - beg - 12) {
00464 case 0:
00465 sec2 = '0';
00466 break;
00467 case 2:
00468 sec1 = fracp[-2];
00469 case 1:
00470 sec2 = fracp[-1];
00471 break;
00472 default:
00473 return (const char *) NULL;
00474 }
00475
00476
00477 tzp = fracp;
00478 fracl = 0;
00479 if(fracp < end && (*fracp == '.' || *fracp == ',')) {
00480 fracp++;
00481 do
00482 tzp++;
00483 while(tzp < end && *tzp >= '0' && *tzp <= '9');
00484
00485 for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--)
00486 ;
00487 }
00488
00489
00490 if(tzp >= end)
00491 ;
00492 else if(*tzp == 'Z') {
00493 tzp = " GMT";
00494 end = tzp + 4;
00495 }
00496 else {
00497 sep = " ";
00498 tzp++;
00499 }
00500
00501 tzl = end - tzp;
00502 return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
00503 beg, beg + 4, beg + 6,
00504 beg + 8, beg + 10, sec1, sec2,
00505 fracl? ".": "", fracl, fracp,
00506 sep, tzl, tzp);
00507 }
00508
00509 static const char *UTime2str(const char *beg, const char *end)
00510 {
00511 const char *tzp;
00512 size_t tzl;
00513 const char *sec;
00514
00515
00516
00517
00518 for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++)
00519 ;
00520
00521 sec = beg + 10;
00522 switch(tzp - sec) {
00523 case 0:
00524 sec = "00";
00525 case 2:
00526 break;
00527 default:
00528 return (const char *) NULL;
00529 }
00530
00531
00532 if(tzp >= end)
00533 return (const char *) NULL;
00534 if(*tzp == 'Z') {
00535 tzp = "GMT";
00536 end = tzp + 3;
00537 }
00538 else
00539 tzp++;
00540
00541 tzl = end - tzp;
00542 return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
00543 20 - (*beg >= '5'), beg, beg + 2, beg + 4,
00544 beg + 6, beg + 8, sec,
00545 tzl, tzp);
00546 }
00547
00548 const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
00549 {
00550
00551
00552
00553 if(elem->constructed)
00554 return (const char *) NULL;
00555
00556 if(!type)
00557 type = elem->tag;
00558
00559 switch(type) {
00560 case CURL_ASN1_BOOLEAN:
00561 return bool2str(elem->beg, elem->end);
00562 case CURL_ASN1_INTEGER:
00563 case CURL_ASN1_ENUMERATED:
00564 return int2str(elem->beg, elem->end);
00565 case CURL_ASN1_BIT_STRING:
00566 return bit2str(elem->beg, elem->end);
00567 case CURL_ASN1_OCTET_STRING:
00568 return octet2str(elem->beg, elem->end);
00569 case CURL_ASN1_NULL:
00570 return strdup("");
00571 case CURL_ASN1_OBJECT_IDENTIFIER:
00572 return OID2str(elem->beg, elem->end, TRUE);
00573 case CURL_ASN1_UTC_TIME:
00574 return UTime2str(elem->beg, elem->end);
00575 case CURL_ASN1_GENERALIZED_TIME:
00576 return GTime2str(elem->beg, elem->end);
00577 case CURL_ASN1_UTF8_STRING:
00578 case CURL_ASN1_NUMERIC_STRING:
00579 case CURL_ASN1_PRINTABLE_STRING:
00580 case CURL_ASN1_TELETEX_STRING:
00581 case CURL_ASN1_IA5_STRING:
00582 case CURL_ASN1_VISIBLE_STRING:
00583 case CURL_ASN1_UNIVERSAL_STRING:
00584 case CURL_ASN1_BMP_STRING:
00585 return string2str(type, elem->beg, elem->end);
00586 }
00587
00588 return (const char *) NULL;
00589 }
00590
00591 static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
00592 {
00593 curl_asn1Element rdn;
00594 curl_asn1Element atv;
00595 curl_asn1Element oid;
00596 curl_asn1Element value;
00597 size_t l = 0;
00598 const char *p1;
00599 const char *p2;
00600 const char *p3;
00601 const char *str;
00602
00603
00604
00605
00606 for(p1 = dn->beg; p1 < dn->end;) {
00607 p1 = Curl_getASN1Element(&rdn, p1, dn->end);
00608 for(p2 = rdn.beg; p2 < rdn.end;) {
00609 p2 = Curl_getASN1Element(&atv, p2, rdn.end);
00610 p3 = Curl_getASN1Element(&oid, atv.beg, atv.end);
00611 Curl_getASN1Element(&value, p3, atv.end);
00612 str = Curl_ASN1tostr(&oid, 0);
00613 if(!str)
00614 return -1;
00615
00616
00617
00618 if(l) {
00619 for(p3 = str; isupper(*p3); p3++)
00620 ;
00621 for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
00622 if(l < n)
00623 buf[l] = *p3;
00624 l++;
00625 }
00626 }
00627
00628
00629 for(p3 = str; *p3; p3++) {
00630 if(l < n)
00631 buf[l] = *p3;
00632 l++;
00633 }
00634 free((char *) str);
00635
00636
00637 if(l < n)
00638 buf[l] = '=';
00639 l++;
00640
00641
00642 str = Curl_ASN1tostr(&value, 0);
00643 if(!str)
00644 return -1;
00645 for(p3 = str; *p3; p3++) {
00646 if(l < n)
00647 buf[l] = *p3;
00648 l++;
00649 }
00650 free((char *) str);
00651 }
00652 }
00653
00654 return l;
00655 }
00656
00657 const char *Curl_DNtostr(curl_asn1Element *dn)
00658 {
00659 char *buf = (char *) NULL;
00660 ssize_t n = encodeDN(buf, 0, dn);
00661
00662
00663
00664
00665 if(n >= 0) {
00666 buf = malloc(n + 1);
00667 if(buf) {
00668 encodeDN(buf, n + 1, dn);
00669 buf[n] = '\0';
00670 }
00671 }
00672 return (const char *) buf;
00673 }
00674
00675
00676
00677
00678
00679 int Curl_parseX509(curl_X509certificate *cert,
00680 const char *beg, const char *end)
00681 {
00682 curl_asn1Element elem;
00683 curl_asn1Element tbsCertificate;
00684 const char *ccp;
00685 static const char defaultVersion = 0;
00686
00687
00688
00689
00690
00691 cert->certificate.header = NULL;
00692 cert->certificate.beg = beg;
00693 cert->certificate.end = end;
00694
00695
00696 if(!Curl_getASN1Element(&elem, beg, end))
00697 return -1;
00698 beg = elem.beg;
00699 end = elem.end;
00700
00701
00702 beg = Curl_getASN1Element(&tbsCertificate, beg, end);
00703
00704 beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
00705
00706 Curl_getASN1Element(&cert->signature, beg, end);
00707
00708
00709 beg = tbsCertificate.beg;
00710 end = tbsCertificate.end;
00711
00712 cert->version.header = NULL;
00713 cert->version.beg = &defaultVersion;
00714 cert->version.end = &defaultVersion + sizeof defaultVersion;;
00715 beg = Curl_getASN1Element(&elem, beg, end);
00716 if(elem.tag == 0) {
00717 Curl_getASN1Element(&cert->version, elem.beg, elem.end);
00718 beg = Curl_getASN1Element(&elem, beg, end);
00719 }
00720 cert->serialNumber = elem;
00721
00722 beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
00723
00724 beg = Curl_getASN1Element(&cert->issuer, beg, end);
00725
00726 beg = Curl_getASN1Element(&elem, beg, end);
00727 ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end);
00728 Curl_getASN1Element(&cert->notAfter, ccp, elem.end);
00729
00730 beg = Curl_getASN1Element(&cert->subject, beg, end);
00731
00732 beg = Curl_getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
00733 ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm,
00734 cert->subjectPublicKeyInfo.beg,
00735 cert->subjectPublicKeyInfo.end);
00736 Curl_getASN1Element(&cert->subjectPublicKey, ccp,
00737 cert->subjectPublicKeyInfo.end);
00738
00739 cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
00740 cert->extensions.tag = elem.tag = 0;
00741 cert->issuerUniqueID.header = cert->subjectUniqueID.header = NULL;
00742 cert->issuerUniqueID.beg = cert->issuerUniqueID.end = "";
00743 cert->subjectUniqueID.beg = cert->subjectUniqueID.end = "";
00744 cert->extensions.header = NULL;
00745 cert->extensions.beg = cert->extensions.end = "";
00746 if(beg < end)
00747 beg = Curl_getASN1Element(&elem, beg, end);
00748 if(elem.tag == 1) {
00749 cert->issuerUniqueID = elem;
00750 if(beg < end)
00751 beg = Curl_getASN1Element(&elem, beg, end);
00752 }
00753 if(elem.tag == 2) {
00754 cert->subjectUniqueID = elem;
00755 if(beg < end)
00756 beg = Curl_getASN1Element(&elem, beg, end);
00757 }
00758 if(elem.tag == 3)
00759 Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
00760 return 0;
00761 }
00762
00763 static size_t copySubstring(char *to, const char *from)
00764 {
00765 size_t i;
00766
00767
00768
00769
00770 for(i = 0; i < 64; i++) {
00771 to[i] = *from;
00772 if(!*from++)
00773 break;
00774 }
00775
00776 to[i++] = '\n';
00777 return i;
00778 }
00779
00780 static const char *dumpAlgo(curl_asn1Element *param,
00781 const char *beg, const char *end)
00782 {
00783 curl_asn1Element oid;
00784
00785
00786
00787 beg = Curl_getASN1Element(&oid, beg, end);
00788 param->header = NULL;
00789 param->tag = 0;
00790 param->beg = param->end = end;
00791 if(beg < end)
00792 Curl_getASN1Element(param, beg, end);
00793 return OID2str(oid.beg, oid.end, TRUE);
00794 }
00795
00796 static void do_pubkey_field(struct Curl_easy *data, int certnum,
00797 const char *label, curl_asn1Element *elem)
00798 {
00799 const char *output;
00800
00801
00802
00803 output = Curl_ASN1tostr(elem, 0);
00804 if(output) {
00805 if(data->set.ssl.certinfo)
00806 Curl_ssl_push_certinfo(data, certnum, label, output);
00807 if(!certnum)
00808 infof(data, " %s: %s\n", label, output);
00809 free((char *) output);
00810 }
00811 }
00812
00813 static void do_pubkey(struct Curl_easy *data, int certnum,
00814 const char *algo, curl_asn1Element *param,
00815 curl_asn1Element *pubkey)
00816 {
00817 curl_asn1Element elem;
00818 curl_asn1Element pk;
00819 const char *p;
00820 const char *q;
00821 unsigned long len;
00822 unsigned int i;
00823
00824
00825
00826
00827 Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
00828
00829 if(strcasecompare(algo, "rsaEncryption")) {
00830 p = Curl_getASN1Element(&elem, pk.beg, pk.end);
00831
00832 for(q = elem.beg; !*q && q < elem.end; q++)
00833 ;
00834 len = (unsigned long)((elem.end - q) * 8);
00835 if(len)
00836 for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1)
00837 len--;
00838 if(len > 32)
00839 elem.beg = q;
00840 if(!certnum)
00841 infof(data, " RSA Public Key (%lu bits)\n", len);
00842 if(data->set.ssl.certinfo) {
00843 q = curl_maprintf("%lu", len);
00844 if(q) {
00845 Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
00846 free((char *) q);
00847 }
00848 }
00849
00850 do_pubkey_field(data, certnum, "rsa(n)", &elem);
00851 Curl_getASN1Element(&elem, p, pk.end);
00852 do_pubkey_field(data, certnum, "rsa(e)", &elem);
00853 }
00854 else if(strcasecompare(algo, "dsa")) {
00855 p = Curl_getASN1Element(&elem, param->beg, param->end);
00856 do_pubkey_field(data, certnum, "dsa(p)", &elem);
00857 p = Curl_getASN1Element(&elem, p, param->end);
00858 do_pubkey_field(data, certnum, "dsa(q)", &elem);
00859 Curl_getASN1Element(&elem, p, param->end);
00860 do_pubkey_field(data, certnum, "dsa(g)", &elem);
00861 do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
00862 }
00863 else if(strcasecompare(algo, "dhpublicnumber")) {
00864 p = Curl_getASN1Element(&elem, param->beg, param->end);
00865 do_pubkey_field(data, certnum, "dh(p)", &elem);
00866 Curl_getASN1Element(&elem, param->beg, param->end);
00867 do_pubkey_field(data, certnum, "dh(g)", &elem);
00868 do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
00869 }
00870 #if 0
00871 else if(strcasecompare(algo, "ecPublicKey")) {
00872
00873 }
00874 #endif
00875 }
00876
00877 CURLcode Curl_extract_certinfo(struct connectdata *conn,
00878 int certnum,
00879 const char *beg,
00880 const char *end)
00881 {
00882 curl_X509certificate cert;
00883 struct Curl_easy *data = conn->data;
00884 curl_asn1Element param;
00885 const char *ccp;
00886 char *cp1;
00887 size_t cl1;
00888 char *cp2;
00889 CURLcode result;
00890 unsigned long version;
00891 size_t i;
00892 size_t j;
00893
00894 if(!data->set.ssl.certinfo)
00895 if(certnum)
00896 return CURLE_OK;
00897
00898
00899
00900
00901 if(Curl_parseX509(&cert, beg, end))
00902 return CURLE_OUT_OF_MEMORY;
00903
00904
00905 ccp = Curl_DNtostr(&cert.subject);
00906 if(!ccp)
00907 return CURLE_OUT_OF_MEMORY;
00908 if(data->set.ssl.certinfo)
00909 Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
00910 if(!certnum)
00911 infof(data, "%2d Subject: %s\n", certnum, ccp);
00912 free((char *) ccp);
00913
00914
00915 ccp = Curl_DNtostr(&cert.issuer);
00916 if(!ccp)
00917 return CURLE_OUT_OF_MEMORY;
00918 if(data->set.ssl.certinfo)
00919 Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
00920 if(!certnum)
00921 infof(data, " Issuer: %s\n", ccp);
00922 free((char *) ccp);
00923
00924
00925 version = 0;
00926 for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
00927 version = (version << 8) | *(const unsigned char *) ccp;
00928 if(data->set.ssl.certinfo) {
00929 ccp = curl_maprintf("%lx", version);
00930 if(!ccp)
00931 return CURLE_OUT_OF_MEMORY;
00932 Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
00933 free((char *) ccp);
00934 }
00935 if(!certnum)
00936 infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
00937
00938
00939 ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
00940 if(!ccp)
00941 return CURLE_OUT_OF_MEMORY;
00942 if(data->set.ssl.certinfo)
00943 Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
00944 if(!certnum)
00945 infof(data, " Serial Number: %s\n", ccp);
00946 free((char *) ccp);
00947
00948
00949 ccp = dumpAlgo(¶m, cert.signatureAlgorithm.beg,
00950 cert.signatureAlgorithm.end);
00951 if(!ccp)
00952 return CURLE_OUT_OF_MEMORY;
00953 if(data->set.ssl.certinfo)
00954 Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
00955 if(!certnum)
00956 infof(data, " Signature Algorithm: %s\n", ccp);
00957 free((char *) ccp);
00958
00959
00960 ccp = Curl_ASN1tostr(&cert.notBefore, 0);
00961 if(!ccp)
00962 return CURLE_OUT_OF_MEMORY;
00963 if(data->set.ssl.certinfo)
00964 Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
00965 if(!certnum)
00966 infof(data, " Start Date: %s\n", ccp);
00967 free((char *) ccp);
00968
00969
00970 ccp = Curl_ASN1tostr(&cert.notAfter, 0);
00971 if(!ccp)
00972 return CURLE_OUT_OF_MEMORY;
00973 if(data->set.ssl.certinfo)
00974 Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
00975 if(!certnum)
00976 infof(data, " Expire Date: %s\n", ccp);
00977 free((char *) ccp);
00978
00979
00980 ccp = dumpAlgo(¶m, cert.subjectPublicKeyAlgorithm.beg,
00981 cert.subjectPublicKeyAlgorithm.end);
00982 if(!ccp)
00983 return CURLE_OUT_OF_MEMORY;
00984 if(data->set.ssl.certinfo)
00985 Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp);
00986 if(!certnum)
00987 infof(data, " Public Key Algorithm: %s\n", ccp);
00988 do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey);
00989 free((char *) ccp);
00990
00991
00992
00993
00994 ccp = Curl_ASN1tostr(&cert.signature, 0);
00995 if(!ccp)
00996 return CURLE_OUT_OF_MEMORY;
00997 if(data->set.ssl.certinfo)
00998 Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
00999 if(!certnum)
01000 infof(data, " Signature: %s\n", ccp);
01001 free((char *) ccp);
01002
01003
01004 result = Curl_base64_encode(data, cert.certificate.beg,
01005 cert.certificate.end - cert.certificate.beg,
01006 &cp1, &cl1);
01007 if(result)
01008 return result;
01009
01010
01011
01012
01013
01014
01015
01016
01017 i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26;
01018 cp2 = malloc(i + 1);
01019 if(!cp2) {
01020 free(cp1);
01021 return CURLE_OUT_OF_MEMORY;
01022 }
01023
01024 i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----");
01025 for(j = 0; j < cl1; j += 64)
01026 i += copySubstring(cp2 + i, cp1 + j);
01027 i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
01028 cp2[i] = '\0';
01029 free(cp1);
01030 if(data->set.ssl.certinfo)
01031 Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
01032 if(!certnum)
01033 infof(data, "%s\n", cp2);
01034 free(cp2);
01035 return CURLE_OK;
01036 }
01037
01038 #endif
01039
01040 #if defined(USE_GSKIT)
01041
01042 static const char *checkOID(const char *beg, const char *end,
01043 const char *oid)
01044 {
01045 curl_asn1Element e;
01046 const char *ccp;
01047 const char *p;
01048 bool matched;
01049
01050
01051
01052
01053 ccp = Curl_getASN1Element(&e, beg, end);
01054 if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
01055 return (const char *) NULL;
01056
01057 p = OID2str(e.beg, e.end, FALSE);
01058 if(!p)
01059 return (const char *) NULL;
01060
01061 matched = !strcmp(p, oid);
01062 free((char *) p);
01063 return matched? ccp: (const char *) NULL;
01064 }
01065
01066 CURLcode Curl_verifyhost(struct connectdata *conn,
01067 const char *beg, const char *end)
01068 {
01069 struct Curl_easy *data = conn->data;
01070 curl_X509certificate cert;
01071 curl_asn1Element dn;
01072 curl_asn1Element elem;
01073 curl_asn1Element ext;
01074 curl_asn1Element name;
01075 const char *p;
01076 const char *q;
01077 char *dnsname;
01078 int matched = -1;
01079 size_t addrlen = (size_t) -1;
01080 ssize_t len;
01081 const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
01082 conn->host.name;
01083 const char * const dispname = SSL_IS_PROXY()?
01084 conn->http_proxy.host.dispname:
01085 conn->host.dispname;
01086 #ifdef ENABLE_IPV6
01087 struct in6_addr addr;
01088 #else
01089 struct in_addr addr;
01090 #endif
01091
01092
01093
01094
01095 if(!SSL_CONN_CONFIG(verifyhost))
01096 return CURLE_OK;
01097
01098 if(Curl_parseX509(&cert, beg, end))
01099 return CURLE_PEER_FAILED_VERIFICATION;
01100
01101
01102 #ifdef ENABLE_IPV6
01103 if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr))
01104 addrlen = sizeof(struct in6_addr);
01105 else
01106 #endif
01107 if(Curl_inet_pton(AF_INET, hostname, &addr))
01108 addrlen = sizeof(struct in_addr);
01109
01110
01111 for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
01112 p = Curl_getASN1Element(&ext, p, cert.extensions.end);
01113
01114 ext.beg = checkOID(ext.beg, ext.end, sanOID);
01115 if(ext.beg) {
01116 ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
01117
01118 if(elem.tag == CURL_ASN1_BOOLEAN)
01119 ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
01120
01121 Curl_getASN1Element(&elem, elem.beg, elem.end);
01122
01123 for(q = elem.beg; matched != 1 && q < elem.end;) {
01124 q = Curl_getASN1Element(&name, q, elem.end);
01125 switch(name.tag) {
01126 case 2:
01127 len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
01128 name.beg, name.end);
01129 if(len > 0 && (size_t)len == strlen(dnsname))
01130 matched = Curl_cert_hostcheck(dnsname, hostname);
01131 else
01132 matched = 0;
01133 free(dnsname);
01134 break;
01135
01136 case 7:
01137 matched = (size_t) (name.end - q) == addrlen &&
01138 !memcmp(&addr, q, addrlen);
01139 break;
01140 }
01141 }
01142 }
01143 }
01144
01145 switch(matched) {
01146 case 1:
01147
01148 infof(data, "\t subjectAltName: %s matched\n", dispname);
01149 return CURLE_OK;
01150 case 0:
01151
01152
01153 infof(data, "\t subjectAltName does not match %s\n", dispname);
01154 return CURLE_PEER_FAILED_VERIFICATION;
01155 }
01156
01157
01158 name.header = NULL;
01159 name.beg = name.end = "";
01160 q = cert.subject.beg;
01161
01162
01163 while(q < cert.subject.end) {
01164 q = Curl_getASN1Element(&dn, q, cert.subject.end);
01165 for(p = dn.beg; p < dn.end;) {
01166 p = Curl_getASN1Element(&elem, p, dn.end);
01167
01168 elem.beg = checkOID(elem.beg, elem.end, cnOID);
01169 if(elem.beg)
01170 name = elem;
01171 }
01172 }
01173
01174
01175 if(!Curl_getASN1Element(&elem, name.beg, name.end))
01176 failf(data, "SSL: unable to obtain common name from peer certificate");
01177 else {
01178 len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
01179 if(len < 0) {
01180 free(dnsname);
01181 return CURLE_OUT_OF_MEMORY;
01182 }
01183 if(strlen(dnsname) != (size_t) len)
01184 failf(data, "SSL: illegal cert name field");
01185 else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) {
01186 infof(data, "\t common name: %s (matched)\n", dnsname);
01187 free(dnsname);
01188 return CURLE_OK;
01189 }
01190 else
01191 failf(data, "SSL: certificate subject name '%s' does not match "
01192 "target host name '%s'", dnsname, dispname);
01193 free(dnsname);
01194 }
01195
01196 return CURLE_PEER_FAILED_VERIFICATION;
01197 }
01198
01199 #endif