-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathserver.cpp
More file actions
139 lines (125 loc) · 4.39 KB
/
Copy pathserver.cpp
File metadata and controls
139 lines (125 loc) · 4.39 KB
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
#include "server.h"
Server::Server(int port) {
cout << "Running program as server" << endl;
this->m_nListenPort = port;
// initalize server specific parameters
FD_ZERO(&m_masterSet);
FD_ZERO(&m_readSet);
// starting event handler
eventHandler();
}
Server::~Server() {
}
void Server::startListener() {
struct sockaddr_in m_srvAddr;
// add stdin to master set
FD_SET(STDIN, &m_masterSet);
// populate server address structure
m_srvAddr.sin_family = AF_INET;
m_srvAddr.sin_port = htons(m_nListenPort);
m_srvAddr.sin_addr.s_addr = INADDR_ANY;
// create a TCP listening socket
if((m_nListenSd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Listening socket creation failed");
exit(EXIT_FAILURE);
}
// reuse the socket in case of crash
int optval = 1;
if(setsockopt(m_nListenSd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) < 0) {
perror("setsockopt failed");
exit(EXIT_FAILURE);
}
// bind m_srvAddr to the listening socket
if(bind(m_nListenSd, (struct sockaddr *)&m_srvAddr, sizeof(m_srvAddr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("Server is now listening on port: %d \n", m_nListenPort);
// maximum of 5 pending connections for m_nListenSd socket
if(listen(m_nListenSd, 5)) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
// add listening socket to master set and update m_nMaxFd
FD_SET(m_nListenSd, &m_masterSet);
m_nMaxFd = m_nListenSd;
}
void Server::eventHandler() {
char buffer[1024];
SSL_library_init();
SSL_CTX *ctx = InitServerCTX();
LoadCertificates(ctx, "mycert.pem", "mycert.pem");
startListener();
while (1)
{ struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
int client = accept(m_nListenSd, (struct sockaddr*)&addr, &len); /* accept connection as usual */
printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
ssl = SSL_new(ctx); /* get new SSL state with context */
SSL_set_fd(ssl, client); /* set connection socket to SSL state */
Servlet(ssl); /* service connection */
}
close(m_nListenSd); /* close server socket */
SSL_CTX_free(ctx); /* release context */
}
void Server::Servlet(SSL* ssl) /* Serve the connection -- threadable */
{ char buf[1024];
char reply[1024];
int sd, bytes;
const char* HTMLecho="<html><body><pre>%s</pre></body></html>\n\n";
if ( SSL_accept(ssl) == 0 ) /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
else
{
//ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
if ( bytes > 0 )
{
buf[bytes] = 0;
//printf("Client msg: \"%s\"\n", buf);
sprintf(reply, HTMLecho, buf); /* construct reply */
SSL_write(ssl, reply, strlen(reply)); /* send reply */
}
else
ERR_print_errors_fp(stderr);
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
void Server::LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
/* set the local certificate from CertFile */
if ( SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0 )
{
ERR_print_errors_fp(stderr);
abort();
}
/* set the private key from KeyFile (may be the same as CertFile) */
if ( SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0 )
{
ERR_print_errors_fp(stderr);
abort();
}
/* verify private key */
if ( !SSL_CTX_check_private_key(ctx) )
{
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
}
SSL_CTX* Server::InitServerCTX(void)
{ const SSL_METHOD *method;
SSL_CTX *ctx;
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
method = SSLv3_server_method(); /* create new server-method instance */
ctx = SSL_CTX_new(method); /* create new context from method */
if ( ctx == NULL )
{
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
}