5.77KiB; C++ | 2020-06-30 19:24:14+02 | SLOC 222
1
2
//Server
3
import std.stdio;
4
import std.socket;
5
import std.algorithm;
6
import core.thread;
7
import deimos.openssl.ssl;
8
import deimos.openssl.err;
9
static import std.c.stdio;
10
11
const ListenAddress = "127.0.0.1";
12
const ListenPort = 10443;
13
const RecvSize = 1024;
14
const CertFile = "server_cert.pem";
15
const KeyFile = "server_key.pem";
16
17
class SSLConnection : Thread{
18
	Socket r;
19
	char[RecvSize] buf;
20
	uint len;
21
	SSL_CTX *ctx;
22
	SSL *ssl;
23
24
	this(Socket r, SSL_CTX *ctx){
25
		this.r = r;
26
		this.ctx = ctx;
27
		this.isDaemon(true);
28
		super(&run);
29
	}
30
31
	void run(){
32
		writeln("new connection from ", r.remoteAddress().toString());
33
␣␣
34
		ssl = SSL_new(ctx);
35
		SSL_set_fd(ssl, r.handle());
36
		sslAssert(SSL_accept(ssl) != -1);
37
␣␣
38
		while (r.isAlive()){
39
			len = SSL_read(ssl, cast(void*) buf, RecvSize);
40
			if (len <= 0){
41
				break;
42
			}
43
			writeln("ssl read ", len, " bytes: ", buf[0 .. len]);
44
			SSL_write(ssl, cast(const void*) buf[0 .. len], len);
45
		}
46
␣␣
47
		if (r.isAlive()){
48
			writeln("close connection from ", r.remoteAddress().toString());
49
		}
50
		SSL_free(ssl);
51
		r.close();
52
	}
53
}
54
55
void sslAssert(bool ret){
56
	if (!ret){
57
		ERR_print_errors_fp(std.c.stdio.stderr);
58
		throw new Exception("SSL_ERROR");
59
	}
60
}
61
62
void initSSL(){
63
	SSL_library_init();
64
	OpenSSL_add_all_algorithms();
65
	SSL_load_error_strings();
66
}
67
68
SSL_CTX *getCTX(string certfile, string keyfile){
69
	SSL_CTX *ctx = SSL_CTX_new(SSLv3_server_method());
70
	sslAssert(!(ctx is null));
71
	sslAssert(SSL_CTX_use_certificate_file(ctx, cast(const char*) certfile, SSL_FILETYPE_PEM) > 0);
72
	sslAssert(SSL_CTX_use_PrivateKey_file(ctx, cast(const char*) keyfile, SSL_FILETYPE_PEM) > 0);
73
	sslAssert(SSL_CTX_check_private_key(ctx) > 0);
74
	return ctx;
75
}
76
77
int main(string[] args){
78
	initSSL();
79
	SSL_CTX *ctx = getCTX(CertFile, KeyFile);
80
81
	Socket s = new TcpSocket();
82
	s.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
83
	s.bind(new InternetAddress(ListenAddress, ListenPort));
84
	s.listen(10);
85
86
	writef("listen %s:%d\n", ListenAddress, ListenPort);
87
	while (s.isAlive()){
88
		Thread ss = new SSLConnection(s.accept(), ctx);
89
		ss.start();
90
	}
91
92
	s.close();
93
	SSL_CTX_free(ctx);
94
	return 0;
95
}
96
97
98
99
100
101
//Client
102
import std.stdio;
103
import std.socket;
104
import std.algorithm;
105
import std.string;
106
import core.thread;
107
import core.memory;
108
import deimos.openssl.ssl;
109
import deimos.openssl.err;
110
import deimos.openssl.sha;
111
static import std.c.stdio;
112
113
const ConnectAddress = "127.0.0.1";
114
const ConnectPort = 10443;
115
const BufSize = 1024;
116
const msg = "test message";
117
118
void sslAssert(bool ret){
119
	if (!ret){
120
		ERR_print_errors_fp(std.c.stdio.stderr);
121
		throw new Exception("SSL_ERROR");
122
	}
123
}
124
125
string getSha256(string input){
126
	char[SHA256_DIGEST_LENGTH] hash;
127
	string hash_hex;
128
	SHA256_CTX *sha256 = new SHA256_CTX;
129
	SHA256_Init(sha256);
130
	SHA256_Update(sha256, cast(const void*) input, input.length);
131
	SHA256_Final(cast(ubyte*) hash, sha256);
132
	for(int i=0; i<SHA256_DIGEST_LENGTH; i++){
133
		hash_hex ~= format("%02x", hash[i]);
134
	}
135
	return hash_hex;
136
}
137
138
string getCertInfo(X509 *cert){
139
	char buf[BufSize];
140
	uint len;
141
	string data;
142
	BIO* strio = BIO_new(BIO_s_mem());
143
	X509_print(strio, cert);
144
	//BIO_ctrl(strio, BIO_C_FILE_SEEK, 0, null);
145
	while (true){
146
		len = BIO_gets(strio, cast(char*) buf, BufSize);
147
		if (len <= 0){
148
			break;
149
		}
150
		data ~= buf[0 .. len];
151
	}
152
	BIO_free(strio);
153
	return data;
154
}
155
156
bool verifyCert(X509 *cert){
157
	X509_print_fp(std.c.stdio.stdout, cert);
158
159
	/* PEM_read... are broken
160
	//std.c.stdio.FILE *fp = std.c.stdio.fopen(cast(char*) CertFile, "rb");
161
	BIO* lcertio = BIO_new_file(cast(char*) "server_cert.pem", "rb");
162
	X509* lcert = PEM_read_bio_X509(lcertio, null, null, null);
163
	writeln(X509_verify(lcert, X509_get_pubkey(cert)));
164
	X509_free(lcert);
165
	BIO_free(lcertio);*/
166
167
	string cert_hash = getSha256(getCertInfo(cert));
168
	writeln("sha256: ", cert_hash);
169
170
	return true; //or return (cert_hash == some_const_value) to verify cert
171
}
172
173
int main(string[] args){
174
	char buf[BufSize];
175
	uint len;
176
177
	SSL_library_init();
178
	OpenSSL_add_all_algorithms();
179
	SSL_load_error_strings();
180
181
	SSL_CTX *ctx = SSL_CTX_new(SSLv3_client_method());
182
	sslAssert(!(ctx is null));
183
184
	Socket r = new TcpSocket();
185
	r.connect(new InternetAddress(ConnectAddress, ConnectPort));
186
187
	SSL *ssl = SSL_new(ctx);
188
	SSL_set_fd(ssl, r.handle());
189
	sslAssert(SSL_connect(ssl) != -1);
190
191
	if (!verifyCert(SSL_get_peer_certificate(ssl))){
192
		throw new Exception("verify cert failed");
193
	}
194
195
	SSL_write(ssl, cast(const char*) msg, msg.length);
196
	len = SSL_read(ssl, cast(void*) buf, BufSize);
197
	writef("get reply %d bytes: %s\n", len, buf[0 .. len]);
198
199
	SSL_free(ssl);
200
	r.close();
201
202
	SSL_CTX_free(ctx);
203
	return 0;
204
}
205
struct Employee
206
{
207
    uint id;
208
    uint organization_id;
209
    string name;
210
    uint age;
211
}
212
213
struct Employees
214
{
215
    Employee[] data;
216
217
    this(Employee[] employees)
218
    {
219
        data = employees;
220
    }
221
222
    Employee front()
223
    {
224
        return data[0];
225
    }
226
227
    void popFront()
228
    {
229
        data = data[1 .. $];
230
    }
231
232
    bool empty()
233
    {
234
        return data.length == 0;
235
    }
236
}
237
238
void main()
239
{
240
    import std.algorithm.iteration : filter, chunkBy;
241
242
    Employees employees = Employees([
243
        Employee(1, 1, "George", 50),
244
        Employee(2, 3, "John", 65),
245
        Employee(3, 2, "David", 40),
246
        Employee(4, 1, "Eli", 40),
247
        Employee(5, 2, "Hal", 35)
248
    ]);
249
250
    auto older_employees = employees
251
        .filter!(a => a.age > 40) // lambdas in D use the => syntax
252
        .chunkBy!((a,b) => a.organization_id == b.organization_id);
253
}
254
void main()
255
{
256
    import std.algorithm.iteration : filter, chunkBy;
257
258
    Employees employees = Employees([
259
        Employee(1, 1, "George", 50),
260
        Employee(2, 3, "John", 65),
261
        Employee(3, 2, "David", 40),
262
        Employee(4, 1, "Eli", 40),
263
        Employee(5, 2, "Hal", 35)
264
    ]);
265
266
    auto older_employees = employees
267
        .filter!(a => a.age > 40) // lambdas in D use the => syntax
268
        .chunkBy!((a,b) => a.organization_id == b.organization_id);
269 1
}