1 /*
2 Copyright (C) 2008-2017, Millistream Market Data <support@millistream.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 */
18
19 #include <sys/select.h>
20 #include "common.h"
21 #include "encode.h"
22 #include "crypt.h"
23
24 /* buf must be at least 5 bytes */
add_len(uint8_t * buf,uint32_t len)25 static int add_len (uint8_t *buf, uint32_t len)
26 {
27 uint8_t *p = buf;
28 uint32_t tmp = len;
29 uint32_t offset = 0;
30 int d;
31 int c = 0;
32
33 do {
34 ++c;
35 offset = offset * 128 + 1;
36 tmp = (tmp - 1) / 128;
37 } while (tmp != 0);
38
39 len -= offset;
40 d = c - 1;
41
42 do {
43 p[--c] = (uint8_t) (len % 128);
44 len /= 128;
45 } while (c != 0);
46
47 p += d;
48
49 *p++ |= 128;
50
51 return p - buf;
52 }
53
54 /* buf must be at least 11 bytes */
add_header(uint8_t * buf,uint16_t mref,uint64_t insref)55 static int add_header (uint8_t *buf, uint16_t mref, uint64_t insref)
56 {
57 uint8_t *p = buf;
58 uint8_t *attr = buf;
59
60 if (mref <= 256) {
61 *p++ = 0;
62 *p++ = (uint8_t) mref;
63 } else {
64 *p++ = 128;
65 *((uint16_t *)p) = cpu_to_le16 (mref);
66 p += 2;
67 }
68
69 if (insref <= 8191) {
70 *attr |= (uint8_t) (insref >> 8);
71 *p++ = (uint8_t) (insref & __UINT64_C (0x00000000000000FF));
72 } else if (insref <= 2105343) {
73 insref -= 8192;
74 *attr |= 32 | (uint8_t) (insref >> 16);
75 *((uint16_t *)p) = cpu_to_le16 ((uint16_t)(insref & __UINT64_C (0x000000000000FFFF)));
76 p += 2;
77 } else if (insref <= __UINT64_C (137441058815)) {
78 insref -= 2105344;
79 *attr |= 64 | (uint8_t) (insref >> 32);
80 *((uint32_t *)p) = cpu_to_le32 ((uint32_t)(insref & __UINT64_C (0x00000000FFFFFFFF)));
81 p += 4;
82 } else {
83 *attr |= 96;
84 *((uint64_t *)p) = cpu_to_le64 (insref);
85 p += 8;
86 }
87
88 return p - buf;
89 }
90
compare_tags(const void * A,const void * B)91 static int compare_tags (const void *A, const void *B)
92 {
93 return (((const struct msg_field *)A)->tag - ((const struct msg_field *)B)->tag);
94 }
95
mdf_int_rebalance_templates(struct msg_template * const templates,const int templates_num)96 void mdf_int_rebalance_templates (struct msg_template * const templates, const int templates_num)
97 {
98 int i, j;
99 for (i = 0; i < templates_num; i++) {
100 free (templates[i].fields);
101
102 if (templates[i].tags_num == 0) {
103 templates[i].fields = NULL;
104 continue;
105 }
106
107 templates[i].fields = (struct msg_field *) malloc ((sizeof *templates[i].fields) * templates[i].tags_num);
108
109 for (j = 0; j < templates[i].tags_num; j++) {
110 templates[i].fields[j].pos = j;
111 templates[i].fields[j].tag = templates[i].tags[j];
112 }
113
114 qsort (templates[i].fields, templates[i].tags_num, sizeof *templates[i].fields, compare_tags);
115 }
116 }
117
mdf_create()118 mdf_t mdf_create ()
119 {
120 struct mdf_s *handle;
121 #if defined (HAVE_SIGACTION) && defined (SIGPIPE)
122 struct sigaction act;
123 #endif
124 #if defined _WIN32 || defined _WIN64
125 WSADATA wsaData;
126
127 if (WSAStartup (MAKEWORD (2,2), &wsaData) != 0)
128 return NULL;
129 #endif
130 handle = (struct mdf_s *) calloc (1, sizeof *handle);
131
132 if (handle == NULL) {
133 #if defined _WIN32 || defined _WIN64
134 WSACleanup ();
135 #endif
136 return NULL;
137 }
138
139 handle->data_size = 10240;
140 handle->data = (uint8_t *) malloc (handle->data_size);
141 handle->timediff = 0;
142 handle->vlen = 1024;
143 handle->value = (uint8_t *) malloc (handle->vlen);
144 handle->fstatus = 2;
145 handle->error = MDF_ERR_NO_ERROR;
146 handle->fd = INVALID_SOCKET;
147 handle->connect_timeout = 5;
148 handle->heartbeat_interval = 30;
149 handle->max_missed_heartbeats = 2;
150 handle->cstate = CSTATE_INVALID;
151
152 if (handle->data == NULL || handle->value == NULL) {
153 #if defined _WIN32 || defined _WIN64
154 WSACleanup ();
155 #endif
156 free (handle->data);
157 handle->data = NULL;
158
159 free (handle->value);
160 handle->value = NULL;
161
162 free (handle);
163 return NULL;
164 }
165
166 /* setup version #0 of the message templates, this is enough to
167 * be able to receive the message templates message, to create
168 * a logon message and to receive a possible logoff message */
169 handle->templates_num = 3;
170 handle->templates = (struct msg_template *) calloc (handle->templates_num, sizeof *handle->templates);
171
172 handle->templates[MDF_M_MESSAGESREFERENCE].mclass = MDF_MC_UNDEF;
173 handle->templates[MDF_M_MESSAGESREFERENCE].tags_num = 1;
174 handle->templates[MDF_M_MESSAGESREFERENCE].tags = (uint32_t *) malloc (sizeof (uint32_t) * handle->templates[MDF_M_MESSAGESREFERENCE].tags_num);
175 handle->templates[MDF_M_MESSAGESREFERENCE].tags[0] = 0xffffffff;
176
177 handle->templates[MDF_M_LOGON].mclass = MDF_MC_UNDEF;
178 handle->templates[MDF_M_LOGON].tags_num = 3;
179 handle->templates[MDF_M_LOGON].tags = (uint32_t *) malloc (sizeof (uint32_t) * handle->templates[MDF_M_LOGON].tags_num);
180 handle->templates[MDF_M_LOGON].tags[0] = MDF_F_USERNAME;
181 handle->templates[MDF_M_LOGON].tags[1] = MDF_F_PASSWORD;
182 handle->templates[MDF_M_LOGON].tags[2] = MDF_F_EXTRACREDENTIAL;
183
184 handle->templates[MDF_M_LOGOFF].mclass = MDF_MC_UNDEF;
185 handle->templates[MDF_M_LOGOFF].tags_num = 1;
186 handle->templates[MDF_M_LOGOFF].tags = (uint32_t *) malloc (sizeof (uint32_t) * handle->templates[MDF_M_LOGOFF].tags_num);
187 handle->templates[MDF_M_LOGOFF].tags[0] = MDF_F_LOGOFFREASON;
188
189 mdf_int_rebalance_templates (handle->templates, handle->templates_num);
190
191 #if defined (HAVE_SIGACTION) && defined (SIGPIPE)
192 memset (&act, 0, sizeof act);
193 act.sa_handler = SIG_IGN;
194 sigaction (SIGPIPE, &act, NULL);
195 #elif defined (HAVE_SIGNAL) && defined (SIGPIPE)
196 signal (SIGPIPE, SIG_IGN);
197 #endif
198 return handle;
199 }
200
mdf_destroy(mdf_t handle)201 void mdf_destroy (mdf_t handle)
202 {
203 int i;
204
205 if (handle == NULL)
206 return;
207
208 mdf_disconnect (handle);
209
210 free (handle->data);
211 handle->data = NULL;
212
213 free (handle->value);
214 handle->value = NULL;
215
216 free (handle->connected_host);
217 handle->connected_host = NULL;
218
219 free (handle->connected_ip);
220 handle->connected_ip = NULL;
221
222 for (i = 0; i < handle->templates_num; i++) {
223 free (handle->templates[i].tags);
224 free (handle->templates[i].fields);
225 }
226
227 free (handle->templates);
228 handle->templates = NULL;
229
230 free (handle->sendfields);
231 handle->sendfields = NULL;
232
233 free (handle->sendtags);
234 handle->sendtags = NULL;
235
236 free (handle->sendbuf);
237 handle->sendbuf = NULL;
238
239 free (handle);
240
241 #if defined _WIN32 || defined _WIN64
242 WSACleanup ();
243 #endif
244 }
245
call_status_callback(mdf_t handle,MDF_CONN_STATUS status,const char * host,const char * ip)246 static void call_status_callback (mdf_t handle, MDF_CONN_STATUS status, const char *host, const char *ip)
247 {
248 if (handle->callbacks.func_status == NULL)
249 return;
250
251 handle->callbacks.func_status (handle->callbacks.udata_status, status, host, ip);
252 }
253
disconnect(mdf_t handle)254 static void disconnect (mdf_t handle)
255 {
256 if (handle->master_secret != NULL) {
257 memset (handle->master_secret, 0x00, handle->digest_length);
258 free (handle->master_secret);
259 handle->master_secret = NULL;
260 }
261
262 free (handle->client_iv);
263 handle->client_iv = NULL;
264
265 free (handle->server_iv);
266 handle->server_iv = NULL;
267
268 free (handle->client_enc);
269 handle->client_enc = NULL;
270
271 free (handle->server_enc);
272 handle->server_enc = NULL;
273
274 if (handle->client_hmac != NULL) {
275 #if OPENSSL_VERSION_NUMBER < 0x10100000L
276 HMAC_CTX_cleanup (handle->client_hmac);
277 OPENSSL_free (handle->client_hmac);
278 #else
279 HMAC_CTX_free (handle->client_hmac);
280 #endif
281 handle->client_hmac = NULL;
282 }
283
284 if (handle->server_hmac != NULL) {
285 #if OPENSSL_VERSION_NUMBER < 0x10100000L
286 HMAC_CTX_cleanup (handle->server_hmac);
287 OPENSSL_free (handle->server_hmac);
288 #else
289 HMAC_CTX_free (handle->server_hmac);
290 #endif
291 handle->server_hmac = NULL;
292 }
293
294 handle->data_pos = 0;
295 handle->data_used = 0;
296 handle->fstatus = 2;
297 handle->error = MDF_ERR_NO_ERROR;
298
299 #if defined _WIN32 || defined _WIN64
300 closesocket (handle->fd);
301 #else
302 close (handle->fd);
303 #endif
304 handle->fd = INVALID_SOCKET;
305
306 call_status_callback (handle, MDF_STATUS_DISCONNECTED, handle->connected_host, handle->connected_ip);
307 }
308
read_int_msg(mdf_t handle,uint8_t * buf,ssize_t * restrict len,int * restrict pos,const size_t maxlen)309 static int read_int_msg (mdf_t handle, uint8_t *buf, ssize_t * restrict len, int * restrict pos, const size_t maxlen)
310 {
311 size_t offset = 0;
312 size_t toread = 0;
313
314 do {
315 ssize_t ret;
316 fd_set fdset;
317 struct timeval tv;
318
319 FD_ZERO (&fdset);
320 FD_SET (handle->fd, &fdset);
321
322 tv.tv_sec = 10;
323 tv.tv_usec = 0;
324
325 ret = select (handle->fd + 1, &fdset, NULL, NULL, &tv);
326
327 if (ret != 1)
328 return -1;
329
330 ret = recv (handle->fd, (char *) (buf + offset), maxlen - offset, 0);
331
332 if (ret < 1)
333 return -1;
334
335 handle->bytes_read += ret;
336 offset += ret;
337
338 if (offset < 5)
339 continue;
340
341 if (toread == 0) {
342 int i = 0;
343
344 do {
345 toread *= 128;
346 toread += (buf[i] & 127) + 1;
347 } while ((buf[i++] & 128) == 0 && i < 5);
348
349 *len = toread + i;
350 *pos = i;
351
352 toread += i;
353
354 if (toread > maxlen)
355 return -1;
356
357 toread -= offset;
358 } else
359 toread -= ret;
360 } while (toread != 0);
361
362 return 0;
363 }
364
send_greeting(mdf_t handle)365 static int send_greeting (mdf_t handle)
366 {
367 int used = 5;
368 int offset;
369 int msg1_len;
370 int msg2_len;
371 int msg2_offset;
372 ssize_t len;
373 ssize_t hostlen;
374 int64_t expiry;
375 uint32_t tmp_u32;
376 uint8_t *msg1;
377 uint8_t *buf;
378 uint8_t *Na;
379 uint8_t *Nb = NULL;
380 uint8_t *master_key;
381 BIGNUM *X = NULL;
382 union digest_ctx ctx1;
383 union digest_ctx ctx2;
384 unsigned char md[MAX_DIGEST_LENGTH];
385 DH *dh;
386 RSA *rsa_master = NULL;
387 RSA *rsa_server = NULL;
388 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
389 BIGNUM *bn1 = NULL;
390 BIGNUM *bn2 = NULL;
391 #endif
392
393 /* As part of setting up the connection with the server, the client
394 * must initiate a crypto handshake with the server. The first
395 * message from the client will contain the mdf version (for book-
396 * keeping), a random nonce (Na), the minimum number of bytes that
397 * the client accepts for the DH p parameter, and a list of the
398 * digests and encryptions that we support. */
399 len = sizeof (MDF_VERSION) - 1;
400
401 if (len > 255) {
402 disconnect (handle);
403 return 0;
404 }
405
406 hostlen = sizeof (MDF_BUILD_HOST) - 1;
407
408 if (hostlen > 255) {
409 disconnect (handle);
410 return 0;
411 }
412
413 msg1 = malloc (5 + 11 + sizeof (uint64_t) + sizeof (uint8_t) + len + sizeof (uint32_t) + sizeof md + sizeof (uint32_t) + mdf_int_sizeof_cryptmethods () + sizeof (uint8_t) + hostlen);
414 Na = malloc (sizeof md);
415
416 used += add_header (msg1 + used, 0, 0);
417
418 *((uint64_t *)(msg1 + used)) = cpu_to_le64 (handle->template_version);
419 used += sizeof (uint64_t);
420
421 msg1[used++] = (uint8_t) len;
422
423 memcpy (msg1 + used, MDF_VERSION, len);
424 used += len;
425
426 /* we send the largest Na that we can produce */
427 if (RAND_bytes (Na, sizeof md) != 1) {
428 free (Na);
429 free (msg1);
430 disconnect (handle);
431 return 0;
432 }
433
434 *((uint32_t *)(msg1 + used)) = cpu_to_le32 (sizeof md);
435 used += sizeof (uint32_t);
436 memcpy (msg1 + used, Na, sizeof md);
437 used += sizeof md;
438
439 *((uint32_t *)(msg1 + used)) = cpu_to_le32 (MIN_DH_LENGTH);
440 used += sizeof (uint32_t);
441
442 /* we add the list of supported digest and encryption methods */
443 mdf_int_populate_cryptmethods (msg1, &used);
444
445 /* add the MDF_BUILD_HOST info */
446 msg1[used++] = (uint8_t) hostlen;
447 memcpy (msg1 + used, MDF_BUILD_HOST, hostlen);
448 used += hostlen;
449
450 msg1_len = used - 5;
451
452 offset = 5 - add_len (msg1, msg1_len);
453
454 if (offset != 0) {
455 memmove (msg1 + offset, msg1, 5 - offset);
456 used -= offset;
457 }
458
459 len = send (handle->fd, (void *)(msg1 + offset), used, 0);
460
461 if (len != used) {
462 free (Na);
463 free (msg1);
464 disconnect (handle);
465 return 0;
466 }
467
468 handle->bytes_written += len;
469
470 /* We should now receive the first message from the server. This
471 * message will contain the public DH parameters (g, p), the
472 * server public DH key (X), a random nonce (Nb), the server
473 * public RSA key (e,n) and a signature from the "master" to
474 * authenticate the public RSA key, the hostname etc.
475 * Last in the message is a RSA signature created with the
476 * server key of all bytes exchanged so far (by both parties).
477 *
478 * Since the signature covers the random nonce (Na) that the
479 * client generated, the client now knows two things:
480 * 1. The server has seen the first message from the client,
481 * so there was no man-in-the-middle fiddling with the
482 * message trying to impersonate as the client.
483 *
484 * 2. This message does indeed come from the server, it
485 * carries the servers signature and it is not part in
486 * any reply attack since Na was randomly chosen.
487 */
488 buf = malloc (201728);
489
490 if (read_int_msg (handle, buf, &len, &offset, 201728) == -1) {
491 free (Na);
492 free (buf);
493 free (msg1);
494 disconnect (handle);
495 return 0;
496 }
497
498 msg2_len = len - offset;
499
500 dh = DH_new ();
501
502 if (len < 100)
503 goto exit_in_error;
504
505 msg2_offset = offset;
506
507 if (buf[offset] != 0x00 || buf[offset + 1] != 0x00 || buf[offset + 2] != 0x03)
508 goto exit_in_error;
509
510 offset += 3;
511
512 /* do we support the suggested encryption method? */
513 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
514 offset += sizeof (uint32_t);
515
516 if (mdf_int_encryptions_verify (used, &handle->encryption_method) == 0)
517 goto exit_in_error;
518
519 /* do we support the suggested digest method? */
520 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
521 offset += sizeof (uint32_t);
522
523 if (mdf_int_digests_verify (used, &handle->digest_method, &handle->digest_length) == 0)
524 goto exit_in_error;
525
526 /* since we now know the digest method of choice we can calculate what the
527 * digest of our first message should have been! */
528 mdf_int_digest_init (handle->digest_method, &ctx1);
529
530 tmp_u32 = cpu_to_le32 (1); /* message no 1 */
531 mdf_int_digest_update (handle->digest_method, &ctx1, &tmp_u32, sizeof tmp_u32);
532
533 tmp_u32 = cpu_to_le32 (msg1_len);
534 mdf_int_digest_update (handle->digest_method, &ctx1, &tmp_u32, sizeof tmp_u32);
535 mdf_int_digest_update (handle->digest_method, &ctx1, msg1 + 5, msg1_len);
536
537 free (msg1);
538 msg1 = NULL;
539
540 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
541 offset += sizeof (uint32_t);
542
543 /* do we have room for g and p-len? */
544 if (offset + used + (int)sizeof (uint32_t) > len)
545 goto exit_in_error;
546
547 #if OPENSSL_VERSION_NUMBER < 0x10100000L
548 dh->g = BN_bin2bn (buf + offset, used, NULL);
549 #else
550 bn1 = BN_bin2bn (buf + offset, used, NULL);
551 #endif
552 offset += used;
553
554 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
555 offset += sizeof (uint32_t);
556
557 /* do we have room for p and X-len? */
558 if (offset + used + (int)sizeof (uint32_t) > len)
559 goto exit_in_error;
560
561 /* make sure that p is within limits */
562 if (used < MIN_DH_LENGTH || used > MAX_DH_LENGTH)
563 goto exit_in_error;
564
565 #if OPENSSL_VERSION_NUMBER < 0x10100000L
566 dh->p = BN_bin2bn (buf + offset, used, NULL);
567 #else
568 bn2 = BN_bin2bn (buf + offset, used, NULL);
569
570 if (DH_set0_pqg (dh, bn2, NULL, bn1) == 0)
571 goto exit_in_error;
572
573 /* clear these so that we don't do a double free on exit */
574 bn1 = NULL;
575 bn2 = NULL;
576 #endif
577
578 offset += used;
579
580 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
581 offset += sizeof (uint32_t);
582
583 /* do we have room for X and Nb-len? */
584 if (offset + used + (int)sizeof (uint32_t) > len)
585 goto exit_in_error;
586
587 X = BN_bin2bn (buf + offset, used, NULL);
588 offset += used;
589
590 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
591 offset += sizeof (uint32_t);
592
593 /* do we have room for Nb and master siglen? */
594 if (offset + used + (int)sizeof (uint32_t) > len || used != handle->digest_length)
595 goto exit_in_error;
596
597 Nb = malloc (used);
598 memcpy (Nb, buf + offset, used);
599 offset += used;
600
601 rsa_master = mdf_int_load_rsapublickey ();
602
603 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
604
605 /* do we have room for the master signature block? */
606 if (offset + used + 1 > len || used <= RSA_size (rsa_master))
607 goto exit_in_error;
608
609 /* verify the master signature */
610 mdf_int_digest_init (handle->digest_method, &ctx2);
611 mdf_int_digest_update (handle->digest_method, &ctx2, buf + offset, used - RSA_size (rsa_master));
612 mdf_int_digest_final (handle->digest_method, md, &ctx2);
613
614 if (mdf_int_digest_verify (handle->digest_method, md, buf + offset + (used - RSA_size (rsa_master)), RSA_size (rsa_master), rsa_master) == 0)
615 goto exit_in_error;
616
617 offset += sizeof (uint32_t);
618
619 /* verify the hostname from the master signature */
620 used = 0;
621 for (tmp_u32 = buf[offset++]; tmp_u32 != 0; tmp_u32--) {
622 if (offset + buf[offset] + 1 > len)
623 goto exit_in_error;
624
625 if (buf[offset] == strlen (handle->connected_host) && memcmp (buf + offset + 1, handle->connected_host, buf[offset]) == 0)
626 used = 1;
627 else if (buf[offset] == strlen (handle->connected_ip) && memcmp (buf + offset + 1, handle->connected_ip, buf[offset]) == 0)
628 used = 1;
629
630 offset += buf[offset] + 1;
631 }
632
633 if (used == 0)
634 goto exit_in_error;
635
636 /* do we have room for the expiry time and e-len? */
637 if (offset + (int)(sizeof (int64_t) + sizeof (uint32_t)) > len)
638 goto exit_in_error;
639
640 /* has the signature expired? */
641 expiry = le64_to_cpu (*((int64_t *)(buf + offset)));
642
643 if (time (NULL) >= expiry)
644 goto exit_in_error;
645
646 offset += sizeof (int64_t);
647
648 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
649 offset += sizeof (uint32_t);
650
651 /* do we have room for e, n-len and is e of the appropiate size? */
652 if (offset + used + (int)sizeof (uint32_t) > len || used > OPENSSL_RSA_MAX_PUBEXP_BITS * 8 || used < 1)
653 goto exit_in_error;
654
655 rsa_server = RSA_new ();
656
657 #if OPENSSL_VERSION_NUMBER < 0x10100000L
658 rsa_server->e = BN_bin2bn (buf + offset, used, NULL);
659 #else
660 bn1 = BN_bin2bn (buf + offset, used, NULL);
661 #endif
662 offset += used;
663
664 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
665 offset += sizeof (uint32_t);
666
667 /* do we have room for n, signature-len and is n of the appropiate size? */
668 if (offset + used + (int)sizeof (uint32_t) > len || used > OPENSSL_RSA_MAX_MODULUS_BITS * 8 || used < 256)
669 goto exit_in_error;
670
671 #if OPENSSL_VERSION_NUMBER < 0x10100000L
672 rsa_server->n = BN_bin2bn (buf + offset, used, NULL);
673 #else
674 bn2 = BN_bin2bn (buf + offset, used, NULL);
675
676 if (RSA_set0_key (rsa_server, bn2, bn1, NULL) == 0)
677 goto exit_in_error;
678
679 /* clear these so that we don't do a double free on exit */
680 bn1 = NULL;
681 bn2 = NULL;
682 #endif
683 offset += used;
684
685 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
686 offset += sizeof (uint32_t);
687
688 /* do we have room for the signature and the sig-len, and is the signature of the correct size? */
689 if (offset + used + (int)sizeof (uint32_t) > len || used != RSA_size (rsa_master))
690 goto exit_in_error;
691
692 /* ok, come this far we have now verified that we have got a valid RSA key from the server.
693 * We know that it hasn't expired, that it's hostname matches that to which we are connected to,
694 * and that the master signature was valid. */
695
696 offset += used;
697 RSA_free (rsa_master);
698 rsa_master = NULL;
699
700 /* let's look at the server's signature */
701 used = le32_to_cpu (*((uint32_t *)(buf + offset)));
702 offset += sizeof (uint32_t);
703
704 tmp_u32 = cpu_to_le32 (2); /* message no 2 */
705 mdf_int_digest_update (handle->digest_method, &ctx1, &tmp_u32, sizeof tmp_u32);
706
707 tmp_u32 = cpu_to_le32 (msg2_len);
708 mdf_int_digest_update (handle->digest_method, &ctx1, &tmp_u32, sizeof tmp_u32);
709 mdf_int_digest_update (handle->digest_method, &ctx1, buf + msg2_offset, offset - msg2_offset);
710
711 /* do we have room for the signature, and is the signature the correct size? */
712 if (offset + used > len || used != RSA_size (rsa_server))
713 goto exit_in_error;
714
715 /* we make a copy of the CTX since we need to send an AUTH for the
716 * client as well and mdf_int_digest_final() will destroy the context */
717 memcpy (&ctx2, &ctx1, sizeof ctx2);
718 mdf_int_digest_final (handle->digest_method, md, &ctx1);
719
720 /* is the signature valid? */
721 if (mdf_int_digest_verify (handle->digest_method, md, buf + offset, used, rsa_server) == 0)
722 goto exit_in_error;
723
724 RSA_free (rsa_server);
725 rsa_server = NULL;
726
727 /* the signature is included in the clients AUTH */
728 mdf_int_digest_update (handle->digest_method, &ctx2, buf + offset, used);
729
730 /* we check that p is a safe prime and that g is a suitable generator,
731 * since we wouldn't want to be catched with our pants down. And also
732 * we do this _after_ we checked the RSA signatures so we have at least
733 * some guarantees that we haven't received values that will keep us up
734 * all night performing the check, or whatever nasty ugliness that could
735 * have happened. */
736 if (DH_check (dh, &used) == 0)
737 goto exit_in_error;
738
739 if (DH_generate_key (dh) == 0)
740 goto exit_in_error;
741
742 master_key = malloc (DH_size (dh));
743
744 used = DH_compute_key (master_key, X, dh);
745
746 if (used == -1) {
747 free (master_key);
748 goto exit_in_error;
749 }
750
751 BN_free (X);
752 X = NULL;
753
754 handle->master_secret = malloc (handle->digest_length);
755 mdf_int_digest_init (handle->digest_method, &ctx1);
756 mdf_int_digest_update (handle->digest_method, &ctx1, master_key, used);
757 mdf_int_digest_final (handle->digest_method, handle->master_secret, &ctx1);
758
759 memset (master_key, 0x00, used);
760 free (master_key);
761
762 mdf_int_set_keys (handle, Na, sizeof md, &handle->client_enc, &handle->client_hmac, &handle->client_iv);
763 mdf_int_set_keys (handle, Nb, handle->digest_length, &handle->server_enc, &handle->server_hmac, &handle->server_iv);
764
765 free (Na);
766 Na = NULL;
767
768 free (Nb);
769 Nb = NULL;
770
771 /* Now we construct the final packet in our crypto handshake,
772 * this message will contain the clients public DH key and the
773 * client AUTH encrypted with the client encryption key.
774 *
775 * This AUTH will not authenticate the client as such (the server
776 * does not know which client it is until the client sends the
777 * username/password credentials, and the client lacks a RSA key.
778 *
779 * No, the reason for the AUTH is to complete the handshake and to
780 * make sure that the server has a secure channel open with "someone"
781 * and that this "someone" was the very same entity who sent the very
782 * first message in the handshake. This is not as bad as it sounds,
783 * this is exactly like secure web browsing (aka SSL/TLS).
784 *
785 * The client on the other had does know that it is communicating
786 * with the server due to the RSA signature, and this is what is
787 * really important since it is the client who will have to send
788 * its password over the wire, and we better make sure it's to no
789 * stranger. */
790 used = 5;
791
792 used += add_header (buf + used, 0, 4);
793
794 #if OPENSSL_VERSION_NUMBER < 0x10100000L
795 len = BN_bn2bin (dh->pub_key, buf + used + sizeof (uint32_t));
796 #else
797 const BIGNUM *dh_pub, *dh_priv;
798 DH_get0_key (dh, &dh_pub, &dh_priv);
799 len = BN_bn2bin (dh_pub, buf + used + sizeof (uint32_t));
800 #endif
801
802 *((uint32_t *)(buf + used)) = cpu_to_le32 (len);
803 used += sizeof (uint32_t) + len;
804
805 DH_free (dh);
806 dh = NULL;
807
808 *((uint32_t *)(buf + used)) = cpu_to_le32 (handle->digest_length);
809 used += sizeof (uint32_t);
810
811 /* len is now as far as we have to calculate AUTH, we have to
812 * perform this little tap dance since we need the message length
813 * attached to be able to calculate the correct message digest */
814 len = used;
815 used += handle->digest_length;
816
817 tmp_u32 = cpu_to_le32 (3); /* message no 3 */
818 mdf_int_digest_update (handle->digest_method, &ctx2, &tmp_u32, sizeof tmp_u32);
819
820 tmp_u32 = cpu_to_le32 (used - 5);
821 mdf_int_digest_update (handle->digest_method, &ctx2, &tmp_u32, sizeof tmp_u32);
822 mdf_int_digest_update (handle->digest_method, &ctx2, buf + 5, len - 5);
823
824 offset = 5 - add_len (buf, used - 5);
825
826 if (offset != 0) {
827 memmove (buf + offset, buf, 5 - offset);
828 used -= offset;
829 }
830
831 mdf_int_digest_final (handle->digest_method, buf + len, &ctx2);
832
833 mdf_int_encrypt_aes_ctr (buf + len, handle->digest_length, handle->client_enc, handle->client_iv);
834 len = send (handle->fd, (void *)(buf + offset), used, 0);
835
836 if (len != used)
837 goto exit_in_error;
838
839 handle->bytes_written += len;
840 handle->cstate = CSTATE_ENCRYPT | CSTATE_DECRYPT;
841 free (buf);
842 return 1;
843
844 exit_in_error:
845 disconnect (handle);
846
847 if (rsa_master != NULL)
848 RSA_free (rsa_master);
849
850 if (rsa_server != NULL)
851 RSA_free (rsa_server);
852
853 if (dh != NULL)
854 DH_free (dh);
855
856 if (X != NULL)
857 BN_free (X);
858
859 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
860 if (bn1 != NULL)
861 BN_free (bn1);
862
863 if (bn2 != NULL)
864 BN_free (bn2);
865 #endif
866
867 free (Na);
868 free (Nb);
869 free (buf);
870 free (msg1);
871 return 0;
872 }
873
mdf_int_send_rekey(mdf_t handle)874 void mdf_int_send_rekey (mdf_t handle)
875 {
876 ssize_t written;
877 int len;
878 uint8_t buf[5 + 11 + sizeof (uint32_t) + MAX_DIGEST_LENGTH + MAX_DIGEST_LENGTH];
879 uint8_t *p = buf;
880 uint8_t *Na = NULL;
881 uint8_t *first_pos;
882 uint32_t tmp_u32;
883
884 /* we don't support rekeyings on non encryption tunnels */
885 if ((handle->cstate & CSTATE_ENCRYPT) != CSTATE_ENCRYPT)
886 return;
887
888 if (handle->no_encryption == 1)
889 len = 3 + sizeof (uint32_t);
890 else
891 len = 3 + sizeof (uint32_t) + handle->digest_length;
892
893 p += add_len (p, len);
894 first_pos = p;
895
896 p += add_header (p, 0, 5);
897
898 if (handle->no_encryption == 1) {
899 memset (p, 0, sizeof (uint32_t));
900 p += sizeof (uint32_t);
901 } else {
902 *((uint32_t *)(p)) = cpu_to_le32 (handle->digest_length);
903 p += sizeof (uint32_t);
904
905 Na = malloc (handle->digest_length);
906
907 if (RAND_bytes (Na, handle->digest_length) != 1) {
908 free (Na);
909 return;
910 }
911
912 memcpy (p, Na, handle->digest_length);
913 p += handle->digest_length;
914 }
915
916 tmp_u32 = cpu_to_le32 ((p - buf) + handle->digest_length);
917
918 HMAC_Init_ex (handle->client_hmac, NULL, 0, NULL, NULL);
919 HMAC_Update (handle->client_hmac, handle->client_iv, sizeof (uint64_t));
920 HMAC_Update (handle->client_hmac, (unsigned char *) &tmp_u32, sizeof tmp_u32);
921 HMAC_Update (handle->client_hmac, buf, p - buf);
922 HMAC_Final (handle->client_hmac, p, NULL);
923 p += handle->digest_length;
924
925 mdf_int_encrypt_aes_ctr (first_pos, p - first_pos, handle->client_enc, handle->client_iv);
926
927 written = send (handle->fd, (void *)buf, p - buf, 0);
928
929 if (written == -1) {
930 free (Na);
931 disconnect (handle);
932 return;
933 }
934
935 handle->bytes_written += written;
936
937 if (handle->no_encryption == 1) {
938 handle->cstate &= ~CSTATE_ENCRYPT;
939 return;
940 }
941
942 mdf_int_set_keys (handle, Na, handle->digest_length, &handle->client_enc, &handle->client_hmac, &handle->client_iv);
943 free (Na);
944 }
945
should_we_rekey(mdf_t handle)946 static void should_we_rekey (mdf_t handle)
947 {
948 if ((handle->cstate & CSTATE_ENCRYPT) != CSTATE_ENCRYPT)
949 return;
950
951 if (le64_to_cpu (*((uint64_t *) handle->client_iv)) < MAX_ENCRYPTED_MESSAGES_PER_KEY)
952 return;
953
954 mdf_int_send_rekey (handle);
955 }
956
mdf_int_send_heartbeat(mdf_t handle)957 int mdf_int_send_heartbeat (mdf_t handle)
958 {
959 ssize_t written;
960 uint8_t buf[12 + MAX_DIGEST_LENGTH];
961 uint8_t *p = buf;
962 uint8_t *first_pos;
963
964 p += add_len (p, 11);
965 first_pos = p;
966
967 p += add_header (p, 0, 2);
968
969 (*(uint64_t *)p) = cpu_to_le64 (time (NULL));
970 p += 8;
971
972 if ((handle->cstate & CSTATE_ENCRYPT) == CSTATE_ENCRYPT) {
973 uint32_t tmp_u32 = cpu_to_le32 ((p - buf) + handle->digest_length);
974
975 HMAC_Init_ex (handle->client_hmac, NULL, 0, NULL, NULL);
976 HMAC_Update (handle->client_hmac, handle->client_iv, sizeof (uint64_t));
977 HMAC_Update (handle->client_hmac, (unsigned char *) &tmp_u32, sizeof tmp_u32);
978 HMAC_Update (handle->client_hmac, buf, p - buf);
979 HMAC_Final (handle->client_hmac, p, NULL);
980 p += handle->digest_length;
981
982 mdf_int_encrypt_aes_ctr (first_pos, p - first_pos, handle->client_enc, handle->client_iv);
983 }
984
985 written = send (handle->fd, (void *)buf, p - buf, 0);
986
987 if (written == -1) {
988 disconnect (handle);
989 handle->error = MDF_ERR_DISCONNECTED;
990 return -1;
991 }
992
993 handle->bytes_written += written;
994 should_we_rekey (handle);
995 return 0;
996 }
997
request_heartbeat(mdf_t handle)998 static int request_heartbeat (mdf_t handle)
999 {
1000 ssize_t written;
1001 uint8_t buf[5 + 11 + MAX_DIGEST_LENGTH];
1002 uint8_t *p = buf;
1003 uint8_t *first_pos;
1004
1005 p += add_len (p, 3);
1006 first_pos = p;
1007
1008 p += add_header (p, 0, 1);
1009
1010 if ((handle->cstate & CSTATE_ENCRYPT) == CSTATE_ENCRYPT) {
1011 uint32_t tmp_u32 = cpu_to_le32 ((p - buf) + handle->digest_length);
1012
1013 HMAC_Init_ex (handle->client_hmac, NULL, 0, NULL, NULL);
1014 HMAC_Update (handle->client_hmac, handle->client_iv, sizeof (uint64_t));
1015 HMAC_Update (handle->client_hmac, (unsigned char *) &tmp_u32, sizeof tmp_u32);
1016 HMAC_Update (handle->client_hmac, buf, p - buf);
1017 HMAC_Final (handle->client_hmac, p, NULL);
1018 p += handle->digest_length;
1019
1020 mdf_int_encrypt_aes_ctr (first_pos, p - first_pos, handle->client_enc, handle->client_iv);
1021 }
1022
1023 written = send (handle->fd, (void *)buf, p - buf, 0);
1024
1025 if (written == -1) {
1026 disconnect (handle);
1027 handle->error = MDF_ERR_DISCONNECTED;
1028 return -1;
1029 }
1030
1031 handle->bytes_written += written;
1032 should_we_rekey (handle);
1033 return 0;
1034 }
1035
1036 #if defined _WIN32 || defined _WIN64
is_connected(SOCKET fd,fd_set * rdevents,fd_set * wrevents,fd_set * exevents)1037 static int is_connected (SOCKET fd, fd_set *rdevents, fd_set *wrevents, fd_set *exevents)
1038 {
1039 WSASetLastError (0);
1040
1041 if (!FD_ISSET (fd, rdevents) && !FD_ISSET (fd, wrevents))
1042 return 0;
1043
1044 if (FD_ISSET (fd, exevents))
1045 return 0;
1046
1047 return 1;
1048 }
1049 #else
is_connected(int fd,fd_set * rdevents,fd_set * wrevents,fd_set * exevents)1050 static int is_connected (int fd, fd_set *rdevents, fd_set *wrevents, fd_set *exevents)
1051 {
1052 int err;
1053 socklen_t len = sizeof err;
1054
1055 (void)exevents;
1056
1057 errno = 0;
1058
1059 if (!FD_ISSET (fd, rdevents) && !FD_ISSET (fd, wrevents))
1060 return 0;
1061
1062 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
1063 return 0;
1064
1065 errno = err;
1066
1067 return err == 0 ? 1 : 0;
1068 }
1069 #endif
1070
try_connect(mdf_t handle,struct addrinfo * addr)1071 static int try_connect (mdf_t handle, struct addrinfo *addr)
1072 {
1073 fd_set rdevents;
1074 fd_set wrevents;
1075 fd_set exevents;
1076 struct timeval tv;
1077 int ret;
1078
1079 #if defined _WIN32 || defined _WIN64
1080 unsigned long val = 1;
1081 #else
1082 int val;
1083 #endif
1084
1085 handle->fd = socket (addr->ai_family, addr->ai_socktype | SOCK_CLOEXEC, addr->ai_protocol);
1086
1087 if (handle->fd == INVALID_SOCKET)
1088 return 0;
1089
1090 /* set non-blocking */
1091 #if defined _WIN32 || defined _WIN64
1092 if (ioctlsocket (handle->fd, FIONBIO, &val) == SOCKET_ERROR) {
1093 closesocket (handle->fd);
1094 handle->fd = INVALID_SOCKET;
1095 return 0;
1096 }
1097 #else
1098 val = fcntl (handle->fd, F_GETFL, 0);
1099
1100 if (val == -1) {
1101 close (handle->fd);
1102 handle->fd = INVALID_SOCKET;
1103 return 0;
1104 }
1105
1106 if (fcntl (handle->fd, F_SETFL, val | O_NONBLOCK) == -1) {
1107 close (handle->fd);
1108 handle->fd = INVALID_SOCKET;
1109 return 0;
1110 }
1111 #endif
1112 ret = connect (handle->fd, addr->ai_addr, addr->ai_addrlen);
1113
1114 #if defined _WIN32 || defined _WIN64
1115 if (ret == SOCKET_ERROR) {
1116 if (WSAGetLastError () != WSAEWOULDBLOCK) {
1117 closesocket (handle->fd);
1118 handle->fd = INVALID_SOCKET;
1119 return 0;
1120 }
1121 #else
1122 if (ret == -1) {
1123 if (errno != EINPROGRESS) {
1124 close (handle->fd);
1125 handle->fd = INVALID_SOCKET;
1126 return 0;
1127 }
1128 #endif
1129 FD_ZERO (&rdevents);
1130 FD_SET (handle->fd, &rdevents);
1131
1132 wrevents = rdevents;
1133 exevents = rdevents;
1134
1135 tv.tv_sec = handle->connect_timeout;
1136 tv.tv_usec = 0;
1137
1138 if (select (handle->fd + 1, &rdevents, &wrevents, &exevents, &tv) < 1) {
1139 #if defined _WIN32 || defined _WIN64
1140 closesocket (handle->fd);
1141 #else
1142 close (handle->fd);
1143 #endif
1144 handle->fd = INVALID_SOCKET;
1145 return 0;
1146 }
1147
1148 if (is_connected (handle->fd, &rdevents, &wrevents, &exevents) == 0) {
1149 #if defined _WIN32 || defined _WIN64
1150 closesocket (handle->fd);
1151 #else
1152 close (handle->fd);
1153 #endif
1154 handle->fd = INVALID_SOCKET;
1155 return 0;
1156 }
1157 }
1158
1159 /* set socket back to blocking */
1160 #if defined _WIN32 || defined _WIN64
1161 val = 0;
1162 ioctlsocket (handle->fd, FIONBIO, &val);
1163 #else
1164 fcntl (handle->fd, F_SETFL, val);
1165 #endif
1166
1167 return 1;
1168 }
1169
1170 static int try_host (mdf_t handle, const char * restrict host, const char * restrict port)
1171 {
1172 struct addrinfo hint;
1173 struct addrinfo *res;
1174 struct addrinfo *r;
1175
1176 memset (&hint, 0, sizeof hint);
1177
1178 #ifdef AI_ADDRCONFIG
1179 hint.ai_flags = AI_ADDRCONFIG;
1180 #endif
1181 #ifdef AI_NUMERICSERV
1182 hint.ai_flags |= AI_NUMERICSERV;
1183 #endif
1184
1185 hint.ai_family = AF_UNSPEC;
1186 hint.ai_socktype = SOCK_STREAM;
1187 hint.ai_protocol = IPPROTO_TCP;
1188
1189 call_status_callback (handle, MDF_STATUS_LOOKUP, host, NULL);
1190
1191 if (getaddrinfo (host, port, &hint, &res) != 0)
1192 return 0;
1193
1194 for (r = res; r != NULL; r = r->ai_next) {
1195 char buf[50];
1196 char *ip = NULL;
1197
1198 if (getnameinfo (r->ai_addr, r->ai_addrlen, buf, sizeof buf, NULL, 0, NI_NUMERICHOST) == 0)
1199 ip = buf;
1200
1201 call_status_callback (handle, MDF_STATUS_CONNECTING, host, ip);
1202
1203 if (try_connect (handle, r) == 1) {
1204 call_status_callback (handle, MDF_STATUS_CONNECTED, host, ip);
1205 freeaddrinfo (res);
1206
1207 free (handle->connected_host);
1208 handle->connected_host = strdup (host);
1209
1210 free (handle->connected_ip);
1211 handle->connected_ip = strdup (ip);
1212 return 1;
1213 }
1214 }
1215
1216 freeaddrinfo (res);
1217
1218 return 0;
1219 }
1220
1221 #ifdef HAVE_SYS_UN_H
1222 static int try_unix (mdf_t handle, const char *path)
1223 {
1224 union { struct sockaddr_un un; struct sockaddr addr; } addr;
1225 int ret;
1226
1227 if (strlen (path) + 1 > sizeof addr.un.sun_path)
1228 return 0;
1229
1230 handle->fd = socket (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
1231
1232 if (handle->fd == INVALID_SOCKET)
1233 return 0;
1234
1235 memset (&addr.un, 0, sizeof addr.un);
1236
1237 addr.un.sun_family = AF_UNIX;
1238 strcpy (addr.un.sun_path, path);
1239
1240 ret = connect (handle->fd, &addr.addr, sizeof addr.un);
1241
1242 if (ret == -1) {
1243 close (handle->fd);
1244 handle->fd = INVALID_SOCKET;
1245 return 0;
1246 }
1247
1248 call_status_callback (handle, MDF_STATUS_CONNECTED, path, path);
1249
1250 free (handle->connected_host);
1251 handle->connected_host = strdup (path);
1252
1253 free (handle->connected_ip);
1254 handle->connected_ip = strdup (path);
1255
1256 handle->cstate = 0; /* No need to encrypt data on AF_UNIX */
1257 return 1;
1258 }
1259 #endif
1260
1261 int mdf_connect (mdf_t handle, const char *servers)
1262 {
1263 char *s, *p, *e, *port;
1264
1265 if (handle == NULL)
1266 return 0;
1267
1268 if (servers == NULL) {
1269 handle->error = MDF_ERR_ARGUMENT;
1270 return 0;
1271 }
1272
1273 /* if we already are connected we must fail */
1274 if (handle->fd != INVALID_SOCKET) {
1275 handle->error = MDF_ERR_CONNECTED;
1276 return 0;
1277 }
1278
1279 handle->cstate = CSTATE_INVALID;
1280
1281 s = strdup (servers);
1282
1283 /* parse the servers string */
1284 for (p = s; *p != '\0'; p = e) {
1285 while (isspace ((unsigned char) *p) != 0 || *p == ',')
1286 ++p;
1287
1288 /* IPv6 */
1289 if (*p == '[') {
1290 ++p;
1291
1292 port = strchr (p, ']');
1293
1294 if (port == NULL) {
1295 free (s);
1296 handle->error = MDF_ERR_ARGUMENT;
1297 return 0;
1298 }
1299
1300 *port++ = '\0';
1301 #ifdef HAVE_SYS_UN_H
1302 } else if (*p == '/') { /* Unix Domain Sockets */
1303 e = strchr (p, ',');
1304
1305 if (e != NULL)
1306 *e++ = '\0';
1307
1308 if (try_unix (handle, p) == 1) {
1309 free (s);
1310 handle->time_lastupdate = time (NULL);
1311 handle->heartbeats_sent = 0;
1312 return 1;
1313 }
1314
1315 if (e == NULL)
1316 break;
1317
1318 continue;
1319 #endif
1320 } else { /* IPv4 or DNS name */
1321 port = strchr (p, ':');
1322
1323 if (port == NULL) {
1324 free (s);
1325 handle->error = MDF_ERR_ARGUMENT;
1326 return 0;
1327 }
1328 }
1329
1330 /* the format must be host:port */
1331 if (*port != ':') {
1332 free (s);
1333 handle->error = MDF_ERR_ARGUMENT;
1334 return 0;
1335 }
1336
1337 *port++ = '\0';
1338
1339 /* scan to the end of the port, yes this code does not perform
1340 * all the checks that it could do, i.e we do not check if the port
1341 * was written like host:1234newhost, but it is futile to try every
1342 * possible error, we should just be happy that we at least do not
1343 * crash ;) */
1344 for (e = port; isdigit ((unsigned char) *e) != 0; e++)
1345 ;
1346
1347 /* do not increase the end pointer if we are at the last byte in the string */
1348 if (*e != '\0')
1349 *e++ = '\0';
1350
1351 /* we found one, try it! */
1352 if (try_host (handle, p, port) != 0) {
1353 setsockopt (handle->fd, SOL_TCP, TCP_NODELAY, (char *) &handle->tcp_nodelay, sizeof handle->tcp_nodelay);
1354
1355 if (send_greeting (handle) == 1) {
1356 free (s);
1357 handle->time_lastupdate = time (NULL);
1358 handle->heartbeats_sent = 0;
1359 call_status_callback (handle, MDF_STATUS_READYTOLOGON, handle->connected_host, handle->connected_ip);
1360 return 1;
1361 }
1362 }
1363 }
1364
1365 free (s);
1366 handle->error = MDF_ERR_CONNECT;
1367 return 0;
1368 }
1369
1370 void mdf_disconnect (mdf_t handle)
1371 {
1372 if (handle == NULL || handle->fd == INVALID_SOCKET)
1373 return;
1374
1375 disconnect (handle);
1376 }
1377
1378 int mdf_get_property (mdf_t handle, MDF_OPTION option, ...)
1379 {
1380 va_list ap;
1381
1382 if (handle == NULL)
1383 return 0;
1384
1385 va_start (ap, option);
1386
1387 switch (option) {
1388 case MDF_OPT_FD : {
1389 #if defined _WIN32 || defined _WIN64
1390 SOCKET *value = va_arg (ap, SOCKET *);
1391 #else
1392 int *value = va_arg (ap, int *);
1393 #endif
1394 if (value == NULL)
1395 return 0;
1396
1397 *value = handle->fd;
1398 return 1;
1399 }
1400
1401 case MDF_OPT_ERROR : {
1402 MDF_ERROR *value = va_arg (ap, MDF_ERROR *);
1403
1404 if (value == NULL)
1405 return 0;
1406
1407 *value = handle->error;
1408 return 1;
1409 }
1410
1411 case MDF_OPT_RCV_BYTES : {
1412 uint64_t *value = va_arg (ap, uint64_t *);
1413
1414 if (value == NULL)
1415 return 0;
1416
1417 *value = handle->bytes_read;
1418 return 1;
1419 }
1420
1421 case MDF_OPT_SENT_BYTES : {
1422 uint64_t *value = va_arg (ap, uint64_t *);
1423
1424 if (value == NULL)
1425 return 0;
1426
1427 *value = handle->bytes_written;
1428 return 1;
1429 }
1430
1431 case MDF_OPT_DATA_CALLBACK_FUNCTION : {
1432 mdf_data_callback *value = va_arg (ap, mdf_data_callback *);
1433
1434 if (value == NULL)
1435 return 0;
1436
1437 *value = handle->callbacks.func_data;
1438 return 1;
1439 }
1440
1441 case MDF_OPT_DATA_CALLBACK_USERDATA : {
1442 char **value = va_arg (ap, char **);
1443
1444 if (value == NULL)
1445 return 0;
1446
1447 *value = (char *) handle->callbacks.udata_data;
1448 return 1;
1449 }
1450
1451 case MDF_OPT_STATUS_CALLBACK_FUNCTION : {
1452 mdf_status_callback *value = va_arg (ap, mdf_status_callback *);
1453
1454 if (value == NULL)
1455 return 0;
1456
1457 *value = handle->callbacks.func_status;
1458 return 1;
1459 }
1460
1461 case MDF_OPT_STATUS_CALLBACK_USERDATA : {
1462 char **value = va_arg (ap, char **);
1463
1464 if (value == NULL)
1465 return 0;
1466
1467 *value = (char *) handle->callbacks.udata_status;
1468 return 1;
1469 }
1470
1471 case MDF_OPT_CONNECT_TIMEOUT : {
1472 int *value = va_arg (ap, int *);
1473
1474 if (value == NULL)
1475 return 0;
1476
1477 *value = handle->connect_timeout;
1478 return 1;
1479 }
1480
1481 case MDF_OPT_HEARTBEAT_INTERVAL : {
1482 int *value = va_arg (ap, int *);
1483
1484 if (value == NULL)
1485 return 0;
1486
1487 *value = handle->heartbeat_interval;
1488 return 1;
1489 }
1490
1491 case MDF_OPT_HEARTBEAT_MAX_MISSED : {
1492 int *value = va_arg (ap, int *);
1493
1494 if (value == NULL)
1495 return 0;
1496
1497 *value = handle->max_missed_heartbeats;
1498 return 1;
1499 }
1500
1501 case MDF_OPT_TCP_NODELAY : {
1502 int *value = va_arg (ap, int *);
1503
1504 if (value == NULL)
1505 return 0;
1506
1507 *value = handle->tcp_nodelay;
1508 return 1;
1509 }
1510
1511 case MDF_OPT_NO_ENCRYPTION : {
1512 int *value = va_arg (ap, int *);
1513
1514 if (value == NULL)
1515 return 0;
1516
1517 *value = handle->no_encryption;
1518 return 1;
1519 }
1520
1521 case MDF_OPT_TIME_DIFFERENCE : {
1522 int *value = va_arg (ap, int *);
1523
1524 if (value == NULL)
1525 return 0;
1526
1527 *value = handle->timediff;
1528 return 1;
1529 }
1530 }
1531
1532 va_end (ap);
1533
1534 return 0;
1535 }
1536
1537 int mdf_set_property (mdf_t handle, MDF_OPTION option, void *value)
1538 {
1539 if (handle == NULL)
1540 return 0;
1541
1542 switch (option) {
1543 case MDF_OPT_DATA_CALLBACK_FUNCTION :
1544 handle->callbacks.func_data = (mdf_data_callback) value;
1545 return 1;
1546
1547 case MDF_OPT_DATA_CALLBACK_USERDATA :
1548 handle->callbacks.udata_data = value;
1549 return 1;
1550
1551 case MDF_OPT_STATUS_CALLBACK_FUNCTION :
1552 handle->callbacks.func_status = (mdf_status_callback) value;
1553 return 1;
1554
1555 case MDF_OPT_STATUS_CALLBACK_USERDATA :
1556 handle->callbacks.udata_status = value;
1557 return 1;
1558
1559 case MDF_OPT_CONNECT_TIMEOUT : {
1560 int *val = (int *) value;
1561
1562 if (*val < 1 || *val > 60)
1563 return 0;
1564
1565 handle->connect_timeout = *val;
1566 return 1;
1567 }
1568
1569 case MDF_OPT_RCV_BYTES :
1570 handle->bytes_read = *((uint64_t *) value);
1571 return 1;
1572
1573 case MDF_OPT_SENT_BYTES :
1574 handle->bytes_written = *((uint64_t *) value);
1575 return 1;
1576
1577 case MDF_OPT_ERROR :
1578 handle->error = *((MDF_ERROR *) value);
1579 return 1;
1580
1581 case MDF_OPT_FD :
1582 return 0;
1583
1584 case MDF_OPT_HEARTBEAT_INTERVAL : {
1585 int *val = (int *) value;
1586
1587 if (*val < 1 || *val > 86400)
1588 return 0;
1589
1590 handle->heartbeat_interval = *val;
1591 return 1;
1592 }
1593
1594 case MDF_OPT_HEARTBEAT_MAX_MISSED : {
1595 int *val = (int *) value;
1596
1597 if (*val < 1 || *val > 100)
1598 return 0;
1599
1600 handle->max_missed_heartbeats = *val;
1601 return 1;
1602 }
1603
1604 case MDF_OPT_TCP_NODELAY : {
1605 int *val = (int *) value;
1606
1607 if (*val < 0 || *val > 1)
1608 return 0;
1609
1610 handle->tcp_nodelay = *val;
1611
1612 if (handle->fd != INVALID_SOCKET)
1613 setsockopt (handle->fd, SOL_TCP, TCP_NODELAY, (char *) &handle->tcp_nodelay, sizeof handle->tcp_nodelay);
1614
1615 return 1;
1616 }
1617
1618 case MDF_OPT_NO_ENCRYPTION : {
1619 int *val = (int *) value;
1620
1621 if (*val < 0 || *val > 1)
1622 return 0;
1623
1624 handle->no_encryption = *val;
1625 return 1;
1626 }
1627
1628 case MDF_OPT_TIME_DIFFERENCE :
1629 return 0;
1630 }
1631
1632 return 0;
1633 }
1634
1635 int mdf_consume (mdf_t handle, const int timeout)
1636 {
1637 fd_set rdset;
1638 struct timeval tv;
1639 int ret;
1640 int flags = 0;
1641 int pos;
1642 size_t tlen;
1643
1644 if (handle == NULL)
1645 return -1;
1646
1647 if (handle->fd == INVALID_SOCKET) {
1648 handle->error = MDF_ERR_NOT_CONNECTED;
1649 return -1;
1650 }
1651
1652 if ((handle->cstate & CSTATE_INVALID) == CSTATE_INVALID)
1653 return 0;
1654
1655 #ifdef MSG_DONTWAIT
1656 flags = MSG_DONTWAIT;
1657
1658 /* if we are on a real POSIX system and timeout is zero
1659 * we can skip the whole select() call saving us some cs */
1660 if (timeout != 0) {
1661 #endif
1662
1663 FD_ZERO (&rdset);
1664 FD_SET (handle->fd, &rdset);
1665
1666 if (timeout < 0)
1667 tv.tv_sec = 1;
1668 else if (timeout > 60 * 60)
1669 tv.tv_sec = 60 * 60;
1670 else
1671 tv.tv_sec = timeout;
1672
1673 tv.tv_usec = 0;
1674
1675 ret = select (handle->fd + 1, &rdset, NULL, NULL, &tv);
1676
1677 if (ret == 0) {
1678 /* is it time to send a heartbeat */
1679 time_t now = time (NULL);
1680
1681 if (difftime (now, handle->time_lastupdate) >= handle->heartbeat_interval) {
1682 if (handle->heartbeats_sent++ == handle->max_missed_heartbeats) {
1683 disconnect (handle);
1684 handle->error = MDF_ERR_CONNECTION_IDLE;
1685 return -1;
1686 }
1687
1688 handle->time_lastupdate = now;
1689 return request_heartbeat (handle);
1690 }
1691
1692 return 0;
1693 }
1694
1695 if (ret < 0) {
1696 #ifdef HAVE_ERRNO_H
1697 if (errno == EINTR)
1698 return 0;
1699 #endif
1700 disconnect (handle);
1701 handle->error = MDF_ERR_DISCONNECTED;
1702 return -1;
1703 }
1704 #ifdef MSG_DONTWAIT
1705 }
1706 #endif
1707
1708 #ifdef MSG_DONTWAIT
1709 try_read_again:
1710 #endif
1711 ret = recv (handle->fd, (char *) (handle->data + handle->data_used), handle->data_size - handle->data_used, flags);
1712
1713 if (ret == 0) {
1714 disconnect (handle);
1715 handle->error = MDF_ERR_DISCONNECTED;
1716 return -1;
1717 }
1718
1719 if (ret < 0) {
1720 #ifdef MSG_DONTWAIT
1721 if (errno == EAGAIN) {
1722 /* is it time to send a heartbeat */
1723 time_t now = time (NULL);
1724
1725 if (difftime (now, handle->time_lastupdate) >= handle->heartbeat_interval) {
1726 if (handle->heartbeats_sent++ == handle->max_missed_heartbeats) {
1727 disconnect (handle);
1728 handle->error = MDF_ERR_CONNECTION_IDLE;
1729 return -1;
1730 }
1731
1732 handle->time_lastupdate = now;
1733 return request_heartbeat (handle);
1734 }
1735
1736 return 0;
1737 }
1738
1739 if (errno == EINTR)
1740 goto try_read_again;
1741 #endif
1742 disconnect (handle);
1743 handle->error = MDF_ERR_DISCONNECTED;
1744 return -1;
1745 }
1746
1747 handle->time_lastupdate = time (NULL);
1748 handle->bytes_read += ret;
1749 handle->data_used += ret;
1750 handle->heartbeats_sent = 0;
1751
1752 /* in case we get called before the client has decoded all the data in the buffer */
1753 if (handle->fstatus != 2) {
1754 if (handle->data_used - ret == handle->message_end)
1755 handle->oldval = handle->data[handle->message_end];
1756
1757 if (handle->callbacks.func_data == NULL)
1758 return 1;
1759
1760 do {
1761 handle->callbacks.func_data (handle->callbacks.udata_data, handle);
1762 } while (handle->fstatus != 2);
1763
1764 return 0;
1765 }
1766
1767 pos = 0;
1768 tlen = 0;
1769
1770 do {
1771 tlen *= 128;
1772 tlen += (handle->data[handle->data_pos + pos] & 127) + 1;
1773 } while ((handle->data[handle->data_pos + pos++] & 128) == 0 && handle->data_pos + pos < handle->data_used);
1774
1775 if (pos > 5) {
1776 disconnect (handle);
1777 handle->error = MDF_ERR_MSG_OOB;
1778 return -1;
1779 }
1780
1781 /* we have not yet received a full header */
1782 if (pos == 0 || (handle->data[handle->data_pos + pos - 1] & 128) == 0) {
1783 if (handle->data_pos != 0) {
1784 handle->data_used -= handle->data_pos;
1785 memmove (handle->data, handle->data + handle->data_pos, handle->data_used);
1786 handle->data_pos = 0;
1787 }
1788
1789 return 0;
1790 }
1791
1792 handle->message_len = tlen + pos;
1793 handle->message_end = handle->data_pos + handle->message_len;
1794 handle->pos = pos;
1795 handle->fpos = handle->data_pos + pos;
1796
1797 if ((handle->cstate & CSTATE_DECRYPT) == CSTATE_DECRYPT)
1798 handle->message_len += handle->digest_length;
1799
1800 if (handle->data_pos + handle->message_len + 12 > handle->data_size) {
1801 void *tmp = realloc (handle->data, handle->data_pos + handle->message_len + 12);
1802
1803 if (tmp == NULL) {
1804 disconnect (handle);
1805 handle->error = MDF_ERR_NO_MEM;
1806 return -1;
1807 }
1808
1809 handle->data = (uint8_t *) tmp;
1810 handle->data_size = handle->data_pos + handle->message_len + 12;
1811 }
1812
1813 if (handle->message_len + handle->data_pos > handle->data_used) {
1814 if (handle->data_pos != 0) {
1815 handle->data_used -= handle->data_pos;
1816 memmove (handle->data, handle->data + handle->data_pos, handle->data_used);
1817 handle->data_pos = 0;
1818 }
1819
1820 return 0;
1821 }
1822
1823 handle->fstatus = 1;
1824
1825 if (handle->callbacks.func_data == NULL)
1826 return 1;
1827
1828 do {
1829 handle->callbacks.func_data (handle->callbacks.udata_data, handle);
1830 } while (handle->fstatus != 2);
1831
1832 return 0;
1833 }
1834
1835 int mdf_message_send (mdf_t handle, mdf_message_t message)
1836 {
1837 unsigned int i;
1838 struct field *field;
1839
1840 if (handle == NULL || message == NULL)
1841 return 0;
1842
1843 if (handle->fd == INVALID_SOCKET)
1844 return 0;
1845
1846 if ((handle->cstate & CSTATE_INVALID) == CSTATE_INVALID)
1847 return 0;
1848
1849 if (message->current_message == -1)
1850 return 0;
1851
1852 #ifdef TCP_CORK
1853 i = 1;
1854 setsockopt (handle->fd, IPPROTO_TCP, TCP_CORK, &i, sizeof (i));
1855 #endif
1856
1857 field = message->fields;
1858
1859 for (i = 0; i < (unsigned int)(message->current_message + 1); i++) {
1860 uint8_t *p, *pmap_pos;
1861 unsigned int j;
1862 unsigned int tags_used = 0;
1863 unsigned int maxpos = 0;
1864 int hlen, offset;
1865 size_t len = 0;
1866 struct msg_template *template;
1867 ssize_t written;
1868
1869 if (message->messages[i].fields == 0 && message->messages[i].mref != MDF_M_INSTRUMENTRESET && message->messages[i].mref != MDF_M_INSTRUMENTDELETE && message->messages[i].mref != MDF_M_ORDERBOOKFLUSH && message->messages[i].mref != MDF_M_LOGOFF)
1870 continue;
1871
1872 if (message->messages[i].mref > 0 && message->messages[i].mref < handle->templates_num) {
1873 template = &(handle->templates[message->messages[i].mref]);
1874
1875 if (template->tags_num > handle->sendfields_num) {
1876 free (handle->sendfields);
1877 handle->sendfields = malloc (sizeof *handle->sendfields * template->tags_num);
1878 handle->sendfields_num = template->tags_num;
1879
1880 if (handle->sendfields == NULL) {
1881 #ifdef TCP_CORK
1882 i = 0;
1883 setsockopt (handle->fd, IPPROTO_TCP, TCP_CORK, &i, sizeof (i));
1884 #endif
1885 handle->sendfields_num = 0;
1886 handle->error = MDF_ERR_NO_MEM;
1887 return 0;
1888 }
1889 }
1890
1891 memset (handle->sendfields, 0, sizeof *handle->sendfields * template->tags_num);
1892 } else {
1893 template = NULL;
1894 }
1895
1896 /* create one list of the tags in positional order and one list of the
1897 * tags that we must send as "tagged" */
1898 for (j = 0; j < (unsigned int)(message->messages[i].fields); j++) {
1899 /* perform binary search for the field position */
1900 int high = template == NULL ? -1 : template->tags_num - 1;
1901 int pos = -1;
1902 int low = 0;
1903
1904 while (high >= low) {
1905 const int mid = (low + high) / 2;
1906
1907 if (template->fields[mid].tag == field->tag) {
1908 pos = template->fields[mid].pos;
1909 break;
1910 }
1911
1912 if (template->fields[mid].tag > field->tag)
1913 high = mid - 1;
1914 else
1915 low = mid + 1;
1916 }
1917
1918 if (pos != -1) {
1919 if (handle->sendfields[pos] != NULL)
1920 len -= handle->sendfields[pos]->len;
1921
1922 handle->sendfields[pos] = field;
1923
1924 if (pos > (int)maxpos)
1925 maxpos = pos;
1926 } else {
1927 if (tags_used + 1 > handle->sendtags_num) {
1928 struct field **tmp = handle->sendtags;
1929 handle->sendtags = realloc (handle->sendtags, sizeof *handle->sendtags * (tags_used + 1));
1930 handle->sendtags_num = tags_used + 1;
1931
1932 if (handle->sendtags == NULL) {
1933 #ifdef TCP_CORK
1934 i = 0;
1935 setsockopt (handle->fd, IPPROTO_TCP, TCP_CORK, &i, sizeof (i));
1936 #endif
1937 free (tmp);
1938 handle->sendtags_num = 0;
1939 handle->error = MDF_ERR_NO_MEM;
1940 return 0;
1941 }
1942 }
1943
1944 handle->sendtags[tags_used++] = field;
1945
1946 if (field->tag <= 255)
1947 len += 2;
1948 else if (field->tag <= 65535)
1949 len += 3;
1950 else
1951 len += 5;
1952 }
1953
1954 len += field->len;
1955 field++;
1956 }
1957
1958 /* the number of pmap:s that we will use */
1959 len += (maxpos / 8) + 1;
1960
1961 if (len + 5 + 11 + handle->digest_length > (size_t) handle->sendbuf_size) {
1962 free (handle->sendbuf);
1963 handle->sendbuf = malloc (len + 5 + 11 + handle->digest_length);
1964 handle->sendbuf_size = len + 5 + 11 + handle->digest_length;
1965
1966 if (handle->sendbuf == NULL) {
1967 #ifdef TCP_CORK
1968 i = 0;
1969 setsockopt (handle->fd, IPPROTO_TCP, TCP_CORK, &i, sizeof (i));
1970 #endif
1971 handle->sendbuf_size = 0;
1972 handle->error = MDF_ERR_NO_MEM;
1973 return 0;
1974 }
1975 }
1976
1977 p = handle->sendbuf + 5;
1978 hlen = add_header (p, (uint16_t) (message->messages[i].mref + 1), message->messages[i].insref);
1979 len += hlen;
1980 p += hlen;
1981
1982 hlen = add_len (handle->sendbuf, len);
1983 offset = 5 - hlen;
1984
1985 if (offset != 0)
1986 memmove (handle->sendbuf + offset, handle->sendbuf, hlen);
1987
1988 if (template != NULL) {
1989 int pmap = 0;
1990
1991 for (j = 0; j < maxpos + 1; j++) {
1992 if (pmap == 0) {
1993 pmap = 128;
1994 pmap_pos = p;
1995 *p++ = 0;
1996 }
1997
1998 if (handle->sendfields[j] != NULL) {
1999 *pmap_pos |= pmap;
2000
2001 if (tags_used != 0) {
2002 unsigned int k;
2003
2004 for (k = 0; k < tags_used; k++) {
2005 if (handle->sendtags[k]->tag <= 255) {
2006 *p++ = 251;
2007 *p++ = (uint8_t) handle->sendtags[k]->tag;
2008 } else if (handle->sendtags[k]->tag <= 65535) {
2009 *p++ = 252;
2010 *((uint16_t *) p) = cpu_to_le16 ((uint16_t) handle->sendtags[k]->tag);
2011 p += 2;
2012 } else {
2013 *p++ = 253;
2014 *((uint32_t *) p) = cpu_to_le32 ((uint32_t) handle->sendtags[k]->tag);
2015 p += 4;
2016 }
2017
2018 memcpy (p, message->data + handle->sendtags[k]->offset, handle->sendtags[k]->len);
2019 p += handle->sendtags[k]->len;
2020 }
2021
2022 tags_used = 0;
2023 }
2024
2025 memcpy (p, message->data + handle->sendfields[j]->offset, handle->sendfields[j]->len);
2026 p += handle->sendfields[j]->len;
2027 }
2028
2029 pmap /= 2;
2030 }
2031 } else if (tags_used == 0) {
2032 *p++ = 0;
2033 }
2034
2035 /* apparently we had only tagged data today... */
2036 if (tags_used != 0) {
2037 if (template == NULL)
2038 *p++ = 128;
2039 else
2040 *pmap_pos = 128;
2041
2042 for (j = 0; j < tags_used; j++) {
2043 if (handle->sendtags[j]->tag <= 255) {
2044 *p++ = 251;
2045 *p++ = (uint8_t) handle->sendtags[j]->tag;
2046 } else if (handle->sendtags[j]->tag <= 65535) {
2047 *p++ = 252;
2048 *((uint16_t *) p) = cpu_to_le16 ((uint16_t) handle->sendtags[j]->tag);
2049 p += 2;
2050 } else {
2051 *p++ = 253;
2052 *((uint32_t *) p) = cpu_to_le32 ((uint32_t) handle->sendtags[j]->tag);
2053 p += 4;
2054 }
2055
2056 memcpy (p, message->data + handle->sendtags[j]->offset, handle->sendtags[j]->len);
2057 p += handle->sendtags[j]->len;
2058 }
2059 }
2060
2061 if ((handle->cstate & CSTATE_ENCRYPT) == CSTATE_ENCRYPT) {
2062 unsigned int length;
2063 uint32_t tmp_u32 = cpu_to_le32 (hlen + len + handle->digest_length);
2064
2065 HMAC_Init_ex (handle->client_hmac, NULL, 0, NULL, NULL);
2066 HMAC_Update (handle->client_hmac, handle->client_iv, sizeof (uint64_t));
2067 HMAC_Update (handle->client_hmac, (unsigned char *) &tmp_u32, sizeof tmp_u32);
2068 HMAC_Update (handle->client_hmac, handle->sendbuf + offset, hlen + len);
2069 HMAC_Final (handle->client_hmac, p, &length);
2070
2071 len += length;
2072
2073 mdf_int_encrypt_aes_ctr (handle->sendbuf + 5, len, handle->client_enc, handle->client_iv);
2074 }
2075
2076 len += hlen;
2077
2078 send_again:
2079 written = send (handle->fd, (void *)(handle->sendbuf + offset), len, 0);
2080
2081 if ((size_t)written == len) {
2082 handle->bytes_written += written;
2083 continue;
2084 }
2085
2086 #ifdef HAVE_ERRNO_H
2087 if (written == -1 && errno == EINTR)
2088 goto send_again;
2089 #endif
2090 handle->error = MDF_ERR_DISCONNECTED;
2091 disconnect (handle);
2092 return 0;
2093 }
2094
2095 #ifdef TCP_CORK
2096 i = 0;
2097 setsockopt (handle->fd, IPPROTO_TCP, TCP_CORK, &i, sizeof (i));
2098 #endif
2099
2100 should_we_rekey (handle);
2101 return 1;
2102 }
2103
2104