1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/* RequiredLibraries: ssl,crypt */
#include "module.h"
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#define CERTFILE "anope.cert"
#define KEYFILE "anope.key"
static SSL_CTX *ctx;
class SSLSocket : public Socket
{
private:
SSL *sslsock;
int RecvInternal(char *buf, size_t sz) const
{
return SSL_read(sslsock, buf, sz);
}
int SendInternal(const std::string &buf) const
{
return SSL_write(sslsock, buf.c_str(), buf.size());
}
public:
SSLSocket(const std::string &nTargetHost, int nPort, const std::string &nBindHost = "", bool nIPv6 = false) : Socket(nTargetHost, nPort, nBindHost, nIPv6)
{
sslsock = SSL_new(ctx);
if (!sslsock)
throw CoreException("Unable to initialize SSL socket");
SSL_set_connect_state(sslsock);
SSL_set_fd(sslsock, Sock);
SSL_connect(sslsock);
UplinkSock = this;
}
~SSLSocket()
{
SSL_shutdown(sslsock);
SSL_free(sslsock);
UplinkSock = NULL;
}
bool Read(const std::string &buf)
{
process(buf);
return true;
}
};
class SSLModule : public Module
{
public:
SSLModule(const std::string &modname, const std::string &creator) : Module(modname, creator)
{
this->SetAuthor("Anope");
this->SetVersion("$Id$");
this->SetType(SUPPORTED);
this->SetPermanent(true);
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
ctx = SSL_CTX_new(SSLv23_client_method());
if (!ctx)
{
throw ModuleException("Error initializing SSL CTX");
}
if (IsFile(CERTFILE))
{
if (!SSL_CTX_use_certificate_file(ctx, CERTFILE, SSL_FILETYPE_PEM))
{
SSL_CTX_free(ctx);
throw ModuleException("Error loading certificate");
}
}
else
{
Alog() << "m_ssl: No certificate file found";
}
if (IsFile(KEYFILE))
{
if (!SSL_CTX_use_PrivateKey_file(ctx, KEYFILE, SSL_FILETYPE_PEM))
{
SSL_CTX_free(ctx);
throw ModuleException("Error loading private key");
}
}
else
{
if (IsFile(CERTFILE))
{
SSL_CTX_free(ctx);
throw ModuleException("Error loading private key - file not found");
}
else
{
Alog() << "m_ssl: No private key found";
}
}
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_options(ctx, SSL_OP_TLS_ROLLBACK_BUG | SSL_OP_ALL);
ModuleManager::Attach(I_OnPreServerConnect, this);
}
~SSLModule()
{
SSL_CTX_free(ctx);
}
EventReturn OnPreServerConnect(Uplink *u, int Number)
{
ConfigReader config;
if (config.ReadFlag("uplink", "ssl", "no", Number - 1))
{
try
{
new SSLSocket(u->host, u->port, Config.LocalHost ? Config.LocalHost : "", u->ipv6);
Alog() << "Connected to Server " << Number << " (" << u->host << ":" << u->port << ")";
}
catch (SocketException& ex)
{
Alog() << "Unable to connect with SSL to server" << Number << " (" << u->host << ":" << u->port << "), " << ex.GetReason();
}
return EVENT_ALLOW;
}
return EVENT_CONTINUE;
}
};
MODULE_INIT(SSLModule)
|