📄 https.c
字号:
/* * Dpi for HTTPS. * * * * W A R N I N G * * One of the important things to have in mind is about whether * unix domain sockets (UDS) are secure for https. I mean, root can always * snoop on sockets (regardless of permissions) so he'd be able to "see" all * the traffic. OTOH, if someone has root access on a machine he can do * anything, and that includes modifying the binaries, peeking-up in * memory space, installing a key-grabber, ... * * * Copyright 2003, 2004 Jorge Arellano Cid <jcid@dillo.org> * Copyright 2004 Garrett Kajmowicz <gkajmowi@tbaytel.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * As a special exception permission is granted to link the code of * the https dillo plugin with the OpenSSL project's "OpenSSL" * library, and distribute the linked executables, without including * the source code for OpenSSL in the source distribution. You must * obey the GNU General Public License, version 2, in all respects * for all of the code used other than "OpenSSL". * *//* * TODO: a lot of things, this is just a bare bones example. * * For instance: * - Handle cookies (now that they arrive with the dpip tag, it needs * testing). * - Certificate authentication (asking the user in case it can't be verified) * - Certificate management. * - Session caching ... * */#include <config.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <sys/un.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <sys/wait.h>#include <errno.h>#include <sys/time.h>#include <sys/stat.h>#include <glib.h>#include "../dpip/dpip.h"#include "dpiutil.h"#define ENABLE_SSL#undef ENABLE_SSL#ifdef ENABLE_SSL#include <openssl/ssl.h>#include <openssl/rand.h>static int get_network_connection(gchar * url);static int handle_certificate_problem(SSL * ssl_connection);static int save_certificate_home(X509 * cert);#endifint main(void);/*---------------------------------------------------------------------------*//* * Global variables */static gchar *root_url = NULL; /*Holds the URL we are connecting to*/static SockHandler *sh;#ifdef ENABLE_SSL/* * Read the answer dpip tag for a dialog and return the number for * the user-selected alternative. * Return: (-1: parse error, 0: window closed, 1-5 alt. number) */static gint dialog_get_answer_number(void){ gint response_number = -1; gchar *dpip_tag, *response; /* Read the dpi command from STDIN */ dpip_tag = sock_handler_read(sh); response = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "msg"); response_number = (response) ? strtol (response, NULL, 10) : -1; g_free(dpip_tag); g_free(response); return response_number;}/* * This function does all of the work with SSL */static void yes_ssl_support(void){ /* The following variable will be set to 1 in the event of * an error and skip any further processing */ gint exit_error = 0; SSL_CTX * ssl_context = NULL; SSL * ssl_connection = NULL; gchar *dpip_tag = NULL, *cmd = NULL, *url = NULL, *http_query = NULL; gchar buf[4096]; int retval = 0; int network_socket = -1; g_printerr("{In https.filter.dpi}\n"); /*Initialize library*/ SSL_load_error_strings(); SSL_library_init(); if (RAND_status() != 1){ /*Insufficient entropy. Deal with it?*/ g_printerr("Insufficient random entropy\n"); } /*Create context and SSL object*/ if (exit_error == 0){ ssl_context = SSL_CTX_new(SSLv23_client_method()); if (ssl_context == NULL){ g_printerr("Error creating SSL context\n"); exit_error = 1; } } /*Set directory to load certificates from*/ /*FIXME - provide for sysconfdir variables and such*/ if (exit_error == 0){ if (SSL_CTX_load_verify_locations( ssl_context, NULL, "/etc/ssl/certs/" ) == 0){ g_printerr("Error opening system x509 certificate location\n"); exit_error = 1; } } if (exit_error == 0){ g_snprintf(buf, 4095, "%s/.dillo/certs/", g_get_home_dir() ); if (SSL_CTX_load_verify_locations(ssl_context, NULL, buf )==0){ g_printerr("Error opening user x509 certificate location\n"); exit_error = 1; } } if (exit_error == 0){ ssl_connection = SSL_new(ssl_context); if (ssl_connection == NULL){ g_printerr("Error creating SSL connection\n"); exit_error = 1; } } if (exit_error == 0){ /* Need to do the following if we want to deal with all * possible ciphers */ SSL_set_cipher_list(ssl_connection, "ALL"); /* Need to do this if we want to have the option of dealing * with self-signed certs */ SSL_set_verify(ssl_connection, SSL_VERIFY_NONE, 0); /*Get the network address and command to be used*/ dpip_tag = sock_handler_read(sh); cmd = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "cmd"); url = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "url"); http_query = a_Dpip_get_attr(dpip_tag, strlen(dpip_tag), "query"); if (cmd == NULL || url == NULL || http_query == NULL){ g_printerr("***Value of cmd, url or http_query is NULL" " - cannot continue\n"); exit_error = 1; } } if (exit_error == 0){ network_socket = get_network_connection(url); if (network_socket<0){ g_printerr("Network socket create error\n"); exit_error = 1; } } if (exit_error == 0){ /* Configure SSL to use network file descriptor */ if (SSL_set_fd(ssl_connection, network_socket) == 0){ g_printerr("Error connecting network socket to SSL\n"); exit_error = 1; } } if (exit_error == 0){ /*Actually do SSL connection handshake*/ if (SSL_connect(ssl_connection) != 1){ g_printerr("SSL_connect failed\n"); exit_error = 1; } } /*Use handle error function to decide what to do*/ if (exit_error == 0){ if (handle_certificate_problem(ssl_connection) < 0){ g_printerr("Certificate verification error\n"); exit_error = 1; } } if (exit_error == 0) { char *d_cmd; /*Send query we want*/ SSL_write(ssl_connection, http_query, (int)strlen(http_query)); /*Analyse response from server*/ /*Send dpi command*/ d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url); sock_handler_write_str(sh, d_cmd, 1); g_free(d_cmd); /*Send remaining data*/ while ((retval = SSL_read(ssl_connection, buf, 4096)) > 0 ){ sock_handler_write(sh, buf, (size_t)retval, 0); } } /*Begin cleanup of all resources used*/ g_free(dpip_tag); g_free(cmd); g_free(url); g_free(http_query); if (network_socket != -1){ close(network_socket); network_socket = -1; } if (ssl_connection != NULL){ SSL_free(ssl_connection); ssl_connection = NULL; } if (ssl_context != NULL){ SSL_CTX_free(ssl_context); ssl_context = NULL; }}/* * The following function attempts to open up a connection to the * remote server and return the file descriptor number of the * socket. Returns -1 in the event of an error */static int get_network_connection(gchar * url){ struct sockaddr_in address; struct hostent *hp; int s; int url_offset = 0; int portnum = 443; unsigned int url_look_up_length = 0; gchar * url_look_up = NULL; /*Determine how much of url we chop off as unneeded*/ if (g_strncasecmp(url, "https://", 8) == 0){ url_offset = 8; } /*Find end of URL*/ if (strpbrk(url+url_offset, ":/") != NULL){ url_look_up_length = strpbrk(url+url_offset, ":/") - (url+url_offset); url_look_up = g_strndup(url+url_offset, url_look_up_length); /*Check for port number*/ if (strchr(url+url_offset, ':') == (url + url_offset + url_look_up_length)){ portnum = atoi(url + url_offset + url_look_up_length + 1); } } else { url_look_up = url + url_offset; } root_url = g_strdup(url_look_up); hp=gethostbyname(url_look_up); /*url_look_uip no longer needed, so free if neccessary*/ if (url_look_up_length != 0){ g_free(url_look_up); } if (hp == NULL){ g_printerr("gethostbyname() failed\n"); return -1; } memset(&address,0,sizeof(address)); memcpy((char *)&address.sin_addr, hp->h_addr, (size_t)hp->h_length); address.sin_family=hp->h_addrtype; address.sin_port= htons((u_short)portnum); s = socket(hp->h_addrtype, SOCK_STREAM, 0); if (connect(s, (struct sockaddr *)&address, sizeof(address)) != 0){ close(s); s = -1; g_printerr("errno: %i\n", errno); } return s;}/* This function is run only when the certificate cannot * be completely trusted. This will notify the user and * allow the user to decide what to do. It may save the * certificate to the user's .dillo directory if it is * trusted. * Return value: -1 on abort, 0 or higher on continue */static int handle_certificate_problem(SSL * ssl_connection){ gint response_number; int retval = -1; long st; char *cn, *cn_end; char buf[4096], *d_cmd, *msg; X509 * remote_cert; remote_cert = SSL_get_peer_certificate(ssl_connection); if (remote_cert == NULL){ /*Inform user that remote system cannot be trusted*/ d_cmd = a_Dpip_build_cmd(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -