DocumentationGenerated on Thu Aug 31 00:02:28 2006 |
||
Connection.cppGo to the documentation of this file.00001 00002 // $Id: Connection.cpp,v 1.19 2005/09/01 20:49:17 klas Exp $ 00003 // 00004 // Usage: Data class. inherited from Connection, everything pertaining to 00005 // data connection goes here. 00006 // 00007 // A part of babyftpd, licensed under the GNU GPL, see the file 00008 // LICENSE for complete information. 00010 00011 #define CONNECTION_CPP 00012 #define NETINCLS 00013 #define BABY_CORE 00014 #include "Connection.h" 00015 00016 Connection::Connection() 00017 { 00018 pthread_rwlock_init(&this->lock, NULL); 00019 this->_settings.reset(); 00020 this->_packet_size = READ_SIZE; 00021 this->_transfered = 0; 00022 } 00023 00024 Connection::~Connection() 00025 { 00026 if(this->_socket_id) 00027 close(this->_socket_id); 00028 00029 pthread_rwlock_destroy(&this->lock); 00030 00031 #ifdef USE_TLS 00032 // TLS cleanup here. 00033 if(this->settings(TLS_INITED)) 00034 { 00035 gnutls_db_remove_session(this->session); 00036 gnutls_deinit(this->session); 00037 } 00038 #endif 00039 if(this->thread_id()) 00040 { 00041 sem_wait(&cleanup_list_lock); 00042 cleanup_list.push_back(this->thread_id()); 00043 sem_post(&cleanup_list_lock); 00044 } 00045 } 00046 00047 ssize_t Connection::send(const char *message, size_t len) 00048 { 00049 assert(len <= this->_packet_size && len > 0); 00050 ssize_t ret = -1; 00051 00052 BABY_WRLOCK(this->lock); 00053 #ifdef USE_TLS 00054 if(this->settings(TLS_ENABLED)) 00055 { 00056 ret = gnutls_record_send(this->session, message, len); 00057 if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) 00058 ret = gnutls_record_send(this->session, message, len); 00059 } 00060 else 00061 #endif // USE_TLS 00062 ret = write(this->_socket_id, message, len); 00063 00064 BABY_UNLOCK(this->lock); 00065 if(ret < 0) 00066 logging->log_this(3, TYPE_INFO, "write to socket " + 00067 util.itos(this->socket_id()) + " failed: %m"); 00068 else 00069 this->transfered(this->transfered() + ret); 00070 00071 return ret; 00072 } 00073 00074 ssize_t Connection::receive(char *message, size_t len) 00075 { 00076 assert(len <= this->_packet_size && len > 0); 00077 ssize_t ret = -1; 00078 00079 #ifdef USE_TLS 00080 if(this->settings(TLS_ENABLED)) 00081 ret = gnutls_record_recv(this->session, message, len); 00082 else 00083 #endif 00084 ret = read(this->socket_id(), message, len); 00085 00086 this->transfered(this->transfered() + ret); 00087 00088 return ret; 00089 } 00090 00091 Connection &Connection::operator<<(long long int num) 00092 { 00093 return (*this << util.itos(num)); 00094 } 00095 00096 Connection &Connection::operator<<(string message) 00097 { 00098 if(this->send(message.c_str(), message.size()) < 0) 00099 this->settings(FAILURE, B_SET); 00100 return *this; 00101 } 00102 00103 #ifdef USE_TLS 00104 bool Connection::engage_tls(void) 00105 { 00106 bool ret = false; 00107 gnutls_init(&session, GNUTLS_SERVER); 00108 00109 gnutls_set_default_priority(this->session); 00110 00111 gnutls_credentials_set(this->session, GNUTLS_CRD_CERTIFICATE, x509_cred); 00112 00113 gnutls_certificate_server_set_request(this->session, GNUTLS_CERT_REQUEST); 00114 00115 gnutls_dh_set_prime_bits(this->session, 1024); 00116 00117 // these are for the connection cache 00118 gnutls_db_set_retrieve_function(this->session, tls_db_fetch); 00119 gnutls_db_set_remove_function(this->session, tls_db_delete); 00120 gnutls_db_set_store_function(this->session, tls_db_store); 00121 gnutls_db_set_ptr(this->session, NULL); 00122 00123 // associating the session with the socket. 00124 gnutls_transport_set_ptr(this->session, 00125 reinterpret_cast<gnutls_transport_ptr>(this->socket_id())); 00126 this->settings(TLS_INITED, B_SET); 00127 00128 if(gnutls_handshake(this->session) >= 0) 00129 { 00130 this->settings(TLS_ENABLED, B_SET); 00131 this->packet_size(gnutls_record_get_max_size(this->session)); 00132 ret = true; 00133 } 00134 00135 return ret; 00136 } 00137 00138 bool Connection::disengage_tls(void) 00139 { 00140 gnutls_bye(this->session, GNUTLS_SHUT_RDWR); 00141 this->settings(TLS_ENABLED, B_RESET); 00142 return true; 00143 } 00144 00145 bool Connection::verify_cert(void) 00146 { 00147 bool ret = false; 00148 if (gnutls_certificate_type_get(this->session) == GNUTLS_CRT_X509) 00149 { 00150 int verified = gnutls_certificate_verify_peers(this->session); 00151 if(util.is_set(verified, GNUTLS_CERT_REVOKED)) 00152 logging->log_this(2, TYPE_AUTH, this->user_name() + 00153 + " tried to login with a revoked certificate."); 00154 else if(!util.is_set(verified, GNUTLS_CERT_INVALID) && 00155 !util.is_set(verified, GNUTLS_CERT_SIGNER_NOT_FOUND)) 00156 { 00157 unsigned int cert_list_size = 0; 00158 // I really hope gnutls has their locking code in shape. get_peers just 00159 // gives us some memory.. *shudder* 00160 const gnutls_datum *cert_list = gnutls_certificate_get_peers( 00161 this->session, &cert_list_size); 00162 if(cert_list_size > 0) 00163 { 00164 gnutls_x509_crt peer_cert; 00165 gnutls_x509_crt_init(&peer_cert); 00166 gnutls_x509_crt_import(peer_cert, &cert_list[0], GNUTLS_X509_FMT_DER); 00167 char dn_buf[200] = {0}, ca_buf[200] = {0}; 00168 size_t buf_size = 199, ca_size = 199; 00169 gnutls_x509_crt_get_dn(peer_cert, dn_buf, &buf_size); 00170 gnutls_x509_crt_get_issuer_dn(peer_cert, ca_buf, &ca_size); 00171 if(buf_size > 0 && ca_size > 0) 00172 { 00173 // here we call an external program to ask if this user may login 00174 // with this cert. 00175 // format is "<user> <host/ip> <ca-dn> <cert-dn>" 00176 string call = config->general.verify_client + " " + 00177 this->user_name() + " " + this->host_name() + 00178 " \"" + ca_buf + "\" \"" + dn_buf + "\""; 00179 logging->log_this(5, TYPE_DEBUG, "running:" + call); 00180 int approved = system(call.c_str()); 00181 if(WEXITSTATUS(approved) == 0) 00182 ret = true; 00183 } 00184 gnutls_x509_crt_deinit(peer_cert); 00185 } 00186 } 00187 } 00188 return ret; 00189 } 00190 #endif // USE_TLS |
- Copyright © 2005, BabyFTPd
- Powered by: