#include #include #include "SslClient.h" SslClient::SslClient(): port(13666) { SslClient((char*)"127.0.0.1"); } SslClient::SslClient(string &addr): port(13666) { SslClient((char*)addr.c_str()); } SslClient::SslClient(char* addr): port(13666) { server = addr; /* read certificates */ QFile ca_cert_file(":/ca.crt"); ca_cert_file.open(QIODevice::ReadOnly); QByteArray ca_cert_arr = ca_cert_file.readAll(); ca_cert_file.close(); QSslCertificate ca_cert(ca_cert_arr); QList ca_certs; ca_certs.push_back(ca_cert); QFile key_file(":/client.key"); key_file.open(QIODevice::ReadOnly); QByteArray key_arr = key_file.readAll(); key_file.close(); QSslKey key(key_arr, QSsl::Rsa); QFile cert_file(":/client.crt"); cert_file.open(QIODevice::ReadOnly); QByteArray cert_arr = cert_file.readAll(); cert_file.close(); QSslCertificate cert(cert_arr); /* create ssl socket */ sslSocket = new QSslSocket; sslSocket->setLocalCertificate(cert); sslSocket->setPrivateKey(key); sslSocket->setCaCertificates(ca_certs); sslSocket->setPeerVerifyMode(QSslSocket::VerifyPeer); sslSocket->setProtocol(QSsl::SslV3); /* setup signal handlers */ connect(sslSocket, SIGNAL(encrypted()), this, SLOT(Connected())); connect(sslSocket, SIGNAL(disconnected()), this, SLOT(Disconnected())); connect(sslSocket, SIGNAL(readyRead()), this, SLOT(DataRecieved())); connect(sslSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(Error(QAbstractSocket::SocketError))); connect(sslSocket, SIGNAL(peerVerifyError(const QSslError &)), this, SLOT(PeerVerifyError(const QSslError))); connect(sslSocket, SIGNAL(sslErrors(const QList &)), this, SLOT(SslErrors(const QList &))); } void SslClient::SetServerAddr(char* addr) { server = addr; } void SslClient::SendRequest(RequestType type) { if (sslSocket->state() != QAbstractSocket::ConnectedState) sslSocket->connectToHostEncrypted(server, port); unsigned char rcode = 0x00; switch (type) { case Config: case GenericProxyList: case StaticProxyList: case FirewallList: rcode = type; break; default: Logger::Error("Invalid server request type"); break; } char data[5] = {0x13, 0x13, rcode, 0x14, 0x14}; QByteArray pkt(data); sslSocket->write(pkt); } /* * Signal handlers */ void SslClient::Connected() { Logger::Info("Connected to server %s\n", server.toStdString().c_str()); } void SslClient::Disconnected() { Logger::Info("Disconnected from server %s\n", server.toStdString().c_str()); } void SslClient::DataRecieved() { Logger::Trace("Recieved reply from %s\n", server.toStdString().c_str()); QByteArray data = sslSocket->readAll(); int length = data.size(); char h1 = data[0]; char h2 = data[1]; char t1 = data[length-1]; char t2 = data[length]; if ((h1 != 0x13) || (h2 != 0x13) || (t1 != 0x14) || (t2 != 0x14)) { Logger::Error("Invalid data packet recieved!"); return; } RequestType type; char rcode = data[2]; switch (rcode) { case Config: case GenericProxyList: case StaticProxyList: case FirewallList: type = (RequestType)rcode; break; default: Logger::Error("Invalid reply code: %x\n", rcode); return; } /* remove header and tail */ data.remove(0, 3); data.remove(length-1, 2); emit ReplyRecieved(type, data); } void SslClient::Error(QAbstractSocket::SocketError socketError) { Logger::Fatal("Socket error!"); } void SslClient::PeerVerifyError(const QSslError &error) { switch(error.error()) { case QSslError::InvalidCaCertificate: case QSslError::NoPeerCertificate: case QSslError::UnspecifiedError: case QSslError::AuthorityIssuerSerialNumberMismatch: Logger::Fatal("Critical peer verify error!, Aborting connection\n" "Error description: %s", error.errorString().toStdString().c_str()); sslSocket->abort(); break; default: Logger::Fatal("Can't verify peer: %s", error.errorString().toStdString().c_str()); break; } } void SslClient::SslErrors(const QList &errors) { if (!errors.empty()) { for (int i = 0; i < errors.size(); i++) { Logger::Fatal("%s", errors[i].errorString().toStdString().c_str()); } } }