ssl.cpp File Reference


Detailed Description

Provides SSL socket communication.

Definition in file ssl.cpp.

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <openssl/rsa.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/x509v3.h>
#include <list>
#include "ssl.h"
#include "sock.h"
#include "log.h"
#include "params.h"

Include dependency graph for ssl.cpp:

Go to the source code of this file.

Classes

struct  mydata_t
 Stores data for verification purposes. More...
struct  s_extra_data
 Stores extra data attached to SLL structure. More...
struct  s_ssl_data
 Stores data to send/receive later. More...
struct  s_ssl_receive_later
 Stores data to receive later. More...
struct  s_ssl_send_later
 Stores data to send later. More...

Defines

#define verify_depth_   128
 Depth of verifying chained certificates.

Functions

bool ssl_client_connection (SSL *&ssl, s_socket *server, char *err_str, char *client_cert, char *client_key)
 Attaches socket of client connected to server to OpenSSL.
bool ssl_client_read (SSL *ssl, s_socket *client, char *err_str, char *buf, size_t buf_len, size_t &buf_got)
 Reads from cache.
void ssl_close (SSL *ssl, s_socket *peer)
 Closes the SSL connection in OpenSSL (not socket).
void ssl_do_read_write (SSL *ssl)
 Performs cached reads and writes.
void ssl_error (char *func, char *err_str)
 Generates error message.
bool ssl_init (char *err_str, char *trustedCAs)
 Initializes OpenSSL.
bool ssl_process_error_on_verify (SSL *ssl)
 Logs a certificate verify error.
int SSL_read_ (SSL *ssl, char *data, size_t size, size_t &read)
 Performs read from read cache.
X509 * ssl_read_cert (char *filename)
 Loads a certificate from file.
bool ssl_server_accept (SSL *ssl, s_socket *client)
 Accepts incomming client connection in OpenSSL.
bool ssl_server_connection (SSL *&ssl, s_socket *client, char *err_str, char *server_cert, char *server_key, char *expected_client_cert)
 Attaches socket connection to OpenSSL.
bool ssl_server_read (SSL *ssl, s_socket *client, char *err_str, char *buf, size_t buf_len, size_t &buf_got)
 Reads from cache.
bool ssl_verify_error (SSL *ssl, char *err_str)
 Checks for success of certification verify.
bool ssl_write (SSL *ssl, s_socket *peer, char *err_str, char *buf, size_t buf_len)
 Writes to send cache.
size_t SSL_write_ (SSL *ssl, char *data, size_t size)
 Performs write to the write cache.
static int verify_callback (int preverify_ok, X509_STORE_CTX *ctx)
 SSL verification callback.

Variables

SSL_CTX * ctx
 SSL context, unique for program's lifetime.
vector< s_extra_dataextra_data
 Array of extra data attached to SSL structure.
SSL_METHOD * meth
 SSL method for context.
s_ssl_conf ssl_conf
 Configuration of SSL.
vector< s_ssl_receive_laterssl_receive_later
 Packets to receive later.
vector< s_ssl_send_laterssl_send_later
 Packets to send later.


Define Documentation

#define verify_depth_   128
 

Depth of verifying chained certificates.

Definition at line 64 of file ssl.cpp.

Referenced by ssl_client_connection(), ssl_init(), and ssl_server_connection().


Function Documentation

bool ssl_client_connection SSL *&  ssl,
s_socket server,
char *  err_str,
char *  client_cert,
char *  client_key
 

Attaches socket of client connected to server to OpenSSL.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl Receives SSL descriptor of connection
server Socket descriptor of connection
err_str If return value is true, there's error string
client_cert Path to file containing client's certificate chain to use for connection
client_key Private key for clients's certificate
Returns:
true for error

Definition at line 965 of file ssl.cpp.

References mydata_t::always_continue, s_ssl_receive_later::cert_verified, ctx, s_ssl_receive_later::data, s_ssl_receive_later::expected_client_cert, extra_data, s_socket::handle, s_ssl_receive_later::has_error, s_extra_data::index, log_ssl(), mydata_t::ok, s_ssl_receive_later::s, s_extra_data::ssl, s_ssl_receive_later::ssl, s_socket::ssl_accepted, s_socket::ssl_data_index, ssl_error(), ssl_receive_later, ssl_verify_error(), mydata_t::verbose_mode, verify_callback(), mydata_t::verify_depth, and verify_depth_.

Referenced by botnet_loop().

00966 {
00967     server->ssl_accepted=true;
00968 
00969     int err;
00970 
00971     //X509*    server_cert;
00972 
00973     ssl = SSL_new (ctx);
00974     if(!ssl) {
00975         strcpy(err_str,"attempt to use NULL SSL handle");
00976         ssl_error("ssl_client_connection",err_str);
00977         log_ssl(err_str);
00978         return true;
00979     }
00980 
00981     SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,verify_callback);
00982     SSL_set_verify_depth(ssl,verify_depth_ + 1);
00983 
00984     if (SSL_use_certificate_file(ssl, client_cert, SSL_FILETYPE_PEM) <= 0) {
00985         ERR_error_string(ERR_get_error(),err_str);
00986         ssl_error("SSL_use_certificate_file",err_str);
00987         log_ssl(err_str);
00988         return true;
00989     }
00990     if (SSL_use_RSAPrivateKey_file(ssl, client_key, SSL_FILETYPE_PEM) <= 0) {
00991         ERR_error_string(ERR_get_error(),err_str);
00992         ssl_error("SSL_use_RSAPrivateKey_file",err_str);
00993         log_ssl(err_str);
00994         return true;
00995     }
00996 
00997     if (!SSL_check_private_key(ssl)) {
00998         sprintf(err_str,"Private key does not match the certificate public key\n");
00999         ssl_error("SSL_check_private_key",err_str);
01000         log_ssl(err_str);
01001         return true;
01002     }
01003 
01004     int mydata_index = SSL_get_ex_new_index(0,NULL , NULL, NULL, NULL);
01005     server->ssl_data_index=mydata_index;
01006     s_extra_data e;
01007     e.ssl=ssl;
01008     e.index=mydata_index;
01009     extra_data.push_back(e);
01010 
01011     mydata_t* mydata=new mydata_t;
01012     mydata->verify_depth = verify_depth_;
01013     mydata->always_continue=false;
01014     mydata->verbose_mode=false;
01015     mydata->ok=true;
01016     SSL_set_ex_data(ssl, mydata_index, mydata);
01017 
01018     SSL_set_fd (ssl, (int)server->handle);
01019     err = SSL_connect (ssl);
01020     if(err==-1 && ERR_get_error()!=0) {
01021         ERR_error_string(ERR_get_error(),err_str);
01022         ssl_error("SSL_connect",err_str);
01023         log_ssl(err_str);
01024         if(ssl_verify_error(ssl,err_str))
01025             log_ssl(err_str);
01026         return true;
01027     }
01028 
01029     /* Following two steps are optional and not required for
01030        data exchange to be successful. */
01031   
01032     /* Get the cipher - opt */
01033 
01034     //printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
01035   
01036     /* Get server's certificate (note: beware of dynamic allocation) - opt */
01037 
01038     /*server_cert = SSL_get_peer_certificate (ssl);
01039     if(!server_cert)
01040         return true;
01041   
01042     str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
01043     if(!str)
01044         return true;
01045     OPENSSL_free (str);
01046 
01047     str = X509_NAME_oneline (X509_get_issuer_name  (server_cert),0,0);
01048     if(!str)
01049         return true;
01050     OPENSSL_free (str);
01051 
01052     /* We could do all sorts of certificate verification stuff here before
01053        deallocating the certificate. *
01054 
01055     X509_free (server_cert);*/
01056 
01057     /* --------------------------------------------------- */
01058     /* DATA EXCHANGE - Send a message and receive a reply. */
01059 
01060     {
01061         s_ssl_receive_later r;
01062         r.data.clear();
01063         r.has_error=false;
01064         r.ssl=ssl;
01065         r.s=*server;
01066         r.cert_verified=false;
01067         r.expected_client_cert="";
01068         ssl_receive_later.push_back(r);
01069     }
01070 
01071     return false;
01072 }

Here is the call graph for this function:

bool ssl_client_read SSL *  ssl,
s_socket client,
char *  err_str,
char *  buf,
size_t  buf_len,
size_t &  buf_got
 

Reads from cache.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
client Socket descriptor of connection
err_str If return value is true, there's error string
buf Buffer for read
buf_len Length of that buffer
buf_got Returns number of bytes actually read
Returns:
true for error

Definition at line 1087 of file ssl.cpp.

References ssl_server_read().

Referenced by botnet_receive().

01088 {
01089     return ssl_server_read(ssl,client,err_str,buf,buf_len,buf_got);
01090 }

Here is the call graph for this function:

void ssl_close SSL *  ssl,
s_socket peer
 

Closes the SSL connection in OpenSSL (not socket).

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
peer Socket descriptor of connection

Definition at line 909 of file ssl.cpp.

References extra_data, s_socket::ssl_data_index, ssl_receive_later, and ssl_send_later.

Referenced by botnet_link(), botnet_loop(), botnet_receive(), botnet_send_command(), botnet_send_control(), and dcc_loop().

00910 {
00911     if(!ssl)
00912         return;
00913 
00914     {
00915         vector<s_ssl_send_later>::iterator i1;
00916         for(i1=ssl_send_later.begin(); i1!=ssl_send_later.end(); i1++) {
00917             if((*i1).ssl==ssl) {
00918                 list<s_ssl_data>::iterator i;
00919                 for(i=(*i1).data.begin(); i!=(*i1).data.end(); i++)
00920                     delete[] (*i).data;
00921                 (*i1).data.clear();
00922                 ssl_send_later.erase(i1);
00923                 break;
00924             }
00925         }
00926 
00927         vector<s_ssl_receive_later>::iterator i2;
00928         for(i2=ssl_receive_later.begin(); i2!=ssl_receive_later.end(); i2++) {
00929             if((*i2).ssl==ssl) {
00930                 list<s_ssl_data>::iterator i;
00931                 for(i=(*i2).data.begin(); i!=(*i2).data.end(); i++)
00932                     delete[] (*i).data;
00933                 (*i2).data.clear();
00934                 ssl_receive_later.erase(i2);
00935                 break;
00936             }
00937         }
00938     }
00939 
00940     mydata_t* mydata = (mydata_t*) SSL_get_ex_data(ssl, peer->ssl_data_index);
00941     if(mydata)
00942         delete mydata;
00943     vector<s_extra_data>::iterator i1;
00944     for(i1=extra_data.begin(); i1!=extra_data.end(); i1++) {
00945         if((*i1).ssl==ssl) {
00946             extra_data.erase(i1);
00947             break;
00948         }
00949     }
00950     SSL_free (ssl);
00951 }

void ssl_do_read_write SSL *  ssl  ) 
 

Performs cached reads and writes.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection

Definition at line 283 of file ssl.cpp.

References s_ssl_data::data, s_ssl_data::error, s_ssl_data::len, log_ssl(), ssl_error(), ssl_process_error_on_verify(), ssl_read_cert(), ssl_receive_later, and ssl_send_later.

Referenced by botnet_loop(), ssl_server_read(), and ssl_write().

00284 {
00285     char err_str[1024];
00286 
00287     vector<s_ssl_receive_later>::iterator i2;
00288     for(i2=ssl_receive_later.begin(); i2!=ssl_receive_later.end(); i2++) {
00289         if((*i2).ssl==ssl) {
00290             unsigned int max_size=1024*20;
00291             char* buf_=new char[max_size];
00292 
00293             timeval t;
00294             t.tv_sec=0;
00295             t.tv_usec=10;
00296 
00297             fd_set a;
00298             FD_ZERO(&a);
00299             FD_SET((*i2).s.handle,&a);
00300 
00301             int i=select((int)(*i2).s.handle+1,&a,NULL,NULL,&t);
00302             if(i==0) {
00303                 delete[] buf_;
00304                 break;
00305             }
00306 
00307             int err;
00308             try {
00309                 err=SSL_read (ssl, buf_, max_size);
00310             } catch(...) {
00311                 err=-1;
00312             }
00313             if(err==-1 && (ERR_get_error()==SSL_ERROR_WANT_READ || ERR_get_error()==SSL_ERROR_WANT_WRITE)) {
00314                 delete[] buf_;
00315                 break;
00316             }
00317             if(err==-1 && ERR_get_error()!=0) {
00318                 ERR_error_string(ERR_get_error(),err_str);
00319                 ssl_error("SSL_read",err_str);
00320                 log_ssl(err_str);
00321 
00322                 delete[] buf_;
00323                 if(!(*i2).has_error) {
00324                     s_ssl_data d;
00325                     d.error=ERR_get_error();
00326                     (*i2).data.push_back(d);
00327                     (*i2).has_error=true;
00328                     break;
00329                 }
00330             }
00331             if(!(*i2).has_error && ssl_process_error_on_verify(ssl)) {
00332                 s_ssl_data d;
00333                 d.data=NULL;
00334                 d.len=0;
00335                 d.error=-1;
00336                 (*i2).data.push_back(d);
00337                 (*i2).has_error=true;
00338             }
00339             size_t size_=((signed)err>0?err:0);
00340             if(size_==0) {
00341                 delete[] buf_;
00342                 break;
00343             }
00344             if(size_) {
00345                 s_ssl_data d;
00346                 d.error=0;
00347                 d.len=size_;
00348                 d.data=buf_;
00349                 (*i2).data.push_back(d);
00350 
00351                 if(!(*i2).cert_verified) {
00352                     X509* client_cert = SSL_get_peer_certificate (ssl);
00353                     if (client_cert != NULL) {
00354                         if (SSL_get_verify_result(ssl) == X509_V_OK) {
00355                             // The client sent a certificate which verified OK
00356                             bool ok=false;
00357                             if(!(*i2).expected_client_cert.empty()) {
00358                                 X509* ecc=ssl_read_cert((char*)(*i2).expected_client_cert.c_str());
00359                                 X509_check_purpose(ecc,-1,0); // compute SHA1 hash
00360                                 if(ecc==NULL) {
00361                                     ok=false;
00362                                 } else {
00363                                     char* hash1=(char*)&(ecc->sha1_hash);
00364                                     char* hash2=(char*)&(client_cert->sha1_hash);
00365                                     ok=true;
00366                                     for(int i1=0; i1<sizeof(client_cert->sha1_hash); i1++, hash1++, hash2++)
00367                                         if(*hash1!=*hash2) {
00368                                             ok=false;
00369                                             break;
00370                                         }
00371                                 }
00372                             } else
00373                                 ok=true;
00374                             if(ok) {
00375                                 (*i2).cert_verified=true;
00376                                 X509_free (client_cert);
00377                             } else {
00378                                 char err_str[1024];
00379                                 strcpy(err_str,"certificate verification failed");
00380                                 ssl_error("ssl_server_read",err_str);
00381                                 log_ssl(err_str);
00382                                 X509_free (client_cert);
00383                                 (*i2).has_error=true;
00384                                 s_ssl_data d;
00385                                 d.error=-1;
00386                                 d.len=0;
00387                                 d.data=NULL;
00388                                 (*i2).data.push_back(d);
00389                             }
00390                         } else {
00391                             char err_str[1024];
00392                             strcpy(err_str,"certificate verification failed");
00393                             ssl_error("ssl_server_read",err_str);
00394                             log_ssl(err_str);
00395                             X509_free (client_cert);
00396                             (*i2).has_error=true;
00397                             s_ssl_data d;
00398                             d.error=-1;
00399                             d.len=0;
00400                             d.data=NULL;
00401                             (*i2).data.push_back(d);
00402                         }
00403                     } else {
00404                         char err_str[1024];
00405                         strcpy(err_str,"certificate verification failed");
00406                         ssl_error("ssl_server_read",err_str);
00407                         log_ssl(err_str);
00408                         (*i2).has_error=true;
00409                         s_ssl_data d;
00410                         d.error=-1;
00411                         d.len=0;
00412                         d.data=NULL;
00413                         (*i2).data.push_back(d);
00414                     }
00415                 }
00416             }
00417         }
00418     }
00419 
00420     vector<s_ssl_send_later>::iterator i1;
00421     for(i1=ssl_send_later.begin(); i1!=ssl_send_later.end(); i1++) {
00422     again:
00423         list<s_ssl_data>::iterator i2;
00424         try {
00425             i2=(*i1).data.begin();
00426         } catch(...) {
00427             continue;
00428         }
00429         for(i2=(*i1).data.begin(); i2!=(*i1).data.end(); i2++) {
00430             size_t l=1024;
00431             if((*i2).len<l)
00432                 l=(*i2).len;
00433 
00434             size_t Sent;
00435             //int err;
00436             try {
00437                 Sent=SSL_write (ssl, (*i2).data, (int)(*i2).len);
00438             } catch(...) {
00439                 Sent=(size_t)-1;
00440             }
00441             if(Sent==(size_t)-1 && ERR_get_error()!=SSL_ERROR_WANT_READ && ERR_get_error()!=SSL_ERROR_WANT_WRITE) {
00442                 if(!(*i1).has_error && ERR_get_error()!=0) {
00443                     ERR_error_string(ERR_get_error(),err_str);
00444                     ssl_error("SSL_write",err_str);
00445                     log_ssl(err_str);
00446                     s_ssl_data d;
00447                     d.data=NULL;
00448                     d.len=0;
00449                     d.error=ERR_get_error();
00450                     (*i1).data.push_back(d);
00451                     (*i1).has_error=true;
00452                 }
00453                 if(!(*i1).has_error && ssl_process_error_on_verify(ssl)) {
00454                     s_ssl_data d;
00455                     d.data=NULL;
00456                     d.len=0;
00457                     d.error=-1;
00458                     (*i1).data.push_back(d);
00459                     (*i1).has_error=true;
00460                 }
00461                 break;
00462             }
00463             if((signed)Sent<0)
00464                 Sent=0;
00465 
00466             if(Sent<(*i2).len) {
00467                 char* buf_=new char[(*i2).len-Sent];
00468                 memcpy(buf_,&(*i2).data[Sent],(*i2).len-Sent);
00469                 delete[] (*i2).data;
00470                 (*i2).len-=Sent;
00471                 (*i2).data=buf_;
00472             } else {
00473                 delete[] (*i2).data;
00474                 (*i1).data.pop_front();
00475             }
00476             goto again;
00477         }
00478     }
00479 }

Here is the call graph for this function:

void ssl_error char *  func,
char *  err_str
 

Generates error message.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
func Name of failed function
err_str Original Error string, will be expanded
Warning:
err_str must be at least 1024 bytes long!

Definition at line 169 of file ssl.cpp.

Referenced by ssl_client_connection(), ssl_do_read_write(), ssl_init(), ssl_process_error_on_verify(), ssl_server_connection(), ssl_server_read(), and ssl_write().

00170 {
00171     char* tmp=new char[strlen(func)+strlen(err_str)+1024+1];
00172     strcpy(tmp,"while calling ");
00173     strcat(tmp,func);
00174     strcat(tmp,"() occured error ");
00175     strcat(tmp,err_str);
00176     if(strlen(tmp)>1023)
00177         tmp[1023]=0;
00178     strcpy(err_str,tmp);
00179     delete[] tmp;
00180 }

bool ssl_init char *  err_str,
char *  trustedCAs
 

Initializes OpenSSL.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
err_str If return value is true, there's error string
trustedCAs Path to file containing certificates of CA's tu trust
Returns:
true for error

Definition at line 671 of file ssl.cpp.

References ctx, log_ssl(), meth, ssl_error(), verify_callback(), and verify_depth_.

Referenced by main().

00672 {
00673     /* SSL preliminaries. We keep the certificate and key with the context. */
00674 
00675     SSL_load_error_strings();
00676 
00677     SSL_library_init();                      /* initialize library */
00678     //actions_to_seed_PRNG();
00679 
00680     SSLeay_add_ssl_algorithms();
00681     meth = SSLv3_method();
00682     ctx = SSL_CTX_new (meth);
00683 
00684     if (!ctx) {
00685         //ERR_print_errors_fp(stderr);
00686         ERR_error_string(ERR_get_error(),err_str);
00687         ssl_error("SSL_CTX_new",err_str);
00688         log_ssl(err_str);
00689         return true;
00690     }
00691 
00692     STACK_OF(X509_NAME) *cert_names=SSL_load_client_CA_file(trustedCAs);
00693     if(!cert_names) {
00694         ERR_error_string(ERR_get_error(),err_str);
00695         ssl_error("SSL_load_client_CA_file",err_str);
00696         if(strlen(err_str)+strlen(trustedCAs)+64<1024) {
00697             strcat(err_str,"(using file \"");
00698             strcat(err_str,trustedCAs);
00699             strcat(err_str,"\")");
00700         }
00701         log_ssl(err_str);
00702         return true;
00703     }
00704     SSL_CTX_set_client_CA_list(ctx,cert_names);
00705 
00706     if(!SSL_CTX_load_verify_locations(ctx,trustedCAs,NULL)) {
00707         ERR_error_string(ERR_get_error(),err_str);
00708         ssl_error("SSL_CTX_load_verify_locations",err_str);
00709         log_ssl(err_str);
00710         return true;
00711     }
00712 
00713     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,verify_callback);
00714     SSL_CTX_set_verify_depth(ctx,verify_depth_ + 1);
00715 
00716     return false;
00717 }

Here is the call graph for this function:

bool ssl_process_error_on_verify SSL *  ssl  ) 
 

Logs a certificate verify error.

Author:
VooDooMan
Version:
1
Date:
2005
Parameters:
ssl SSL descriptor of connection
Return values:
true Returns true for error
Returns:
Returns true for error

Definition at line 250 of file ssl.cpp.

References mydata_t::err, extra_data, index(), log_ssl(), mydata_t::ok, and ssl_error().

Referenced by ssl_do_read_write().

00251 {
00252     int index=-1;
00253     vector<s_extra_data>::iterator i1;
00254     for(i1=extra_data.begin(); i1!=extra_data.end(); i1++) {
00255         if((*i1).ssl==ssl) {
00256             index=(*i1).index;
00257             break;
00258         }
00259     }
00260     if(index==-1)
00261         return false;
00262     mydata_t* mydata = (mydata_t*) SSL_get_ex_data(ssl, index);
00263     if(mydata) {
00264         if(!mydata->ok) {
00265             char err_str[1024];
00266             strncpy(err_str,mydata->err,sizeof(err_str));
00267             err_str[sizeof(err_str)-1]=0;
00268             ssl_error("(certificate verification callback)",err_str);
00269             log_ssl(err_str);
00270             return true;
00271         }
00272     }
00273     return false;
00274 }

Here is the call graph for this function:

int SSL_read_ SSL *  ssl,
char *  data,
size_t  size,
size_t &  read
 

Performs read from read cache.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
data Buffer to receive data
size Size of that buffer
read Returns number of bytes actually read
Returns:
Returns error from ERR_get_error() from OpenSSL

Definition at line 492 of file ssl.cpp.

References ssl_receive_later.

Referenced by ssl_server_read().

00493 {
00494     read=0;
00495     {
00496         vector<s_ssl_receive_later>::iterator i1;
00497         for(i1=ssl_receive_later.begin(); i1!=ssl_receive_later.end(); i1++) {
00498             if((*i1).ssl==ssl) {
00499                 list<s_ssl_data>::iterator i2;
00500                 for(i2=(*i1).data.begin(); i2!=(*i1).data.end(); i2++) {
00501                     int error_code=(*i2).error;
00502                     if(error_code)
00503                         return error_code;
00504 
00505                     size_t l=size;
00506                     if((*i2).len<=l) {
00507                         l=(*i2).len;
00508                         if((*i2).len)
00509                             memcpy(data,(*i2).data,l);
00510                         delete[] (*i2).data;
00511                         (*i1).data.pop_front();
00512                         read=l;
00513                         return 0;
00514                     }
00515                     if((*i2).len>l) {
00516                         memcpy(data,(*i2).data,l);
00517                         char* buf=new char[(*i2).len-l];
00518                         memcpy(buf,&((*i2).data[l]),(*i2).len-l);
00519                         delete[] (*i2).data;
00520                         (*i2).len-=l;
00521                         (*i2).data=buf;
00522                         error_code=0;
00523                         read=l;
00524                         return 0;
00525                     }
00526                 }
00527                 return 0;
00528             }
00529         }
00530     }
00531     return 0;
00532 }

X509* ssl_read_cert char *  filename  ) 
 

Loads a certificate from file.

Author:
VooDooMan
Version:
1
Date:
2005
Parameters:
filename Name of file

Definition at line 221 of file ssl.cpp.

Referenced by ssl_do_read_write().

00222 {
00223     X509* cert;
00224     BIO* s=BIO_new_file(filename,"r");
00225 
00226     if(!s)
00227         return NULL;
00228           
00229     BIO* f=BIO_new(BIO_f_base64());
00230     if(!f) {
00231         BIO_free(s);
00232         return NULL;
00233     }
00234     s=BIO_push(f,s);
00235     cert=d2i_X509_bio(s,NULL);
00236     BIO_free_all(s);
00237 
00238     return cert;
00239 }

bool ssl_server_accept SSL *  ssl,
s_socket client
 

Accepts incomming client connection in OpenSSL.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
client Socket descriptor of connection
Returns:
true if connection has been accepted, otherwise false

Definition at line 1146 of file ssl.cpp.

References s_socket::handle, and s_socket::ssl_accepted.

Referenced by dcc_loop().

01147 {
01148     if(!ssl)
01149         return false;
01150 
01151     int err;
01152 
01153     if(!client->ssl_accepted) {
01154         timeval t;
01155         t.tv_sec=0;
01156         t.tv_usec=10;
01157         fd_set a;
01158         FD_ZERO(&a);
01159         FD_SET(client->handle,&a);
01160         int ii=select((int)client->handle+1,&a,NULL,NULL,&t);
01161         if(ii==0)
01162             return false;
01163         err = SSL_accept (ssl);
01164         /*if(err==-1) {
01165             char err_str[1024];
01166             ERR_error_string(ERR_get_error(),err_str);
01167             //log_ssl(err_str);
01168             return false;
01169         }*/
01170         return client->ssl_accepted=true;
01171     }
01172     return true;
01173 }

bool ssl_server_connection SSL *&  ssl,
s_socket client,
char *  err_str,
char *  server_cert,
char *  server_key,
char *  expected_client_cert
 

Attaches socket connection to OpenSSL.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl Returns SSL descriptor, if succeeded
client Socket descriptor to attach
err_str If return value is true, there's error string
server_cert Path to file containing server's certificate chain to use for connection
server_key Private key for server's certificate
expected_client_cert Path to file containing expected client's certificate
Returns:
true for error

Definition at line 732 of file ssl.cpp.

References mydata_t::always_continue, s_ssl_receive_later::cert_verified, ctx, s_ssl_receive_later::data, mydata_t::err, s_ssl_receive_later::expected_client_cert, extra_data, s_socket::handle, s_ssl_receive_later::has_error, s_extra_data::index, log_ssl(), mydata_t::ok, s_ssl_receive_later::s, s_extra_data::ssl, s_ssl_receive_later::ssl, s_socket::ssl_data_index, ssl_error(), ssl_receive_later, mydata_t::verbose_mode, mydata_t::verify_depth, and verify_depth_.

Referenced by dcc_loop().

00733 {
00734     ssl = SSL_new (ctx);
00735     if(!ssl) {
00736         strcpy(err_str,"attempt to use NULL SSL handle");
00737         ssl_error("SSL_new",err_str);
00738         log_ssl(err_str);
00739         return true;
00740     }
00741 
00742     /*SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,verify_callback);
00743     SSL_set_verify_depth(ssl,verify_depth_ + 1);*/
00744   
00745     /*
00746      * Set up the SSL specific data into "mydata" and store it into th SSL
00747      * structure.
00748      */
00749 
00750     if (SSL_use_certificate_file(ssl, server_cert, SSL_FILETYPE_PEM) <= 0) {
00751         ERR_error_string(ERR_get_error(),err_str);
00752         ssl_error("SSL_use_certificate_file",err_str);
00753         log_ssl(err_str);
00754         return true;
00755     }
00756     if (SSL_use_RSAPrivateKey_file(ssl, server_key, SSL_FILETYPE_PEM) <= 0) {
00757         ERR_error_string(ERR_get_error(),err_str);
00758         ssl_error("SSL_use_RSAPrivateKey_file",err_str);
00759         log_ssl(err_str);
00760         return true;
00761     }
00762 
00763     if (!SSL_check_private_key(ssl)) {
00764         sprintf(err_str,"Private key does not match the certificate public key\n");
00765         ssl_error("SSL_check_private_key",err_str);
00766         log_ssl(err_str);
00767         return true;
00768     }
00769 
00770     int mydata_index = SSL_get_ex_new_index(0,NULL , NULL, NULL, NULL);
00771     client->ssl_data_index=mydata_index;
00772     s_extra_data e;
00773     e.ssl=ssl;
00774     e.index=mydata_index;
00775     extra_data.push_back(e);
00776 
00777     mydata_t* mydata=new mydata_t;
00778     mydata->verify_depth = verify_depth_;
00779     mydata->always_continue=false;
00780     mydata->verbose_mode=false;
00781     mydata->ok=true;
00782     mydata->err[0]=0;
00783     SSL_set_ex_data(ssl, mydata_index, mydata);
00784 
00785     SSL_set_fd (ssl, (int)client->handle);
00786 
00787     {
00788         s_ssl_receive_later r;
00789         r.data.clear();
00790         r.has_error=false;
00791         r.ssl=ssl;
00792         r.s=*client;
00793         r.cert_verified=false;
00794         r.expected_client_cert=expected_client_cert;
00795         ssl_receive_later.push_back(r);
00796     }
00797 
00798     return false;
00799 }

Here is the call graph for this function:

bool ssl_server_read SSL *  ssl,
s_socket client,
char *  err_str,
char *  buf,
size_t  buf_len,
size_t &  buf_got
 

Reads from cache.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
client Socket descriptor of connection
err_str If return value is true, there's error string
buf Buffer for read
buf_len Length of that buffer
buf_got Returns number of bytes actually read
Returns:
true for error

Definition at line 814 of file ssl.cpp.

References s_socket::handle, log_ssl(), mydata_t::ok, s_socket::ssl_accepted, s_socket::ssl_data_index, ssl_do_read_write(), ssl_error(), SSL_read_(), and ssl_verify_error().

Referenced by ssl_client_read().

00815 {
00816     buf_got=0;
00817 
00818     if(!ssl) {
00819         strcpy(err_str,"attempt to use NULL SSL handle");
00820         ssl_error("ssl_server_read",err_str);
00821         log_ssl(err_str);
00822         return true;
00823     }
00824 
00825     int err;
00826 
00827     if(!client->ssl_accepted) {
00828         timeval t;
00829         t.tv_sec=0;
00830         t.tv_usec=10;
00831         fd_set a;
00832         FD_ZERO(&a);
00833         FD_SET(client->handle,&a);
00834         int ii=select((int)client->handle+1,&a,NULL,NULL,&t);
00835         if(ii==0)
00836             return false;
00837         err = SSL_accept (ssl);
00838         /*if(err==-1) {
00839             return false;
00840         }*/
00841         client->ssl_accepted=true;
00842     }
00843 
00844     /* Get the cipher - opt */
00845 
00846     //printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
00847   
00848     /* Get client's certificate (note: beware of dynamic allocation) - opt */
00849 
00850     /*if (client_cert != NULL) {
00851         //printf ("Client certificate:\n");
00852     
00853         str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
00854         if(!str)
00855             return true;
00856         //printf ("\t subject: %s\n", str);
00857         OPENSSL_free (str);
00858     
00859         str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0);
00860         if(!str)
00861             return true;
00862         //printf ("\t issuer: %s\n", str);
00863         OPENSSL_free (str);
00864     
00865         /* We could do all sorts of certificate verification stuff here before
00866            deallocating the certificate. *
00867 
00868         X509_free (client_cert);
00869     } else
00870         //printf ("Client does not have certificate.\n");
00871         ;*/
00872 
00873     /* DATA EXCHANGE - Receive message and send reply. */
00874 
00875     mydata_t* mydata = (mydata_t*) SSL_get_ex_data(ssl, client->ssl_data_index);
00876 
00877     if(!mydata->ok) {
00878         strcpy(err_str,"certificate verification failed");
00879         ssl_error("ssl_server_read",err_str);
00880         log_ssl(err_str);
00881         return true;
00882     }
00883 
00884     ssl_do_read_write(ssl);
00885 
00886     size_t read;
00887     err = SSL_read_ (ssl, buf, buf_len,read);
00888 
00889     if(err!=0) {
00890         ERR_error_string(err,err_str);
00891         ssl_error("SSL_read",err_str);
00892         log_ssl(err_str);
00893         if(ssl_verify_error(ssl,err_str))
00894             log_ssl(err_str);
00895         return true;
00896     }
00897     buf_got=read;
00898     return false;
00899 }

Here is the call graph for this function:

bool ssl_verify_error SSL *  ssl,
char *  err_str
 

Checks for success of certification verify.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
err_str Returns error string if there was an error
Warning:
err_str must be at least 1024 bytes long!
Returns:
true for error

Definition at line 192 of file ssl.cpp.

References mydata_t::err, extra_data, index(), and mydata_t::ok.

Referenced by ssl_client_connection(), ssl_server_read(), and ssl_write().

00193 {
00194     mydata_t* mydata;
00195 
00196     int index=0;
00197     vector<s_extra_data>::iterator i1;
00198     for(i1=extra_data.begin(); i1!=extra_data.end(); i1++) {
00199         if((*i1).ssl==ssl) {
00200             index=(*i1).index;
00201             break;
00202         }
00203     }
00204     mydata = (mydata_t*) SSL_get_ex_data(ssl, index);
00205     if(mydata) {
00206         if(!mydata->ok && strlen(mydata->err))
00207             strcpy(err_str,mydata->err);
00208         if(!mydata->ok)
00209             return true;
00210     }
00211     return false;
00212 }

Here is the call graph for this function:

bool ssl_write SSL *  ssl,
s_socket peer,
char *  err_str,
char *  buf,
size_t  buf_len
 

Writes to send cache.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
peer Socket descriptor of connection
err_str If return value is true, there's error string
buf Buffer for read
buf_len Length of that buffer
Returns:
true for error

Definition at line 1104 of file ssl.cpp.

References log_ssl(), mydata_t::ok, s_socket::ssl_data_index, ssl_do_read_write(), ssl_error(), ssl_verify_error(), and SSL_write_().

Referenced by botnet_send_command(), and botnet_send_control().

01105 {
01106     if(!ssl) {
01107         strcpy(err_str,"attempt to use NULL SSL handle");
01108         ssl_error("ssl_write",err_str);
01109         log_ssl(err_str);
01110         return true;
01111     }
01112 
01113     mydata_t* mydata = (mydata_t*) SSL_get_ex_data(ssl, peer->ssl_data_index);
01114 
01115     if(!mydata->ok) {
01116         strcpy(err_str,"certificate verification failed");
01117         ssl_error("ssl_write",err_str);
01118         log_ssl(err_str);
01119         return true;
01120     }
01121 
01122     ssl_do_read_write(ssl);
01123 
01124     /*size_t err = */SSL_write_ (ssl, buf, buf_len);
01125     if(ssl_verify_error(ssl,err_str)) {
01126         log_ssl(err_str);
01127         return true;
01128     }
01129     /*if(err==-1 && ERR_get_error()!=SSL_ERROR_WANT_READ && ERR_get_error()!=SSL_ERROR_WANT_WRITE) {
01130         ERR_error_string(ERR_get_error(),err_str);
01131         log_ssl(err_str);
01132         return true;
01133     }*/
01134     return false;
01135 }

Here is the call graph for this function:

size_t SSL_write_ SSL *  ssl,
char *  data,
size_t  size
 

Performs write to the write cache.

Author:
VooDooMan
Version:
1
Date:
2004
Parameters:
ssl SSL descriptor of connection
data Buffer to send data
size Size of that buffer
Returns:
Always returns value of size parameter

Definition at line 544 of file ssl.cpp.

References s_ssl_data::data, s_ssl_send_later::data, s_ssl_data::error, s_ssl_send_later::has_error, s_ssl_data::len, s_ssl_send_later::ssl, and ssl_send_later.

Referenced by ssl_write().

00545 {
00546     {
00547         {
00548 
00549             {
00550             again:
00551                 bool got=false;
00552                 vector<s_ssl_send_later>::iterator i1;
00553                 for(i1=ssl_send_later.begin(); i1!=ssl_send_later.end(); i1++) {
00554                     if((*i1).ssl==ssl) {
00555                         got=true;
00556                         break;
00557                     }
00558                 }
00559                 if(!got) {
00560                     s_ssl_send_later s;
00561                     s.ssl=ssl;
00562                     s.data.clear();
00563                     s.has_error=false;
00564                     ssl_send_later.push_back(s);
00565                     goto again;
00566                 }
00567                 s_ssl_data d;
00568                 d.error=0;
00569                 d.len=size;
00570                 d.data=new char[size];
00571                 memcpy(d.data,data,size);
00572                 (*i1).data.push_back(d);
00573 
00574                 return size;
00575             }
00576         }
00577     }
00578 }

static int verify_callback int  preverify_ok,
X509_STORE_CTX *  ctx
[static]
 

SSL verification callback.

Author:
Sampo Kellomaki <sampo@iki.fi>; Wade Scholine <wades@mail.cybg.com>; VooDooMan
Version:
1
Date:
1996-1998, 2004
Parameters:
preverify_ok I don't actually know what the OpenSSL wants to say by this parameter ;-)
ctx Context of stored certificates
Returns:
Returns 1 (one) to continue the verification process, 0 (zero) to terminate

Definition at line 589 of file ssl.cpp.

References mydata_t::always_continue, mydata_t::err, extra_data, index(), mydata_t::ok, mydata_t::verbose_mode, and mydata_t::verify_depth.

Referenced by ssl_client_connection(), and ssl_init().

00590 {
00591     char    buf__[256];
00592     X509   *err_cert;
00593     int     err, depth;
00594     SSL    *ssl;
00595     mydata_t *mydata;
00596 
00597     err_cert = X509_STORE_CTX_get_current_cert(ctx);
00598     err = X509_STORE_CTX_get_error(ctx);
00599     depth = X509_STORE_CTX_get_error_depth(ctx);
00600 
00601     /*
00602      * Retrieve the pointer to the SSL of the connection currently treated
00603      * and the application specific data stored into the SSL object.
00604      */
00605     ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
00606 
00607     int index=0;
00608     vector<s_extra_data>::iterator i1;
00609     for(i1=extra_data.begin(); i1!=extra_data.end(); i1++) {
00610         if((*i1).ssl==ssl) {
00611             index=(*i1).index;
00612             break;
00613         }
00614     }
00615     mydata = (mydata_t*) SSL_get_ex_data(ssl, index);
00616 
00617     X509_NAME_oneline(X509_get_subject_name(err_cert), buf__, 256);
00618 
00619     /*
00620      * Catch a too long certificate chain. The depth limit set using
00621      * SSL_CTX_set_verify_depth() is by purpose set to "limit+1" so
00622      * that whenever the "depth>verify_depth" condition is met, we
00623      * have violated the limit and want to log this error condition.
00624      * We must do it here, because the CHAIN_TOO_LONG error would not
00625      * be found explicitly; only errors introduced by cutting off the
00626      * additional certificates would be logged.
00627      */
00628     if (depth > mydata->verify_depth) {
00629         preverify_ok = 0;
00630         err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
00631         X509_STORE_CTX_set_error(ctx, err);
00632     }
00633     if (!preverify_ok) {
00634         mydata->ok=false;
00635         sprintf(mydata->err,"verify error:num=%d:%s:depth=%d:%s\n", err,
00636                  X509_verify_cert_error_string(err), depth, buf__);
00637     }
00638     else if (mydata->verbose_mode)
00639     {
00640         //printf("depth=%d:%s\n", depth, buf__);
00641     }
00642 
00643     /*
00644      * At this point, err contains the last verification error. We can use
00645      * it for something special
00646      */
00647     if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
00648     {
00649         X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf__, 256);
00650         //printf("issuer= %s\n", buf__);
00651     }
00652 
00653     if (mydata->always_continue)
00654         return 1;
00655     else
00656         return preverify_ok;
00657 }

Here is the call graph for this function:


Variable Documentation

SSL_CTX* ctx
 

SSL context, unique for program's lifetime.

Definition at line 659 of file ssl.cpp.

Referenced by botnet_partyline_event(), logic_process_script_output(), ssl_client_connection(), ssl_init(), and ssl_server_connection().

vector<s_extra_data> extra_data
 

Array of extra data attached to SSL structure.

Definition at line 93 of file ssl.cpp.

Referenced by ssl_client_connection(), ssl_close(), ssl_process_error_on_verify(), ssl_server_connection(), ssl_verify_error(), and verify_callback().

SSL_METHOD* meth
 

SSL method for context.

Definition at line 660 of file ssl.cpp.

Referenced by ssl_init().

s_ssl_conf ssl_conf
 

Configuration of SSL.

Definition at line 66 of file ssl.cpp.

vector<s_ssl_receive_later> ssl_receive_later
 

Packets to receive later.

Definition at line 158 of file ssl.cpp.

Referenced by ssl_client_connection(), ssl_close(), ssl_do_read_write(), SSL_read_(), and ssl_server_connection().

vector<s_ssl_send_later> ssl_send_later
 

Packets to send later.

Definition at line 157 of file ssl.cpp.

Referenced by ssl_close(), ssl_do_read_write(), and SSL_write_().


Generated on Sun Jul 10 05:40:16 2005 for VooDoo cIRCle by doxygen 1.4.3

Hosted by SourceForge.net Logo