myssl_openssl.c
来自「网络爬虫程序」· C语言 代码 · 共 788 行 · 第 1/2 页
C
788 行
/***************************************************************************//* 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_OPENSSL)#include <arpa/inet.h>#include <assert.h>#include <netdb.h>#include <netinet/in.h>#include <stdio.h>#include <string.h>#include <sys/socket.h>#include <time.h>#include "bufio.h"#include "errcode.h"#include "http.h"#include "myssl.h"#include "tools.h"/* Let's try to cache session ids! *//* Very unlikely to have more than 4 session ids active, * so use cheap slow lookup */typedef struct session_entry{ int len; int family; struct sockaddr_in addr; SSL_SESSION *session;} session_entry;#define N_SESSIONS 10static session_entry *session_map[N_SESSIONS];static int session_map_init = -1;static int cmp_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b){ return (a->sin_addr.s_addr != b->sin_addr.s_addr) || (a->sin_port != b->sin_port);}static void dump_session_id(SSL_SESSION * s){ int i; if(!s) { DEBUG_SSL("No session ID to dump?\n"); return; } DEBUG_SSL("ssl_session_id(%d) = [", s->session_id_length); for(i = 0; i < s->session_id_length; i++) { DEBUG_SSL(" %02x", s->session_id[i]); } DEBUG_SSL("]\n"); return;}static void map_init(void){ int i; if(session_map_init != -1) return; LOCK_SSL_MAP; if(session_map_init == -1) { for(i = 0; i < N_SESSIONS; i++) session_map[i] = 0; session_map_init = 1; } UNLOCK_SSL_MAP;}static SSL_SESSION *cache_locate_session_by_addr(struct sockaddr_in *addr, int dolock){ int i; map_init(); if(!addr) { DEBUG_SSL("No addr to locate session id by?\n"); return 0; } DEBUG_SSL("Trying to locate session id for ip %s:%d\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); if(dolock) { LOCK_SSL_MAP; } for(i = 0; i < N_SESSIONS; i++) { if(session_map[i] && !cmp_sockaddr(addr, &session_map[i]->addr)) { if(dolock) { UNLOCK_SSL_MAP; } DEBUG_SSL("returning slot %d id for %s:%d\n", i, inet_ntoa(session_map[i]->addr.sin_addr), ntohs(session_map[i]->addr.sin_port)); dump_session_id(session_map[i]->session); return session_map[i]->session; } } if(dolock) { UNLOCK_SSL_MAP; } DEBUG_SSL("not cached\n"); return 0;}static void cache_session_by_addr(struct sockaddr_in *addr, SSL * con){ session_entry *p; int i; SSL_SESSION *s; map_init(); LOCK_SSL_MAP; /* see if this session is already in the map */ s = cache_locate_session_by_addr(addr, 0); if(s) { /* Yes, so simply return */ UNLOCK_SSL_MAP; DEBUG_SSL("session id for %s:%d already cached\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); dump_session_id(s); return; } /* Install session in empty entry in map */ assert(con); s = SSL_get1_session(con); if(s == 0) { DEBUG_SSL("(cache session) No session id to cache?\n"); UNLOCK_SSL_MAP; return; } for(i = 0; i < N_SESSIONS; i++) { if(session_map[i] == 0) { p = malloc(sizeof(session_entry)); p->addr = *addr; p->session = s; session_map[i] = p; UNLOCK_SSL_MAP; DEBUG_SSL("(cache_session) session for %s:%d cached in slot %d\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), i); dump_session_id(p->session); return; } } DEBUG_SSL("(cache_session) You don't have a big enough map\n"); /* FIXME: Replace oldest entry */ UNLOCK_SSL_MAP; return;}static void cache_remove_session(SSL_SESSION * sess){ DEBUG_SSL("Turn your head and cough\n"); /* FIXME: WRITE ME */}static int SSL_FD(SSL * ssl){ if(ssl == NULL) { return -1; } return BIO_get_fd(SSL_get_rbio(ssl), NULL);}static int ssl_new_session_cb(SSL * ssl, SSL_SESSION * sess){ int sock = SSL_FD(ssl); struct sockaddr_in sa; struct sockaddr_in *sp; socklen_t alen = sizeof(sa); SSL_SESSION *cached; assert(sock != -1); DEBUG_SSL("ssl_new_session_cb() called\n"); if(getpeername(sock, (struct sockaddr *) &sa, &alen)) return 1; DEBUG_SSL("ssl_new_session_cb(%s:%d)\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); /* * Search in cache. */ cached = cache_locate_session_by_addr(&sa, 1); if(cached) { DEBUG_SSL("SSL session for %s:%d already cached.\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); return 1; } sp = malloc(sizeof(struct sockaddr_in)); if(sp == NULL) return 1; *sp = sa; cached = SSL_get1_session(ssl); assert(cached == sess); cache_session_by_addr(sp, ssl); DEBUG_SSL("SSL session for %s:%d now cached\n", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); return 1;}static SSL_SESSION *ssl_get_session_cb(SSL * ssl, unsigned char *data, int len, int *copy){ DEBUG_SSL("ssl_get_session_cb()\n"); return NULL;}static void ssl_remove_session_cb(SSL_CTX * ssl, SSL_SESSION * sess){ cache_remove_session(sess);}static void ssl_assign_cached_session(SSL * ssl, struct sockaddr_in *peer){ SSL_SESSION *sess; DEBUG_SSL("ssl_assign_cached_session() called\n"); if(peer == NULL) return; DEBUG_SSL("ssl_assign_cached_session(%s:%d)\n", inet_ntoa(peer->sin_addr), ntohs(peer->sin_port)); sess = cache_locate_session_by_addr(peer, 1); if(sess == NULL) { DEBUG_SSL("SSL session for %s:%d not cached yet\n", inet_ntoa(peer->sin_addr), ntohs(peer->sin_port)); return; } DEBUG_SSL("Setting SSL session for %s:%d\n", inet_ntoa(peer->sin_addr), ntohs(peer->sin_port)); dump_session_id(sess); if(SSL_set_session(ssl, sess) == 0) { DEBUG_SSL("Failed to assign cached SSL session for %s:%d\n", inet_ntoa(peer->sin_addr), ntohs(peer->sin_port)); return; } DEBUG_SSL("SSL session for %s:%d found in cache\n", inet_ntoa(peer->sin_addr), ntohs(peer->sin_port));}static void ssl_assign_cached_session_by_doc(SSL * ssl, doc * docp){ char *hp; int alen; struct sockaddr_in addr; int family; map_init(); DEBUG_SSL("assign_cached_session_by_doc()\n"); if(!docp) { DEBUG_SSL("(assign cached session by doc) No doc?\n"); return; } if(!docp->doc_url) { DEBUG_SSL("(assign cached session by doc) Doc has no url?\n"); return; } hp = docp->doc_url->p.http.host; if(dns_gethostbyname(hp, &alen, (char *) &addr.sin_addr, &family) < 0) { DEBUG_SSL("(assign cached session by doc) Unable to get dns for %s\n", hp); return; } assert(family == AF_INET); assert(alen == sizeof(addr.sin_addr)); addr.sin_port = htons(docp->doc_url->p.http.port); ssl_assign_cached_session(ssl, &addr);}/* Most of this code is inspired by example programs from SSLeay package */static int my_ssl_passwd_callback(char *buf, int num, int verify){ if(verify) xprintf(1, "%s\n", buf); else { if(num > strlen(priv_cfg.ssl_cert_passwd)) { strcpy(buf, priv_cfg.ssl_cert_passwd); return strlen(buf); } } return 0;}static void my_ssl_info_callback(const SSL * con, int where, int ret){ if(where & SSL_CB_LOOP) { DEBUG_SSL("SSL_CB_LOOP: (%s) %s\n", SSL_state_string(con), SSL_state_string_long(con)); } else if(where & SSL_CB_ALERT) { DEBUG_SSL("SSL_CB_ALERT: %s:%s\n", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); } else if((where & SSL_CB_EXIT) && (ret <= 0)) { /* If we print 'unknown' errors, we end up spewing the same */ /* message dozens of times. This avoids that */ if(SSL_alert_type_string(ret)[0] == 'U') return; DEBUG_SSL("SSL_CB_EXIT: [%s:%s] (%s) %s\n", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret), SSL_state_string(con), SSL_state_string_long(con)); }}static int my_ssl_verify_callback(int ok, X509_STORE_CTX * ctx){ char buf[256]; X509 *err_cert; int err, depth; 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); DEBUG_SSL("Depth: %d\n", depth); DEBUG_SSL("Subject: %s\n", buf); if(!ok) { DEBUG_SSL("verify error:num=%d:%s\n", err, X509_verify_cert_error_string(err)); if(0 >= depth) ok = 1; else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?