1/*
2 This file is part of Mtproto-proxy Library.
3
4 Mtproto-proxy Library 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 2 of the License, or
7 (at your option) any later version.
8
9 Mtproto-proxy Library 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
16
17 Copyright 2010-2013 Vkontakte Ltd
18 2010-2013 Nikolai Durov
19 2010-2013 Andrey Lopatin
20 2013 Vitaliy Valtman
21
22 Copyright 2014-2016 Telegram Messenger Inc
23 2015-2016 Vitaly Valtman
24*/
25
26#define _FILE_OFFSET_BITS 64
27
28#include <assert.h>
29#include <string.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <time.h>
33#include <unistd.h>
34
35#include "crc32.h"
36#include "crc32c.h"
37#include "net/net-events.h"
38#include "kprintf.h"
39#include "precise-time.h"
40#include "net/net-connections.h"
41#include "net/net-tcp-rpc-server.h"
42#include "net/net-tcp-connections.h"
43#include "net/net-thread.h"
44
45#include "rpc-const.h"
46
47#include "net/net-crypto-aes.h"
48#include "net/net-crypto-dh.h"
49#include "net/net-config.h"
50
51#include "vv/vv-io.h"
52/*
53 *
54 * BASIC RPC SERVER INTERFACE
55 *
56 */
57
58int tcp_rpcs_wakeup (connection_job_t c);
59int tcp_rpcs_parse_execute (connection_job_t c);
60int tcp_rpcs_alarm (connection_job_t c);
61int tcp_rpcs_do_wakeup (connection_job_t c);
62int tcp_rpcs_init_accepted (connection_job_t c);
63int tcp_rpcs_close_connection (connection_job_t c, int who);
64int tcp_rpcs_init_accepted_nohs (connection_job_t c);
65int tcp_rpcs_default_check_perm (connection_job_t c);
66int tcp_rpcs_init_crypto (connection_job_t c, struct tcp_rpc_nonce_packet *P);
67
68conn_type_t ct_tcp_rpc_server = {
69 .magic = CONN_FUNC_MAGIC,
70 .flags = C_RAWMSG,
71 .title = "rpc_tcp_server",
72 .init_accepted = tcp_rpcs_init_accepted,
73 .parse_execute = tcp_rpcs_parse_execute,
74 .close = tcp_rpcs_close_connection,
75 .flush = tcp_rpc_flush,
76 .write_packet = tcp_rpc_write_packet,
77 .connected = server_failed,
78 .wakeup = tcp_rpcs_wakeup,
79 .alarm = tcp_rpcs_alarm,
80 .crypto_init = aes_crypto_init,
81 .crypto_free = aes_crypto_free,
82 .crypto_encrypt_output = cpu_tcp_aes_crypto_encrypt_output,
83 .crypto_decrypt_input = cpu_tcp_aes_crypto_decrypt_input,
84 .crypto_needed_output_bytes = cpu_tcp_aes_crypto_needed_output_bytes,
85};
86
87int tcp_rpcs_default_execute (connection_job_t c, int op, struct raw_message *msg);
88
89struct tcp_rpc_server_functions default_tcp_rpc_server = {
90 .execute = tcp_rpcs_default_execute,
91 .check_ready = server_check_ready,
92 .flush_packet = tcp_rpc_flush_packet,
93 .rpc_wakeup = tcp_rpcs_do_wakeup,
94 .rpc_alarm = tcp_rpcs_do_wakeup,
95 .rpc_check_perm = tcp_rpcs_default_check_perm,
96 .rpc_init_crypto = tcp_rpcs_init_crypto,
97 .rpc_ready = server_noop,
98};
99
100int tcp_rpcs_default_execute (connection_job_t C, int op, struct raw_message *raw) {
101 struct connection_info *c = CONN_INFO (C);
102
103 vkprintf (3, "%s: fd=%d, op=%d, len=%d\n", __func__, c->fd, op, raw->total_bytes);
104 if (op == RPC_PING && raw->total_bytes == 12) {
105 c->last_response_time = precise_now;
106 int P[3];
107 assert (rwm_fetch_data (raw, P, 12) == 12);
108 P[0] = RPC_PONG;
109 vkprintf (3, "received ping from " IP_PRINT_STR ":%d (val = %lld)\n", IP_TO_PRINT (c->remote_ip), (int)c->remote_port, *(long long *)(P + 1));
110 tcp_rpc_conn_send_data (JOB_REF_CREATE_PASS (C), 12, P);
111 return 0;
112 }
113 return 0;
114}
115
116static int tcp_rpcs_process_nonce_packet (connection_job_t C, struct raw_message *msg) {
117 struct tcp_rpc_data *D = TCP_RPC_DATA(C);
118 union {
119 struct tcp_rpc_nonce_packet s;
120 struct tcp_rpc_nonce_ext_packet x;
121 struct tcp_rpc_nonce_dh_packet dh;
122 } P;
123 struct tcp_rpc_nonce_dh_packet *dh = 0;
124 int res;
125
126 int packet_num = D->in_packet_num;
127 int packet_type;
128 assert (rwm_fetch_lookup (msg, &packet_type, 4) == 4);
129 int packet_len = msg->total_bytes;
130
131 if (packet_num != -2 || packet_type != RPC_NONCE) {
132 return -2;
133 }
134 if (packet_len < sizeof (struct tcp_rpc_nonce_packet) || packet_len > sizeof (struct tcp_rpc_nonce_dh_packet)) {
135 return -3;
136 }
137
138 assert (rwm_fetch_data (msg, &P, packet_len) == packet_len);
139
140 switch (P.s.crypto_schema) {
141 case RPC_CRYPTO_NONE:
142 if (packet_len != sizeof (struct tcp_rpc_nonce_packet)) {
143 return -3;
144 }
145 break;
146 case RPC_CRYPTO_AES:
147 if (packet_len != sizeof (struct tcp_rpc_nonce_packet)) {
148 return -3;
149 }
150 break;
151 case RPC_CRYPTO_AES_EXT:
152 if (packet_len < sizeof (struct tcp_rpc_nonce_ext_packet) - 4 * RPC_MAX_EXTRA_KEYS) {
153 return -3;
154 }
155 if (P.x.extra_keys_count < 0 || P.x.extra_keys_count > RPC_MAX_EXTRA_KEYS || packet_len != sizeof (struct tcp_rpc_nonce_ext_packet) + 4 * (P.x.extra_keys_count - RPC_MAX_EXTRA_KEYS)) {
156 return -3;
157 }
158 break;
159 case RPC_CRYPTO_AES_DH:
160 if (packet_len < sizeof (struct tcp_rpc_nonce_dh_packet) - 4 * RPC_MAX_EXTRA_KEYS) {
161 return -3;
162 }
163 if (P.x.extra_keys_count < 0 || P.x.extra_keys_count > RPC_MAX_EXTRA_KEYS || packet_len != sizeof (struct tcp_rpc_nonce_dh_packet) + 4 * (P.x.extra_keys_count - RPC_MAX_EXTRA_KEYS)) {
164 return -3;
165 }
166 break;
167 default:
168 return -3;
169 }
170
171 switch (P.s.crypto_schema) {
172 case RPC_CRYPTO_NONE:
173 if (P.s.key_select) {
174 return -3;
175 }
176 if (D->crypto_flags & RPCF_ALLOW_UNENC) {
177 D->crypto_flags = RPCF_ALLOW_UNENC;
178 } else {
179 return -5;
180 }
181 break;
182 case RPC_CRYPTO_AES_DH: {
183 dh = (struct tcp_rpc_nonce_dh_packet *)((char *) &P + 4*(P.x.extra_keys_count - RPC_MAX_EXTRA_KEYS));
184 if (!dh_params_select) {
185 init_dh_params ();
186 }
187 if (!dh->dh_params_select || dh->dh_params_select != dh_params_select) {
188 dh = 0;
189 }
190 }
191 case RPC_CRYPTO_AES_EXT:
192 P.s.key_select = select_best_key_signature (P.s.key_select, P.x.extra_keys_count, P.x.extra_key_select);
193 case RPC_CRYPTO_AES:
194 if (!P.s.key_select || !select_best_key_signature (P.s.key_select, 0, 0)) {
195 if (D->crypto_flags & RPCF_ALLOW_UNENC) {
196 D->crypto_flags = RPCF_ALLOW_UNENC;
197 break;
198 }
199 return -3;
200 }
201 if (!(D->crypto_flags & RPCF_ALLOW_ENC)) {
202 if (D->crypto_flags & RPCF_ALLOW_UNENC) {
203 D->crypto_flags = RPCF_ALLOW_UNENC;
204 break;
205 }
206 return -5;
207 }
208 D->nonce_time = (now ? now : time (0));
209 if (abs (P.s.crypto_ts - D->nonce_time) > 30) {
210 return -6; //less'om
211 }
212 D->crypto_flags &= ~RPCF_ALLOW_UNENC;
213 break;
214 default:
215 if (D->crypto_flags & RPCF_ALLOW_UNENC) {
216 D->crypto_flags = RPCF_ALLOW_UNENC;
217 break;
218 }
219 return -4;
220 }
221
222 if ((D->crypto_flags & (RPCF_REQ_DH | RPCF_ALLOW_ENC)) == (RPCF_REQ_DH | RPCF_ALLOW_ENC) && !dh) {
223 if (D->crypto_flags & RPCF_ALLOW_SKIP_DH) {
224 D->crypto_flags &= ~(RPCF_REQ_DH | RPCF_ALLOW_SKIP_DH);
225 } else {
226 return -7;
227 }
228 }
229
230 res = TCP_RPCS_FUNC(C)->rpc_init_crypto (C, &P.s);
231 if (res < 0) {
232 return -6;
233 }
234 return 0;
235}
236
237static int tcp_rpcs_send_handshake_packet (connection_job_t c) {
238 struct tcp_rpc_data *D = TCP_RPC_DATA(c);
239 struct tcp_rpc_handshake_packet P;
240 if (!PID.ip) {
241 PID.ip = get_my_ipv4 ();
242 }
243 memset (&P, 0, sizeof (P));
244 P.type = RPC_HANDSHAKE;
245 P.flags = D->crypto_flags & RPCF_USE_CRC32C;
246 memcpy (&P.sender_pid, &PID, sizeof (struct process_id));
247 memcpy (&P.peer_pid, &D->remote_pid, sizeof (struct process_id));
248
249 tcp_rpc_conn_send_data_im (JOB_REF_CREATE_PASS (c), sizeof (P), &P);
250 return 0;
251}
252
253static int tcp_rpcs_send_handshake_error_packet (connection_job_t c, int error_code) {
254 struct tcp_rpc_handshake_error_packet P;
255 assert (PID.pid);
256 memset (&P, 0, sizeof (P));
257 P.type = RPC_HANDSHAKE_ERROR;
258 P.error_code = error_code;
259 memcpy (&P.sender_pid, &PID, sizeof (PID));
260
261 tcp_rpc_conn_send_data (JOB_REF_CREATE_PASS (c), sizeof (P), &P);
262 return 0;
263}
264
265static int tcp_rpcs_process_handshake_packet (connection_job_t C, struct raw_message *msg) {
266 struct connection_info *c = CONN_INFO (C);
267
268 struct tcp_rpc_data *D = TCP_RPC_DATA(C);
269 struct tcp_rpc_handshake_packet P;
270 if (!PID.ip) {
271 init_server_PID (c->our_ip, c->our_port);
272 if (!PID.ip) {
273 PID.ip = get_my_ipv4 ();
274 }
275 }
276
277 int packet_num = D->in_packet_num;
278 int packet_type;
279 assert (rwm_fetch_lookup (msg, &packet_type, 4) == 4);
280 int packet_len = msg->total_bytes;
281
282 if (packet_num != -1 || packet_type != RPC_HANDSHAKE) {
283 return -2;
284 }
285 if (packet_len != sizeof (struct tcp_rpc_handshake_packet)) {
286 tcp_rpcs_send_handshake_error_packet (C, -3);
287 return -3;
288 }
289 assert (rwm_fetch_data (msg, &P, packet_len) == packet_len);
290 memcpy (&D->remote_pid, &P.sender_pid, sizeof (struct process_id));
291 if (!matches_pid (&PID, &P.peer_pid) && !(TCP_RPCS_FUNC(C)->mode_flags & TCP_RPC_IGNORE_PID)) {
292 vkprintf (1, "PID mismatch during handshake: local %08x:%d:%d:%d, remote %08x:%d:%d:%d\n",
293 PID.ip, PID.port, PID.pid, PID.utime, P.peer_pid.ip, P.peer_pid.port, P.peer_pid.pid, P.peer_pid.utime);
294 tcp_rpcs_send_handshake_error_packet (C, -4);
295 return -4;
296 }
297 if (P.flags & 0xff) {
298 tcp_rpcs_send_handshake_error_packet (C, -7);
299 return -7;
300 }
301 if (P.flags & tcp_get_default_rpc_flags () & RPCF_USE_CRC32C) {
302 D->crypto_flags |= RPCF_USE_CRC32C;
303 }
304 return 0;
305}
306
307int tcp_rpcs_parse_execute (connection_job_t C) {
308 struct connection_info *c = CONN_INFO (C);
309
310 vkprintf (4, "%s. in_total_bytes = %d\n", __func__, c->in.total_bytes);
311 struct tcp_rpc_data *D = TCP_RPC_DATA(C);
312 int len;
313
314 while (1) {
315 if (c->flags & C_ERROR) {
316 return NEED_MORE_BYTES;
317 }
318 if (c->flags & C_STOPPARSE) {
319 return NEED_MORE_BYTES;
320 }
321 len = c->in.total_bytes;
322 if (len <= 0) {
323 return NEED_MORE_BYTES;
324 }
325
326 if (len < 4) {
327 return 4 - len;
328 }
329
330 int packet_len;
331 assert (rwm_fetch_lookup (&c->in, &packet_len, 4) == 4);
332
333 if (D->crypto_flags & RPCF_QUICKACK) {
334 D->flags = (D->flags & ~RPC_F_QUICKACK) | (packet_len & RPC_F_QUICKACK);
335 packet_len &= ~RPC_F_QUICKACK;
336 }
337
338 if (packet_len <= 0 || (packet_len & 0xc0000003)) {
339 if (D->in_packet_num <= -2 && (packet_len == *(int *)"HEAD" || packet_len == *(int *)"POST" || packet_len == *(int *)"GET " || packet_len == *(int *)"OPTI") && TCP_RPCS_FUNC(C)->http_fallback_type) {
340 vkprintf (1, "switching to http fallback for connection %d\n", c->fd);
341 memset (c->custom_data, 0, sizeof (c->custom_data));
342 c->type = TCP_RPCS_FUNC(C)->http_fallback_type;
343 c->extra = TCP_RPCS_FUNC(C)->http_fallback_extra;
344
345 if (c->type->init_accepted (C) < 0) {
346 vkprintf (1, "http init_accepted() returns error for connection %d\n", c->fd);
347 fail_connection (C, -33);
348 return 0;
349 }
350 //nbit_set (&c->Q, &c->In);
351 return c->type->parse_execute (C);
352 }
353 vkprintf (1, "error while parsing packet: bad packet length %d\n", packet_len);
354 fail_connection (C, -1);
355 return 0;
356 }
357
358 if ((packet_len > TCP_RPCS_FUNC(C)->max_packet_len && TCP_RPCS_FUNC(C)->max_packet_len > 0)) {
359 vkprintf (1, "error while parsing packet: bad packet length %d\n", packet_len);
360 fail_connection (C, -1);
361 return 0;
362 }
363
364 if (packet_len == 4) {
365 assert (rwm_skip_data (&c->in, 4) == 4);
366 continue;
367 }
368
369 if (packet_len < 16) {
370 vkprintf (1, "error while parsing packet: bad packet length %d\n", packet_len);
371 fail_connection (C, -1);
372 return 0;
373 }
374
375 if (len < packet_len) {
376 return packet_len - len;
377 }
378
379 struct raw_message msg;
380 rwm_split_head (&msg, &c->in, packet_len);
381
382 unsigned crc32;
383 assert (rwm_fetch_data_back (&msg, &crc32, 4) == 4);
384
385 unsigned packet_crc32 = rwm_custom_crc32 (&msg, packet_len - 4, D->custom_crc_partial);
386 if (crc32 != packet_crc32) {
387 vkprintf (1, "error while parsing packet: crc32 = %08x != %08x\n", packet_crc32, crc32);
388 rwm_dump (&msg);
389 fail_connection (C, -1);
390 rwm_free (&msg);
391 return 0;
392 }
393
394 int packet_num;
395 int packet_type;
396 assert (rwm_skip_data (&msg, 4) == 4);
397 assert (rwm_fetch_data (&msg, &packet_num, 4) == 4);
398 assert (rwm_fetch_lookup (&msg, &packet_type, 4) == 4);
399 packet_len -= 12;
400
401 if (verbosity > 2) {
402 fprintf (stderr, "received packet from connection %d (num %d)\n", c->fd, packet_num);
403 rwm_dump (&msg);
404 }
405
406 int res = -1;
407
408 if (D->in_packet_num == -3) {
409 D->in_packet_num = 0;
410 }
411
412 if (!(D->crypto_flags & RPCF_SEQNO_HOLES) && packet_num != D->in_packet_num) {
413 vkprintf (1, "error while parsing packet: got packet num %d, expected %d\n", packet_num, D->in_packet_num);
414 fail_connection (C, -1);
415 rwm_free (&msg);
416 return 0;
417 } else if (packet_num < 0) {
418 /* this is for us */
419 if (packet_num == -2) {
420 res = tcp_rpcs_process_nonce_packet (C, &msg); // if res > 0, nonce packet sent in response
421 } else if (packet_num == -1) {
422 res = tcp_rpcs_process_handshake_packet (C, &msg);
423 if (res >= 0) {
424 res = tcp_rpcs_send_handshake_packet (C);
425 if (D->crypto_flags & RPCF_USE_CRC32C) {
426 D->custom_crc_partial = crc32c_partial;
427 }
428 notification_event_insert_tcp_conn_ready (C);
429 }
430 }
431 rwm_free (&msg);
432 if (res < 0) {
433 fail_connection (C, res);
434 return 0;
435 }
436 } else {
437 /* main case */
438 c->last_response_time = precise_now;
439 if (packet_type == RPC_PING) {
440 res = tcp_rpcs_default_execute (C, packet_type, &msg);
441 } else {
442 res = TCP_RPCS_FUNC(C)->execute (C, packet_type, &msg);
443 }
444 if (res <= 0) {
445 rwm_free (&msg);
446 }
447 }
448
449 D->in_packet_num++;
450 }
451 return NEED_MORE_BYTES;
452}
453
454int tcp_rpcs_wakeup (connection_job_t C) {
455 struct connection_info *c = CONN_INFO (C);
456
457 notification_event_insert_tcp_conn_wakeup (C);
458
459 if (c->out_p.total_bytes > 0) {
460 __sync_fetch_and_or (&c->flags, C_WANTWR);
461 }
462
463 //c->generation = ++conn_generation;
464 c->pending_queries = 0;
465 return 0;
466}
467
468int tcp_rpcs_alarm (connection_job_t C) {
469 struct connection_info *c = CONN_INFO (C);
470
471 notification_event_insert_tcp_conn_alarm (C);
472
473 if (c->out_p.total_bytes > 0) {
474 __sync_fetch_and_or (&c->flags, C_WANTWR);
475 }
476
477 //c->generation = ++conn_generation;
478 c->pending_queries = 0;
479 return 0;
480}
481
482int tcp_rpcs_close_connection (connection_job_t C, int who) {
483 if (TCP_RPCS_FUNC(C)->rpc_close) {
484 notification_event_insert_tcp_conn_close (C);
485 }
486
487 return cpu_server_close_connection (C, who);
488}
489
490
491int tcp_rpcs_do_wakeup (connection_job_t c) {
492 return 0;
493}
494
495
496int tcp_rpcs_init_accepted (connection_job_t C) {
497 struct connection_info *c = CONN_INFO (C);
498
499 c->last_query_sent_time = precise_now;
500 TCP_RPC_DATA(C)->custom_crc_partial = crc32_partial;
501
502 if (TCP_RPCS_FUNC(C)->rpc_check_perm) {
503 int res = TCP_RPCS_FUNC(C)->rpc_check_perm (C);
504 vkprintf (4, "tcp_rpcs_check_perm for connection %d: [%s]:%d -> [%s]:%d = %d\n", c->fd, show_remote_ip (C), c->remote_port, show_our_ip (C), c->our_port, res);
505 if (res < 0) {
506 return res;
507 }
508 res &= RPCF_ALLOW_UNENC | RPCF_ALLOW_ENC | RPCF_REQ_DH | RPCF_ALLOW_SKIP_DH;
509 if (!(res & (RPCF_ALLOW_UNENC | RPCF_ALLOW_ENC))) {
510 return -1;
511 }
512
513 TCP_RPC_DATA(C)->crypto_flags = res;
514 } else {
515 TCP_RPC_DATA(C)->crypto_flags = RPCF_ALLOW_UNENC;
516 }
517
518 TCP_RPC_DATA(C)->in_packet_num = -2;
519 TCP_RPC_DATA(C)->out_packet_num = -2;
520
521 return 0;
522}
523
524int tcp_rpcs_init_accepted_nohs (connection_job_t c) {
525 TCP_RPC_DATA(c)->crypto_flags = RPCF_QUICKACK | RPCF_ALLOW_UNENC;
526 TCP_RPC_DATA(c)->in_packet_num = -3;
527 TCP_RPC_DATA(c)->custom_crc_partial = crc32_partial;
528 if (TCP_RPCS_FUNC(c)->rpc_ready) {
529 notification_event_insert_tcp_conn_ready (c);
530 }
531 return 0;
532}
533
534int tcp_rpcs_init_fake_crypto (connection_job_t c) {
535 if (!(TCP_RPC_DATA(c)->crypto_flags & RPCF_ALLOW_UNENC)) {
536 return -1;
537 }
538
539 struct tcp_rpc_nonce_packet buf;
540 memset (&buf, 0, sizeof (buf));
541 buf.type = RPC_NONCE;
542 buf.crypto_schema = RPC_CRYPTO_NONE;
543
544 assert ((TCP_RPC_DATA(c)->crypto_flags & (RPCF_ALLOW_ENC | RPCF_ENC_SENT)) == 0);
545 TCP_RPC_DATA(c)->crypto_flags |= RPCF_ENC_SENT;
546
547 tcp_rpc_conn_send_data_init (c, sizeof (buf), &buf);
548
549 return 1;
550}
551
552#include "net/net-crypto-aes.h"
553#include "net/net-config.h"
554
555int tcp_rpcs_default_check_perm (connection_job_t C) {
556 return RPCF_ALLOW_ENC | RPCF_REQ_DH | tcp_get_default_rpc_flags();
557}
558
559int tcp_rpcs_init_crypto (connection_job_t C, struct tcp_rpc_nonce_packet *P) {
560 struct connection_info *c = CONN_INFO (C);
561
562// fprintf (stderr, "rpcs_init_crypto (%p [fd=%d], '%.*s')\n", c, c->fd, key_len, key);
563 struct tcp_rpc_data *D = TCP_RPC_DATA(C);
564
565 if (c->crypto) {
566 return -1;
567 }
568
569 if ((D->crypto_flags & (RPCF_ALLOW_ENC | RPCF_ALLOW_UNENC)) == RPCF_ALLOW_UNENC) {
570 return tcp_rpcs_init_fake_crypto (C);
571 }
572
573 if ((D->crypto_flags & (RPCF_ALLOW_ENC | RPCF_ALLOW_UNENC)) != RPCF_ALLOW_ENC) {
574 return -1;
575 }
576
577 if (main_secret.key_signature != P->key_select) {
578 return -1;
579 }
580
581 aes_secret_t *secret = &main_secret;
582
583 union {
584 struct tcp_rpc_nonce_packet s;
585 struct tcp_rpc_nonce_ext_packet x;
586 struct tcp_rpc_nonce_dh_packet dh;
587 } buf;
588
589 struct tcp_rpc_nonce_dh_packet *old_dh = 0, *new_dh = 0;
590 unsigned char temp_dh[256];
591 int temp_dh_len = 0;
592
593 if (D->crypto_flags & RPCF_REQ_DH) {
594 new_dh = (struct tcp_rpc_nonce_dh_packet *)((char *)&buf - 4*RPC_MAX_EXTRA_KEYS);
595 if (P->crypto_schema != RPC_CRYPTO_AES_DH) {
596 return -1;
597 }
598 old_dh = (struct tcp_rpc_nonce_dh_packet *)((char *)P + 4*(((struct tcp_rpc_nonce_dh_packet *) P)->extra_keys_count - RPC_MAX_EXTRA_KEYS));
599 if (old_dh->dh_params_select != dh_params_select || !dh_params_select) {
600 return -1;
601 }
602
603 if (tcp_add_dh_accept () < 0) {
604 return -1;
605 }
606
607 temp_dh_len = dh_second_round (temp_dh, new_dh->g_a, old_dh->g_a);
608 assert (temp_dh_len == 256);
609
610 incr_active_dh_connections ();
611 __sync_fetch_and_or (&c->flags, C_ISDH);
612 }
613 aes_generate_nonce (D->nonce);
614
615 struct aes_key_data aes_keys;
616
617 if (aes_create_keys (&aes_keys, 0, D->nonce, P->crypto_nonce, P->crypto_ts, nat_translate_ip (c->our_ip), c->our_port, c->our_ipv6, nat_translate_ip (c->remote_ip), c->remote_port, c->remote_ipv6, secret, temp_dh, temp_dh_len) < 0) {
618 return -1;
619 }
620
621 if (aes_crypto_init (C, &aes_keys, sizeof (aes_keys)) < 0) {
622 return -1;
623 }
624
625 memcpy (buf.s.crypto_nonce, D->nonce, 16);
626 buf.s.crypto_ts = D->nonce_time;
627 buf.s.type = RPC_NONCE;
628 buf.s.key_select = secret->key_signature;
629
630 int buf_len;
631 if (!new_dh) {
632 buf.s.crypto_schema = RPC_CRYPTO_AES;
633 buf_len = sizeof (struct tcp_rpc_nonce_packet);
634 } else {
635 buf.dh.crypto_schema = RPC_CRYPTO_AES_DH;
636 buf_len = sizeof (struct tcp_rpc_nonce_dh_packet) - 4*RPC_MAX_EXTRA_KEYS;
637 buf.dh.extra_keys_count = 0;
638 new_dh->dh_params_select = dh_params_select;
639 }
640
641 assert ((D->crypto_flags & (RPCF_ALLOW_ENC | RPCF_ENC_SENT)) == RPCF_ALLOW_ENC);
642 D->crypto_flags |= RPCF_ENC_SENT;
643
644 tcp_rpc_conn_send_data_init (C, buf_len, &buf);
645
646
647 return 1;
648}
649
650
651/*
652 *
653 * END (BASIC RPC SERVER)
654 *
655 */
656