curl-library
curl bad verify SSL certificates (fwd)
From: Daniel Stenberg <daniel_at_haxx.se>
Date: Thu, 15 Aug 2002 09:48:38 +0200 (MET DST)
Date: Thu, 15 Aug 2002 09:48:38 +0200 (MET DST)
Hey crowd.
I would like to show you all what popped in on the bug tracker just now, and
I think my comments below illustrate my cluelessness in this issue. I'd
appreciate some assistance in this matter.
-- Daniel Stenberg -- curl related mails on curl related mailing lists please ---------- Forwarded message ---------- Date: Thu, 15 Aug 2002 00:38:31 -0700 From: noreply_at_sourceforge.net To: noreply_at_sourceforge.net Subject: [ curl-Bugs-595426 ] curl bad verify SSL certificates Bugs item #595426, was opened at 2002-08-15 09:18 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=100976&aid=595426&group_id=976 Category: https Group: wrong behaviour Status: Open Resolution: None >Priority: 9 Submitted By: Tom Zerucha (tomz) Assigned to: Daniel Stenberg (bagder) Summary: curl bad verify SSL certificates Initial Comment: http://www.thoughtcrime.org/ie-ssl-chain.txt The above describes the problem with IE, which curl is also vulnerable to. There are bits indicating if a cert can or cannot be used to sign other certs in the chain. In this case a cert which isn't allowed to sign other certs, but is used anyway, won't be detected, allowing "man in the middle" attacks. OpenSSL properly detects the anomaly if called properly, but the returned error needs to prevent a connection or return an error. The command line test app, openssl, s_client -connect www.amazon.com:443 returns an error 20 for a dnsspoof-ed www.amazon.com -> thoughtcrime.org, (it establishes the session anyway so you can connect) but curl https://www.amazon.com give no warning or error. Netscape and/or Mozilla don't have this problem, neither do some versions of Opera. Here is some verify callback code I used (several versions ago for an encrypting proxy for lynx). The key routine is the verify callback, but I've included the rest for completeness. Also the file for the encrypting proxy (edssl83.tgz) is attached. I have not verified this specifically, but it does contain the test. #define XBUFSIZ 16384 static char xferbuf[XBUFSIZ]; static char goodcerts[128] = "goodcerts"; static int debugflag = 0; static char hostname[256] = ""; static char thisuser[256]; static char error[256] = ""; static FILE *errlog = stderr; /* match common names using shell expressions */ int shellexp(char *t, char *m) { static char *lastx; int good; char *lastt, *tref; tref = t; lastt = t; while (*m) { good = 0; switch (*m) { case '~': return (!shellexp(tref, ++m)); case '$': return (!(*t)); #ifdef ALLOWILD case '*': while (*m && *m == '*') m++; if (!*m) return 1; while (*t) if (shellexp(t++, m)) return 1; return 0; case '[': { int revflag; if ((revflag = (*++m == '^'))) m++; while (!good && *m && *m != ']') { switch (*m) { case '-': if (*t >= m[-1] && *t <= m[1]) good = 1; m++; m++; break; case '\': if (!*++m) return 0; default: if (*++m == *t) good = 1; break; } } if (good == revflag) return 0; while (*m != ']') if (!*++m) return 0; } case '?': /* with fallthrough */ m++, t++; break; #endif case '(': do { m++; if (shellexp(t, m)) good = 1, lastt = lastx; while (*m && *m != ')' && *m != '|') m++; } while (*m == '|'); if (!good || *m++ != ')') return 0; t = lastt; break; case '|': case ')': lastx = t; return 1; case '\': if (!*++m) return 0; default: /* with fallthrough */ if (tolower(*m++) != tolower(*t++)) return 0; } } return (!(*t)); } /* override bad cert */ int goodover(char *tstcname) { char cbuf[255]; int n; FILE *tmpfd; /* look for good cert override: file format is oneline-space-hostname */ cbuf[0] = 0; n = strlen(tstcname); tmpfd = fopen(goodcerts, "r"); if (tmpfd != NULL) { while (!feof(tmpfd)) { fgets(cbuf, 255, tmpfd); if (!strncasecmp(tstcname, cbuf, n) && !strncasecmp(hostname, &cbuf[n + 1], strlen(hostname))) break; } fclose(tmpfd); } return (!strncasecmp(tstcname, cbuf, n) && !strncasecmp(hostname, &cbuf[n + 1], strlen(hostname))); } /* match cert oneline v.s. hostname */ int namematch(char *tstcname, char *hostname) { char *cp; char cbuf[255]; int n; if (goodover(tstcname)) return 1; cp = strstr(tstcname, "/CN="); /* move to common name */ if (cp == NULL) return 0; cbuf[0] = '\0'; cp += 4; n = strlen(hostname); strcpy(cbuf, cp); if ((cp = strchr(cbuf, '/'))) *cp = '\0'; return (shellexp(hostname, cbuf)); } #include "buffer.h" #include "ssl.h" #include "err.h" #include "pem.h" #include "x509.h" static struct hostent *hostres; static int verify_depth = 0; static int verify_error = X509_V_OK; /* should be X509 * but we can just have them as char *. */ int verify_callback(ok, ctx) int ok; X509_STORE_CTX *ctx; { char buf[256]; X509 *err_cert; int err, depth; BIO *bio_err = BIO_new(BIO_s_file()); BIO_set_fp(bio_err, errlog, BIO_NOCLOSE); err_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); if (depth == 0) strncpy(thisuser, buf, 255); if (ok && depth == 0 && !goodover(thisuser) && !namematch(thisuser, hostname)) { /* proxy SSL to remote secure server - verify server host */ sprintf(error, "Host:%s != Cert:%s", hostname, thisuser); BIO_printf(bio_err, "ERROR: Hostname [%s] != Name in cert\n", hostname); ok = 0; } if (!ok && goodover(thisuser)) ok = 1; if (!debugflag && ok == 1 && err < 2) return (ok); ERR_load_crypto_strings(), SSL_load_error_strings(); if (hostres) BIO_printf(bio_err, "Reverse DNS hostname: %s\n", hostres->h_name); BIO_printf(bio_err, "SSL CERTIFICATE STATUS: ok=%d depth=%d err=%s(%d)\n", ok, depth, X509_verify_cert_error_string(err), err); BIO_printf(bio_err, "Subject Cert Oneline:\n%s %s\n", thisuser, hostname); if (!ok) { if (verify_depth > depth) verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG; else ok++, verify_error = X509_V_OK; } switch (ctx->error) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); BIO_printf(bio_err, "unknown issuer= %s\n", buf); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: BIO_printf(bio_err, "notBefore="); ASN1_UTCTIME_print(bio_err, X509_get_notBefore(ctx->current_cert)); BIO_printf(bio_err, "\n"); break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: BIO_printf(bio_err, "notAfter="); ASN1_UTCTIME_print(bio_err, X509_get_notAfter(ctx->current_cert)); BIO_printf(bio_err, "\n"); break; } return (ok); } /* convert string (dns or dotted decimal) to address */ int getaddr(char *toaddr, struct sockaddr_in *sin) { long n; n = inet_addr(toaddr); if (n != INADDR_NONE) memcpy(&sin->sin_addr, &n, sizeof(n)); else { hostres = gethostbyname(toaddr); if (hostres == NULL) return 1; memcpy(&sin->sin_addr, hostres->h_addr, hostres->h_length); } hostres = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET); return 0; } ---------------------------------------------------------------------- >Comment By: Daniel Stenberg (bagder) Date: 2002-08-15 09:38 Message: Logged In: YES user_id=1110 I'm sorry, but I don't understand much of this talk. I'm quite far away from an expert on SSL or certificate issues, I'm probably stupid and I think I need the problem more spelled out in my face. I did however see the posting on bugtraq previously when this issue came up, saying that curl _isn't_ vulnerable: http://online.securityfocus.com/archive/1/286892 Your submitted code does a lot of various things. Are you suggesting that reading files, matching lines using a miniature regex engine etc is what this issue *requires* in order to get solved? I'm puzzeled, but of course dedicated to have any existing problems of this nature fixed ASAP. I would appreciate if we could move further dicussions of this issue to the libcurl mailing list, as there might be more cluefull people around there than that read this single bug report. Thanks for bringing the issue up. Let's make a fix. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=100976&aid=595426&group_id=976 ------------------------------------------------------- This sf.net email is sponsored by: OSDN - Tired of that same old cell phone? Get a new here for FREE! https://www.inphonic.com/r.asp?r=sourceforge1&refcode1=vs3390Received on 2002-08-15