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

📄 myssl_nss.c

📁 网络爬虫程序
💻 C
字号:
/***************************************************************************//*    This code is part of WWW grabber called pavuk                        *//*    Copyright (c) 1997 - 2001 Stefan Ondrejicka                          *//*    Distributed under GPL 2 or later                                     *//***************************************************************************/#include "config.h"#if defined(USE_SSL) && defined(USE_SSL_IMPL_NSS)#include <string.h>#include <time.h>#include <sys/ioctl.h>#include <secutil.h>#include <sslproto.h>#include "myssl.h"#include "http.h"#include "bufio.h"#include "errcode.h"#include "tools.h"#define PR_DESC_PAVUK_BUFIO 8static PRInt32 PR_CALLBACK myssl_bufio_avail(PRFileDesc * fd){  PRInt32 result;  bufio *sock;  sock = (bufio *) fd->secret;  if(ioctl(sock->fd, FIONREAD, &result) < 0)    result = -1;  else    result += sock->buf_end - sock->buf_start;  return result;}static PRInt64 PR_CALLBACK myssl_bufio_avail64(PRFileDesc * fd){  return myssl_bufio_avail(fd);}static PRStatus PR_CALLBACK myssl_bufio_close(PRFileDesc * fd){  return PR_SUCCESS;}static PRStatus PR_CALLBACK myssl_bufio_sync(PRFileDesc * fd){  return PR_SUCCESS;}static PRStatus PR_CALLBACK myssl_bufio_connect(PRFileDesc * fd,  const PRNetAddr * addr, PRIntervalTime timeout){  return PR_SUCCESS;}static PRInt32 PR_CALLBACK myssl_bufio_read(PRFileDesc * fd, void *buf,  PRInt32 len){  PRInt32 rv;  bufio *sock;  sock = (bufio *) fd->secret;  rv = bufio_nbfread(sock, buf, len);  return rv;}static PRInt32 PR_CALLBACK myssl_bufio_recv(PRFileDesc * fd, void *buf,  PRInt32 len, PRIntn flags, PRIntervalTime timeout){  return myssl_bufio_read(fd, buf, len);}static PRInt32 PR_CALLBACK myssl_bufio_write(PRFileDesc * fd, void *buf,  PRInt32 len){  PRInt32 rv;  bufio *sock;  sock = (bufio *) fd->secret;  rv = bufio_write(sock, buf, len);  return rv;}static PRInt32 PR_CALLBACK myssl_bufio_send(PRFileDesc * fd, void *buf,  PRInt32 len, PRIntn flags, PRIntervalTime timeout){  return myssl_bufio_write(fd, buf, len);}static PRInt16 PR_CALLBACK myssl_bufio_poll(PRFileDesc * fd, PRInt16 in_flags,  PRInt16 * out_flags){  *out_flags = 0;  if((in_flags & PR_POLL_READ) && myssl_bufio_avail(fd) > 0)    *out_flags = PR_POLL_READ;  return in_flags;}static PRStatus PR_CALLBACK myssl_bufio_getpeername(PRFileDesc * fd,  PRNetAddr * addr){  bufio *sock;  PRUint32 len;  len = sizeof(PRNetAddr);  sock = (bufio *) fd->secret;  if(!getpeername(bufio_getfd(sock), (struct sockaddr *) addr, &len))    return PR_SUCCESS;  else    return PR_FAILURE;}static PRStatus PR_CALLBACK myssl_bufio_getsockopt(PRFileDesc * fd,  PRSocketOptionData * data){  if(data->option == PR_SockOpt_Nonblocking)  {    data->value.non_blocking = FALSE;    return PR_SUCCESS;  }  return PR_FAILURE;}/* FIXME: externs should be in an include file */extern PRIntn _PR_InvalidInt(void);extern PRInt64 _PR_InvalidInt64(void);extern PRStatus _PR_InvalidStatus(void);extern PRFileDesc *_PR_InvalidDesc(void);static const PRIOMethods myssl_bufio_methods = {  PR_DESC_PAVUK_BUFIO,  myssl_bufio_close,  myssl_bufio_read,  myssl_bufio_write,  myssl_bufio_avail,  myssl_bufio_avail64,  myssl_bufio_sync,  (PRSeekFN) _PR_InvalidInt,  (PRSeek64FN) _PR_InvalidInt64,  (PRFileInfoFN) _PR_InvalidStatus,  (PRFileInfo64FN) _PR_InvalidStatus,  (PRWritevFN) _PR_InvalidInt,  myssl_bufio_connect,  (PRAcceptFN) _PR_InvalidDesc,  (PRBindFN) _PR_InvalidStatus,  (PRListenFN) _PR_InvalidStatus,  (PRShutdownFN) _PR_InvalidStatus,  myssl_bufio_recv,  myssl_bufio_send,  (PRRecvfromFN) _PR_InvalidInt,  (PRSendtoFN) _PR_InvalidInt,  (PRPollFN) myssl_bufio_poll,  (PRAcceptreadFN) _PR_InvalidInt,  (PRTransmitfileFN) _PR_InvalidInt,  (PRGetsocknameFN) _PR_InvalidStatus,  myssl_bufio_getpeername,  (PRReservedFN) _PR_InvalidInt,  (PRReservedFN) _PR_InvalidInt,  myssl_bufio_getsockopt,  (PRSetsocketoptionFN) _PR_InvalidStatus,  (PRSendfileFN) _PR_InvalidInt,  (PRReservedFN) _PR_InvalidInt,  (PRReservedFN) _PR_InvalidInt,  (PRReservedFN) _PR_InvalidInt,  (PRReservedFN) _PR_InvalidInt,  (PRReservedFN) _PR_InvalidInt,};static void myssl_bufio_init_io_layer(void){  static int inited = FALSE;  if(!inited)  {    myssl_bufio_methods.file_type = PR_GetUniqueIdentity("Pavuk_bufio");    inited = FALSE;  }  inited = TRUE;}static PRFileDesc *myssl_bufio_get_io_layer(void){  myssl_bufio_init_io_layer();  return PR_CreateIOLayerStub(myssl_bufio_methods.file_type,    &myssl_bufio_methods);}static PRFileDesc *myssl_bufio_new_socket(bufio * sock){  PRFileDesc *fd;  fd = myssl_bufio_get_io_layer();  fd->secret = (PRFilePrivate *) sock;  return fd;}static char *my_ssl_passwd_callback(PK11SlotInfo * slot, PRBool retry,  void *arg){  char *passwd = NULL;  if(!retry && arg)    passwd = PL_strdup((char *) arg);  return passwd;}static SECStatus my_ssl_verify_callback(void *arg, PRFileDesc * fd,  PRBool check_sig, PRBool is_server){  SECStatus rv;  CERTCertificate *cert;  cert = SSL_PeerCertificate(fd);  DEBUG_SSL("Subject: %s\n", cert->subjectName);  DEBUG_SSL("Issuer: %s\n", cert->issuerName);  rv = SSL_AuthCertificate(arg, fd, check_sig, is_server);  if(rv == SECSuccess)    DEBUG_SSL("SSL certificate valid.\n");  CERT_DestroyCertificate(cert);  return rv;}static SECStatus my_ssl_verify_failed_callback(void *arg, PRFileDesc * fd){  int err = PR_GetError();  DEBUG_SSL("SSL certificate invalid (%d).\n", err);  DEBUG_SSL("%s\n", SECU_Strerror(err));  return cfg.nss_accept_unknown_cert ? SECSuccess : SECFailure;}void my_ssl_init(void){}void my_ssl_init_once(void){  PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);}void my_ssl_init_start(void){  SECStatus rv;  char *certDir = priv_cfg.nss_cert_dir;  static bool_t called = FALSE;  if(called)    NSS_Shutdown();  else    called = TRUE;  if(!certDir)  {    /* Look in $SSL_DIR */    certDir = SECU_DefaultSSLDir();    /* call even if it's NULL */    certDir = SECU_ConfigDirectory(certDir);  }  DEBUG_SSL("myssl_nss: config dir %s\n", certDir ? certDir : "(null)");  if(priv_cfg.ssl_cert_passwd)    PK11_SetPasswordFunc(my_ssl_passwd_callback);  else    PK11_SetPasswordFunc(SECU_GetModulePassword);  rv = NSS_Init(certDir);  if(rv != SECSuccess)    xprintf(1, gettext("NSS_Init: Unable to open cert database"));  if(cfg.nss_domestic_policy)    NSS_SetDomesticPolicy();  else    NSS_SetExportPolicy();}void my_ssl_cleanup(void){  NSS_Shutdown();  PR_Cleanup();}void my_ssl_connection_close(ssl_connection * con){  if(con->fd)    PR_Close(con->fd);  if(con->socket)    bufio_close(con->socket);  con->fd = NULL;  con->socket = NULL;}void my_ssl_connection_destroy(ssl_connection * con){  my_ssl_connection_close(con);  _free(con);}static ssl_connection *my_ssl_connection_new(void){  ssl_connection *con;  con = _malloc(sizeof(ssl_connection));  con->fd = NULL;  con->socket = NULL;  return con;}static const struct{  int cipher;  char *name;} my_ssl_cipher_tab[] ={  {SSL_EN_RC4_128_WITH_MD5, "EN_RC4_128_WITH_MD5"},  {SSL_EN_RC4_128_EXPORT40_WITH_MD5, "EN_RC4_128_EXPORT40_WITH_MD5"},  {SSL_EN_RC2_128_CBC_WITH_MD5, "EN_RC2_128_CBC_WITH_MD5"},  {SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, "EN_RC2_128_CBC_EXPORT40_WITH_MD5"},  {SSL_EN_DES_64_CBC_WITH_MD5, "EN_DES_64_CBC_WITH_MD5"},  {SSL_EN_DES_192_EDE3_CBC_WITH_MD5, "EN_DES_192_EDE3_CBC_WITH_MD5"},  {SSL_NULL_WITH_NULL_NULL, "NULL_WITH_NULL_NULL"},  {SSL_RSA_WITH_NULL_MD5, "RSA_WITH_NULL_MD5"},  {SSL_RSA_WITH_NULL_SHA, "RSA_WITH_NULL_SHA"},  {SSL_RSA_EXPORT_WITH_RC4_40_MD5, "RSA_EXPORT_WITH_RC4_40_MD5"},  {SSL_RSA_WITH_RC4_128_MD5, "RSA_WITH_RC4_128_MD5"},  {SSL_RSA_WITH_RC4_128_SHA, "RSA_WITH_RC4_128_SHA"},  {SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "RSA_EXPORT_WITH_RC2_CBC_40_MD5"},  {SSL_RSA_WITH_IDEA_CBC_SHA, "RSA_WITH_IDEA_CBC_SHA"},  {SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, "RSA_EXPORT_WITH_DES40_CBC_SHA"},  {SSL_RSA_WITH_DES_CBC_SHA, "RSA_WITH_DES_CBC_SHA"},  {SSL_RSA_WITH_3DES_EDE_CBC_SHA, "RSA_WITH_3DES_EDE_CBC_SHA"},  {SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, "DH_DSS_EXPORT_WITH_DES40_CBC_SHA"},  {SSL_DH_DSS_WITH_DES_CBC_SHA, "DH_DSS_WITH_DES_CBC_SHA"},  {SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, "DH_DSS_WITH_3DES_EDE_CBC_SHA"},  {SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, "DH_RSA_EXPORT_WITH_DES40_CBC_SHA"},  {SSL_DH_RSA_WITH_DES_CBC_SHA, "DH_RSA_WITH_DES_CBC_SHA"},  {SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA, "DH_RSA_WITH_3DES_EDE_CBC_SHA"},  {SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, "DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"},  {SSL_DHE_DSS_WITH_DES_CBC_SHA, "DHE_DSS_WITH_DES_CBC_SHA"},  {SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, "DHE_DSS_WITH_3DES_EDE_CBC_SHA"},  {SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, "DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"},  {SSL_DHE_RSA_WITH_DES_CBC_SHA, "DHE_RSA_WITH_DES_CBC_SHA"},  {SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "DHE_RSA_WITH_3DES_EDE_CBC_SHA"},  {SSL_DH_ANON_EXPORT_WITH_RC4_40_MD5, "DH_ANON_EXPORT_WITH_RC4_40_MD5"},  {SSL_DH_ANON_WITH_RC4_128_MD5, "DH_ANON_WITH_RC4_128_MD5"},  {SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA, "DH_ANON_EXPORT_WITH_DES40_CBC_SHA"},  {SSL_DH_ANON_WITH_DES_CBC_SHA, "DH_ANON_WITH_DES_CBC_SHA"},  {SSL_DH_ANON_WITH_3DES_EDE_CBC_SHA, "DH_ANON_WITH_3DES_EDE_CBC_SHA"},  {SSL_FORTEZZA_DMS_WITH_NULL_SHA, "FORTEZZA_DMS_WITH_NULL_SHA"},  {SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,      "FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"},  {SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, "FORTEZZA_DMS_WITH_RC4_128_SHA"},  {TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, "RSA_EXPORT1024_WITH_DES_CBC_SHA"},  {TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, "RSA_EXPORT1024_WITH_RC4_56_SHA"},  {TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA,      "DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA"},  {TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA,      "DHE_DSS_EXPORT1024_WITH_RC4_56_SHA"},  {TLS_DHE_DSS_WITH_RC4_128_SHA, "DHE_DSS_WITH_RC4_128_SHA"},  {SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA, "RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA"},  {SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA, "RSA_OLDFIPS_WITH_DES_CBC_SHA"},  {SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, "RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},  {SSL_RSA_FIPS_WITH_DES_CBC_SHA, "RSA_FIPS_WITH_DES_CBC_SHA"}};static int my_ssl_get_cipher_by_name(char *n){  int i;  for(i = 0; i < NUM_ELEM(my_ssl_cipher_tab); i++)  {    if(!strcasecmp(n, my_ssl_cipher_tab[i].name))      return my_ssl_cipher_tab[i].cipher;  }  DEBUG_SSL("unknown NSS3 SSL cipher %s\n", n);  return -1;}static void my_ssl_set_ciphers(PRFileDesc * fd, char *ciphers){  char **c;  int cipher, i;  if(!strcasecmp(ciphers, "all"))    return;  c = tl_str_split(ciphers, ",");  /* at first disable all ciphers */  for(i = 0; i < NUM_ELEM(my_ssl_cipher_tab); i++)  {    cipher = my_ssl_cipher_tab[i].cipher;    if(fd)      SSL_CipherPrefSet(fd, cipher, SSL_NOT_ALLOWED);  }  for(i = 0; c && c[i]; i++)  {    cipher = my_ssl_get_cipher_by_name(c[i]);    if(cipher != -1 && fd)      SSL_CipherPrefSet(fd, cipher, SSL_ALLOWED);  }  tl_strv_free(c);}bufio *my_ssl_do_connect(doc * docp, bufio * socket,  ssl_connection * parent_ssl_con){  int rv;  ssl_connection *con;  PRFileDesc *model;  CERTCertDBHandle *handle;  my_ssl_init();  if(priv_cfg.ssl_proxy)  {    if(http_dumy_proxy_connect(docp,        url_get_site(docp->doc_url), url_get_port(docp->doc_url),        priv_cfg.ssl_proxy, cfg.ssl_proxy_port))    {      docp->errcode = ERR_PROXY_CONNECT;      return NULL;    }  }  con = my_ssl_connection_new();  model = myssl_bufio_new_socket(socket);  /* model = PR_ImportTCPSocket(bufio_getfd(socket)); */  con->fd = SSL_ImportFD(NULL, model);  SSL_OptionSet(con->fd, SSL_SECURITY, PR_TRUE);  SSL_OptionSet(con->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);  switch (cfg.ssl_version)  {  case 1:    SSL_OptionSet(con->fd, SSL_ENABLE_SSL2, TRUE);    SSL_OptionSet(con->fd, SSL_ENABLE_SSL3, FALSE);    SSL_OptionSet(con->fd, SSL_ENABLE_TLS, FALSE);    SSL_OptionSet(con->fd, SSL_V2_COMPATIBLE_HELLO, TRUE);    break;  case 2:    SSL_OptionSet(con->fd, SSL_ENABLE_SSL2, TRUE);    SSL_OptionSet(con->fd, SSL_ENABLE_SSL3, TRUE);    SSL_OptionSet(con->fd, SSL_ENABLE_TLS, FALSE);    SSL_OptionSet(con->fd, SSL_V2_COMPATIBLE_HELLO, TRUE);    break;  case 3:    SSL_OptionSet(con->fd, SSL_ENABLE_SSL2, FALSE);    SSL_OptionSet(con->fd, SSL_ENABLE_SSL3, TRUE);    SSL_OptionSet(con->fd, SSL_ENABLE_TLS, FALSE);    SSL_OptionSet(con->fd, SSL_V2_COMPATIBLE_HELLO, FALSE);    break;  case 4:    SSL_OptionSet(con->fd, SSL_ENABLE_SSL2, FALSE);    SSL_OptionSet(con->fd, SSL_ENABLE_SSL3, FALSE);    SSL_OptionSet(con->fd, SSL_ENABLE_TLS, TRUE);    SSL_OptionSet(con->fd, SSL_V2_COMPATIBLE_HELLO, FALSE);    break;  }  SSL_OptionSet(con->fd, SSL_NO_CACHE, !cfg.unique_sslid);  if(priv_cfg.ssl_cipher_list)    my_ssl_set_ciphers(con->fd, priv_cfg.ssl_cipher_list);  if(priv_cfg.ssl_cert_passwd)    SSL_SetPKCS11PinArg(con->fd, priv_cfg.ssl_cert_passwd);  handle = CERT_GetDefaultCertDB();  SSL_AuthCertificateHook(con->fd, my_ssl_verify_callback, (void *) handle);  SSL_GetClientAuthDataHook(con->fd, NSS_GetClientAuthData, (void *) NULL);  SSL_BadCertHook(con->fd, my_ssl_verify_failed_callback, (void *) NULL);  SSL_SetURL(con->fd, url_get_site(docp->doc_url));  SSL_SetSockPeerID(con->fd, url_get_site(docp->doc_url));  rv = SSL_ResetHandshake(con->fd, 0);  rv = SSL_ForceHandshake(con->fd);  if(rv != SECSuccess)  {    const char *errstr;    errstr = SECU_Strerror(PR_GetError());    xprintf(1, gettext("SSL connect failure - %s\n"), errstr);    my_ssl_connection_destroy(con);    return NULL;  }  con->socket = socket;  return bufio_new_sslcon(socket, con);}int my_ssl_read(ssl_connection * ssl_con, char *buf, size_t len){  return PR_Read(ssl_con->fd, buf, len);}int my_ssl_write(ssl_connection * ssl_con, char *buf, size_t len){  return PR_Write(ssl_con->fd, buf, len);}int my_ssl_data_pending(ssl_connection * ssl_con){  return SSL_DataPending(ssl_con->fd);}void my_ssl_print_last_error(void){  char *errstr = SECU_Strerror(PR_GetError());  xprintf(1, gettext("SSL error - %s\n"), errstr);}#endif

⌨️ 快捷键说明

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