⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 openssl.c

📁 Wget很好的处理了http和ftp的下载,很值得学习的经典代码
💻 C
📖 第 1 页 / 共 2 页
字号:
         && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL         && errno == EINTR);  return ret;}static const char *openssl_errstr (int fd, void *arg){  struct openssl_transport_context *ctx = arg;  unsigned long errcode;  char *errmsg = NULL;  int msglen = 0;  /* If there are no SSL-specific errors, just return NULL. */  if ((errcode = ERR_get_error ()) == 0)    return NULL;  /* Get rid of previous contents of ctx->last_error, if any.  */  xfree_null (ctx->last_error);  /* Iterate over OpenSSL's error stack and accumulate errors in the     last_error buffer, separated by "; ".  This is better than using     a static buffer, which *always* takes up space (and has to be     large, to fit more than one error message), whereas these     allocations are only performed when there is an actual error.  */  for (;;)    {      const char *str = ERR_error_string (errcode, NULL);      int len = strlen (str);      /* Allocate space for the existing message, plus two more chars         for the "; " separator and one for the terminating \0.  */      errmsg = xrealloc (errmsg, msglen + len + 2 + 1);      memcpy (errmsg + msglen, str, len);      msglen += len;      /* Get next error and bail out if there are no more. */      errcode = ERR_get_error ();      if (errcode == 0)        break;      errmsg[msglen++] = ';';      errmsg[msglen++] = ' ';    }  errmsg[msglen] = '\0';  /* Store the error in ctx->last_error where openssl_close will     eventually find it and free it.  */  ctx->last_error = errmsg;  return errmsg;}static voidopenssl_close (int fd, void *arg){  struct openssl_transport_context *ctx = arg;  SSL *conn = ctx->conn;  SSL_shutdown (conn);  SSL_free (conn);  xfree_null (ctx->last_error);  xfree (ctx);#if defined(WINDOWS) || defined(MSDOS)  closesocket (fd);#else  close (fd);#endif  DEBUGP (("Closed %d/SSL 0x%0*lx\n", fd, PTR_FORMAT (conn)));}/* openssl_transport is the singleton that describes the SSL transport   methods provided by this file.  */static struct transport_implementation openssl_transport = {  openssl_read, openssl_write, openssl_poll,  openssl_peek, openssl_errstr, openssl_close};/* Perform the SSL handshake on file descriptor FD, which is assumed   to be connected to an SSL server.  The SSL handle provided by   OpenSSL is registered with the file descriptor FD using   fd_register_transport, so that subsequent calls to fd_read,   fd_write, etc., will use the corresponding SSL functions.   Returns true on success, false on failure.  */boolssl_connect (int fd) {  SSL *conn;  struct openssl_transport_context *ctx;  DEBUGP (("Initiating SSL handshake.\n"));  assert (ssl_ctx != NULL);  conn = SSL_new (ssl_ctx);  if (!conn)    goto error;  if (!SSL_set_fd (conn, fd))    goto error;  SSL_set_connect_state (conn);  if (SSL_connect (conn) <= 0 || conn->state != SSL_ST_OK)    goto error;  ctx = xnew0 (struct openssl_transport_context);  ctx->conn = conn;  /* Register FD with Wget's transport layer, i.e. arrange that our     functions are used for reading, writing, and polling.  */  fd_register_transport (fd, &openssl_transport, ctx);  DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n",           fd, PTR_FORMAT (conn)));  return true; error:  DEBUGP (("SSL handshake failed.\n"));  print_errors ();  if (conn)    SSL_free (conn);  return false;}#define ASTERISK_EXCLUDES_DOT   /* mandated by rfc2818 *//* Return true is STRING (case-insensitively) matches PATTERN, false   otherwise.  The recognized wildcard character is "*", which matches   any character in STRING except ".".  Any number of the "*" wildcard   may be present in the pattern.   This is used to match of hosts as indicated in rfc2818: "Names may   contain the wildcard character * which is considered to match any   single domain name component or component fragment. E.g., *.a.com   matches foo.a.com but not bar.foo.a.com. f*.com matches foo.com but   not bar.com [or foo.bar.com]."   If the pattern contain no wildcards, pattern_match(a, b) is   equivalent to !strcasecmp(a, b).  */static boolpattern_match (const char *pattern, const char *string){  const char *p = pattern, *n = string;  char c;  for (; (c = TOLOWER (*p++)) != '\0'; n++)    if (c == '*')      {        for (c = TOLOWER (*p); c == '*'; c = TOLOWER (*++p))          ;        for (; *n != '\0'; n++)          if (TOLOWER (*n) == c && pattern_match (p, n))            return true;#ifdef ASTERISK_EXCLUDES_DOT          else if (*n == '.')            return false;#endif        return c == '\0';      }    else      {        if (c != TOLOWER (*n))          return false;      }  return *n == '\0';}/* Verify the validity of the certificate presented by the server.   Also check that the "common name" of the server, as presented by   its certificate, corresponds to HOST.  (HOST typically comes from   the URL and is what the user thinks he's connecting to.)   This assumes that ssl_connect has successfully finished, i.e. that   the SSL handshake has been performed and that FD is connected to an   SSL handle.   If opt.check_cert is true (the default), this returns 1 if the   certificate is valid, 0 otherwise.  If opt.check_cert is 0, the   function always returns 1, but should still be called because it   warns the user about any problems with the certificate.  */boolssl_check_certificate (int fd, const char *host){  X509 *cert;  char common_name[256];  long vresult;  bool success = true;  /* If the user has specified --no-check-cert, we still want to warn     him about problems with the server's certificate.  */  const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");  struct openssl_transport_context *ctx = fd_transport_context (fd);  SSL *conn = ctx->conn;  assert (conn != NULL);  cert = SSL_get_peer_certificate (conn);  if (!cert)    {      logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),                 severity, escnonprint (host));      success = false;      goto no_cert;             /* must bail out since CERT is NULL */    }  IF_DEBUG    {      char *subject = X509_NAME_oneline (X509_get_subject_name (cert), 0, 0);      char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);      DEBUGP (("certificate:\n  subject: %s\n  issuer:  %s\n",               escnonprint (subject), escnonprint (issuer)));      OPENSSL_free (subject);      OPENSSL_free (issuer);    }  vresult = SSL_get_verify_result (conn);  if (vresult != X509_V_OK)    {      char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);      logprintf (LOG_NOTQUIET,                 _("%s: cannot verify %s's certificate, issued by `%s':\n"),                 severity, escnonprint (host), escnonprint (issuer));      /* Try to print more user-friendly (and translated) messages for         the frequent verification errors.  */      switch (vresult)        {        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:          logprintf (LOG_NOTQUIET,                     _("  Unable to locally verify the issuer's authority.\n"));          break;        case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:          logprintf (LOG_NOTQUIET, _("  Self-signed certificate encountered.\n"));          break;        case X509_V_ERR_CERT_NOT_YET_VALID:          logprintf (LOG_NOTQUIET, _("  Issued certificate not yet valid.\n"));          break;        case X509_V_ERR_CERT_HAS_EXPIRED:          logprintf (LOG_NOTQUIET, _("  Issued certificate has expired.\n"));          break;        default:          /* For the less frequent error strings, simply provide the             OpenSSL error message.  */          logprintf (LOG_NOTQUIET, "  %s\n",                     X509_verify_cert_error_string (vresult));        }      success = false;      /* Fall through, so that the user is warned about *all* issues         with the cert (important with --no-check-certificate.)  */    }  /* Check that HOST matches the common name in the certificate.     #### The following remains to be done:     - It should use dNSName/ipAddress subjectAltName extensions if       available; according to rfc2818: "If a subjectAltName extension       of type dNSName is present, that MUST be used as the identity."     - When matching against common names, it should loop over all       common names and choose the most specific one, i.e. the last       one, not the first one, which the current code picks.     - Ensure that ASN1 strings from the certificate are encoded as       UTF-8 which can be meaningfully compared to HOST.  */  common_name[0] = '\0';  X509_NAME_get_text_by_NID (X509_get_subject_name (cert),                             NID_commonName, common_name, sizeof (common_name));  if (!pattern_match (common_name, host))    {      logprintf (LOG_NOTQUIET, _("\%s: certificate common name `%s' doesn't match requested host name `%s'.\n"),                 severity, escnonprint (common_name), escnonprint (host));      success = false;    }  if (success)    DEBUGP (("X509 certificate successfully verified and matches host %s\n",             escnonprint (host)));  X509_free (cert); no_cert:  if (opt.check_cert && !success)    logprintf (LOG_NOTQUIET, _("\To connect to %s insecurely, use `--no-check-certificate'.\n"),               escnonprint (host));  /* Allow --no-check-cert to disable certificate checking. */  return opt.check_cert ? success : true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -