BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file flooder.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stdint.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34  
35 #include <protocol/addr.h>
36 #include <protocol/scproto.h>
37 #include <misc/loglevel.h>
38 #include <misc/version.h>
39 #include <misc/nsskey.h>
40 #include <misc/byteorder.h>
41 #include <misc/loggers_string.h>
42 #include <misc/open_standard_streams.h>
43 #include <base/BLog.h>
44 #include <system/BReactor.h>
45 #include <system/BSignal.h>
46 #include <system/BNetwork.h>
47 #include <flow/SinglePacketBuffer.h>
48 #include <flow/PacketProtoEncoder.h>
49 #include <nspr_support/BSSLConnection.h>
50 #include <server_connection/ServerConnection.h>
51  
52 #ifndef BADVPN_USE_WINAPI
53 #include <base/BLog_syslog.h>
54 #endif
55  
56 #include <flooder/flooder.h>
57  
58 #include <generated/blog_channel_flooder.h>
59  
60 #define LOGGER_STDOUT 1
61 #define LOGGER_SYSLOG 2
62  
63 // command-line options
64 struct {
65 int help;
66 int version;
67 int logger;
68 #ifndef BADVPN_USE_WINAPI
69 char *logger_syslog_facility;
70 char *logger_syslog_ident;
71 #endif
72 int loglevel;
73 int loglevels[BLOG_NUM_CHANNELS];
74 int ssl;
75 char *nssdb;
76 char *client_cert_name;
77 char *server_name;
78 char *server_addr;
79 peerid_t floods[MAX_FLOODS];
80 int num_floods;
81 } options;
82  
83 // server address we connect to
84 BAddr server_addr;
85  
86 // server name to use for SSL
87 char server_name[256];
88  
89 // reactor
90 BReactor ss;
91  
92 // client certificate if using SSL
93 CERTCertificate *client_cert;
94  
95 // client private key if using SSL
96 SECKEYPrivateKey *client_key;
97  
98 // server connection
99 ServerConnection server;
100  
101 // whether server is ready
102 int server_ready;
103  
104 // my ID, defined only after server_ready
105 peerid_t my_id;
106  
107 // flooding output
108 PacketRecvInterface flood_source;
109 PacketProtoEncoder flood_encoder;
110 SinglePacketBuffer flood_buffer;
111  
112 // whether we were asked for a packet and blocked
113 int flood_blocking;
114  
115 // index of next peer to send packet too
116 int flood_next;
117  
118 /**
119 * Cleans up everything that can be cleaned up from inside the event loop.
120 */
121 static void terminate (void);
122  
123 /**
124 * Prints command line help.
125 */
126 static void print_help (const char *name);
127  
128 /**
129 * Prints program name, version and copyright notice.
130 */
131 static void print_version (void);
132  
133 /**
134 * Parses command line options into the options strucute.
135 *
136 * @return 1 on success, 0 on failure
137 */
138 static int parse_arguments (int argc, char *argv[]);
139  
140 /**
141 * Processes command line options.
142 *
143 * @return 1 on success, 0 on failure
144 */
145 static int resolve_arguments (void);
146  
147 /**
148 * Handler invoked when program termination is requested.
149 */
150 static void signal_handler (void *unused);
151  
152 static void server_handler_error (void *user);
153 static void server_handler_ready (void *user, peerid_t param_my_id, uint32_t ext_ip);
154 static void server_handler_newclient (void *user, peerid_t peer_id, int flags, const uint8_t *cert, int cert_len);
155 static void server_handler_endclient (void *user, peerid_t peer_id);
156 static void server_handler_message (void *user, peerid_t peer_id, uint8_t *data, int data_len);
157  
158 static void flood_source_handler_recv (void *user, uint8_t *data);
159  
160 int main (int argc, char *argv[])
161 {
162 if (argc <= 0) {
163 return 1;
164 }
165  
166 // open standard streams
167 open_standard_streams();
168  
169 // parse command-line arguments
170 if (!parse_arguments(argc, argv)) {
171 fprintf(stderr, "Failed to parse arguments\n");
172 print_help(argv[0]);
173 goto fail0;
174 }
175  
176 // handle --help and --version
177 if (options.help) {
178 print_version();
179 print_help(argv[0]);
180 return 0;
181 }
182 if (options.version) {
183 print_version();
184 return 0;
185 }
186  
187 // initialize logger
188 switch (options.logger) {
189 case LOGGER_STDOUT:
190 BLog_InitStdout();
191 break;
192 #ifndef BADVPN_USE_WINAPI
193 case LOGGER_SYSLOG:
194 if (!BLog_InitSyslog(options.logger_syslog_ident, options.logger_syslog_facility)) {
195 fprintf(stderr, "Failed to initialize syslog logger\n");
196 goto fail0;
197 }
198 break;
199 #endif
200 default:
201 ASSERT(0);
202 }
203  
204 // configure logger channels
205 for (int i = 0; i < BLOG_NUM_CHANNELS; i++) {
206 if (options.loglevels[i] >= 0) {
207 BLog_SetChannelLoglevel(i, options.loglevels[i]);
208 }
209 else if (options.loglevel >= 0) {
210 BLog_SetChannelLoglevel(i, options.loglevel);
211 }
212 }
213  
214 BLog(BLOG_NOTICE, "initializing "GLOBAL_PRODUCT_NAME" "PROGRAM_NAME" "GLOBAL_VERSION);
215  
216 // initialize network
217 if (!BNetwork_GlobalInit()) {
218 BLog(BLOG_ERROR, "BNetwork_GlobalInit failed");
219 goto fail1;
220 }
221  
222 // init time
223 BTime_Init();
224  
225 // resolve addresses
226 if (!resolve_arguments()) {
227 BLog(BLOG_ERROR, "Failed to resolve arguments");
228 goto fail1;
229 }
230  
231 // init reactor
232 if (!BReactor_Init(&ss)) {
233 BLog(BLOG_ERROR, "BReactor_Init failed");
234 goto fail1;
235 }
236  
237 // setup signal handler
238 if (!BSignal_Init(&ss, signal_handler, NULL)) {
239 BLog(BLOG_ERROR, "BSignal_Init failed");
240 goto fail1a;
241 }
242  
243 if (options.ssl) {
244 // init NSPR
245 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
246  
247 // register local NSPR file types
248 if (!BSSLConnection_GlobalInit()) {
249 BLog(BLOG_ERROR, "BSSLConnection_GlobalInit failed");
250 goto fail3;
251 }
252  
253 // init NSS
254 if (NSS_Init(options.nssdb) != SECSuccess) {
255 BLog(BLOG_ERROR, "NSS_Init failed (%d)", (int)PR_GetError());
256 goto fail2;
257 }
258  
259 // set cipher policy
260 if (NSS_SetDomesticPolicy() != SECSuccess) {
261 BLog(BLOG_ERROR, "NSS_SetDomesticPolicy failed (%d)", (int)PR_GetError());
262 goto fail3;
263 }
264  
265 // init server cache
266 if (SSL_ConfigServerSessionIDCache(0, 0, 0, NULL) != SECSuccess) {
267 BLog(BLOG_ERROR, "SSL_ConfigServerSessionIDCache failed (%d)", (int)PR_GetError());
268 goto fail3;
269 }
270  
271 // open server certificate and private key
272 if (!open_nss_cert_and_key(options.client_cert_name, &client_cert, &client_key)) {
273 BLog(BLOG_ERROR, "Cannot open certificate and key");
274 goto fail4;
275 }
276 }
277  
278 // start connecting to server
279 if (!ServerConnection_Init(
280 &server, &ss, NULL, server_addr, SC_KEEPALIVE_INTERVAL, SERVER_BUFFER_MIN_PACKETS, options.ssl, 0, client_cert, client_key, server_name, NULL,
281 server_handler_error, server_handler_ready, server_handler_newclient, server_handler_endclient, server_handler_message
282 )) {
283 BLog(BLOG_ERROR, "ServerConnection_Init failed");
284 goto fail5;
285 }
286  
287 // set server not ready
288 server_ready = 0;
289  
290 // enter event loop
291 BLog(BLOG_NOTICE, "entering event loop");
292 BReactor_Exec(&ss);
293  
294 if (server_ready) {
295 ServerConnection_ReleaseBuffers(&server);
296 SinglePacketBuffer_Free(&flood_buffer);
297 PacketProtoEncoder_Free(&flood_encoder);
298 PacketRecvInterface_Free(&flood_source);
299 }
300  
301 ServerConnection_Free(&server);
302 fail5:
303 if (options.ssl) {
304 CERT_DestroyCertificate(client_cert);
305 SECKEY_DestroyPrivateKey(client_key);
306 fail4:
307 ASSERT_FORCE(SSL_ShutdownServerSessionIDCache() == SECSuccess)
308 fail3:
309 SSL_ClearSessionCache();
310 ASSERT_FORCE(NSS_Shutdown() == SECSuccess)
311 fail2:
312 ASSERT_FORCE(PR_Cleanup() == PR_SUCCESS)
313 PL_ArenaFinish();
314 }
315  
316 BSignal_Finish();
317 fail1a:
318 BReactor_Free(&ss);
319 fail1:
320 BLog(BLOG_NOTICE, "exiting");
321 BLog_Free();
322 fail0:
323 DebugObjectGlobal_Finish();
324  
325 return 1;
326 }
327  
328 void terminate (void)
329 {
330 BLog(BLOG_NOTICE, "tearing down");
331  
332 // exit event loop
333 BReactor_Quit(&ss, 0);
334 }
335  
336 void print_help (const char *name)
337 {
338 printf(
339 "Usage:\n"
340 " %s\n"
341 " [--help]\n"
342 " [--version]\n"
343 " [--logger <"LOGGERS_STRING">]\n"
344 #ifndef BADVPN_USE_WINAPI
345 " (logger=syslog?\n"
346 " [--syslog-facility <string>]\n"
347 " [--syslog-ident <string>]\n"
348 " )\n"
349 #endif
350 " [--loglevel <0-5/none/error/warning/notice/info/debug>]\n"
351 " [--channel-loglevel <channel-name> <0-5/none/error/warning/notice/info/debug>] ...\n"
352 " [--ssl --nssdb <string> --client-cert-name <string>]\n"
353 " [--server-name <string>]\n"
354 " --server-addr <addr>\n"
355 " [--flood-id <id>] ...\n"
356 "Address format is a.b.c.d:port (IPv4) or [addr]:port (IPv6).\n",
357 name
358 );
359 }
360  
361 void print_version (void)
362 {
363 printf(GLOBAL_PRODUCT_NAME" "PROGRAM_NAME" "GLOBAL_VERSION"\n"GLOBAL_COPYRIGHT_NOTICE"\n");
364 }
365  
366 int parse_arguments (int argc, char *argv[])
367 {
368 if (argc <= 0) {
369 return 0;
370 }
371  
372 options.help = 0;
373 options.version = 0;
374 options.logger = LOGGER_STDOUT;
375 #ifndef BADVPN_USE_WINAPI
376 options.logger_syslog_facility = "daemon";
377 options.logger_syslog_ident = argv[0];
378 #endif
379 options.loglevel = -1;
380 for (int i = 0; i < BLOG_NUM_CHANNELS; i++) {
381 options.loglevels[i] = -1;
382 }
383 options.ssl = 0;
384 options.nssdb = NULL;
385 options.client_cert_name = NULL;
386 options.server_name = NULL;
387 options.server_addr = NULL;
388 options.num_floods = 0;
389  
390 int i;
391 for (i = 1; i < argc; i++) {
392 char *arg = argv[i];
393 if (!strcmp(arg, "--help")) {
394 options.help = 1;
395 }
396 else if (!strcmp(arg, "--version")) {
397 options.version = 1;
398 }
399 else if (!strcmp(arg, "--logger")) {
400 if (1 >= argc - i) {
401 fprintf(stderr, "%s: requires an argument\n", arg);
402 return 0;
403 }
404 char *arg2 = argv[i + 1];
405 if (!strcmp(arg2, "stdout")) {
406 options.logger = LOGGER_STDOUT;
407 }
408 #ifndef BADVPN_USE_WINAPI
409 else if (!strcmp(arg2, "syslog")) {
410 options.logger = LOGGER_SYSLOG;
411 }
412 #endif
413 else {
414 fprintf(stderr, "%s: wrong argument\n", arg);
415 return 0;
416 }
417 i++;
418 }
419 #ifndef BADVPN_USE_WINAPI
420 else if (!strcmp(arg, "--syslog-facility")) {
421 if (1 >= argc - i) {
422 fprintf(stderr, "%s: requires an argument\n", arg);
423 return 0;
424 }
425 options.logger_syslog_facility = argv[i + 1];
426 i++;
427 }
428 else if (!strcmp(arg, "--syslog-ident")) {
429 if (1 >= argc - i) {
430 fprintf(stderr, "%s: requires an argument\n", arg);
431 return 0;
432 }
433 options.logger_syslog_ident = argv[i + 1];
434 i++;
435 }
436 #endif
437 else if (!strcmp(arg, "--loglevel")) {
438 if (1 >= argc - i) {
439 fprintf(stderr, "%s: requires an argument\n", arg);
440 return 0;
441 }
442 if ((options.loglevel = parse_loglevel(argv[i + 1])) < 0) {
443 fprintf(stderr, "%s: wrong argument\n", arg);
444 return 0;
445 }
446 i++;
447 }
448 else if (!strcmp(arg, "--channel-loglevel")) {
449 if (2 >= argc - i) {
450 fprintf(stderr, "%s: requires two arguments\n", arg);
451 return 0;
452 }
453 int channel = BLogGlobal_GetChannelByName(argv[i + 1]);
454 if (channel < 0) {
455 fprintf(stderr, "%s: wrong channel argument\n", arg);
456 return 0;
457 }
458 int loglevel = parse_loglevel(argv[i + 2]);
459 if (loglevel < 0) {
460 fprintf(stderr, "%s: wrong loglevel argument\n", arg);
461 return 0;
462 }
463 options.loglevels[channel] = loglevel;
464 i += 2;
465 }
466 else if (!strcmp(arg, "--ssl")) {
467 options.ssl = 1;
468 }
469 else if (!strcmp(arg, "--nssdb")) {
470 if (1 >= argc - i) {
471 fprintf(stderr, "%s: requires an argument\n", arg);
472 return 0;
473 }
474 options.nssdb = argv[i + 1];
475 i++;
476 }
477 else if (!strcmp(arg, "--client-cert-name")) {
478 if (1 >= argc - i) {
479 fprintf(stderr, "%s: requires an argument\n", arg);
480 return 0;
481 }
482 options.client_cert_name = argv[i + 1];
483 i++;
484 }
485 else if (!strcmp(arg, "--server-name")) {
486 if (1 >= argc - i) {
487 fprintf(stderr, "%s: requires an argument\n", arg);
488 return 0;
489 }
490 options.server_name = argv[i + 1];
491 i++;
492 }
493 else if (!strcmp(arg, "--server-addr")) {
494 if (1 >= argc - i) {
495 fprintf(stderr, "%s: requires an argument\n", arg);
496 return 0;
497 }
498 options.server_addr = argv[i + 1];
499 i++;
500 }
501 else if (!strcmp(arg, "--flood-id")) {
502 if (1 >= argc - i) {
503 fprintf(stderr, "%s: requires an argument\n", arg);
504 return 0;
505 }
506 if (options.num_floods == MAX_FLOODS) {
507 fprintf(stderr, "%s: too many\n", arg);
508 return 0;
509 }
510 options.floods[options.num_floods] = atoi(argv[i + 1]);
511 options.num_floods++;
512 i++;
513 }
514 else {
515 fprintf(stderr, "unknown option: %s\n", arg);
516 return 0;
517 }
518 }
519  
520 if (options.help || options.version) {
521 return 1;
522 }
523  
524 if (options.ssl != !!options.nssdb) {
525 fprintf(stderr, "False: --ssl <=> --nssdb\n");
526 return 0;
527 }
528  
529 if (options.ssl != !!options.client_cert_name) {
530 fprintf(stderr, "False: --ssl <=> --client-cert-name\n");
531 return 0;
532 }
533  
534 if (!options.server_addr) {
535 fprintf(stderr, "False: --server-addr\n");
536 return 0;
537 }
538  
539 return 1;
540 }
541  
542 int resolve_arguments (void)
543 {
544 // resolve server address
545 ASSERT(options.server_addr)
546 if (!BAddr_Parse(&server_addr, options.server_addr, server_name, sizeof(server_name))) {
547 BLog(BLOG_ERROR, "server addr: BAddr_Parse failed");
548 return 0;
549 }
550 if (!addr_supported(server_addr)) {
551 BLog(BLOG_ERROR, "server addr: not supported");
552 return 0;
553 }
554  
555 // override server name if requested
556 if (options.server_name) {
557 if (strlen(options.server_name) >= sizeof(server_name)) {
558 BLog(BLOG_ERROR, "server name: too long");
559 return 0;
560 }
561 strcpy(server_name, options.server_name);
562 }
563  
564 return 1;
565 }
566  
567 void signal_handler (void *unused)
568 {
569 BLog(BLOG_NOTICE, "termination requested");
570  
571 terminate();
572 }
573  
574 void server_handler_error (void *user)
575 {
576 BLog(BLOG_ERROR, "server connection failed, exiting");
577  
578 terminate();
579 }
580  
581 void server_handler_ready (void *user, peerid_t param_my_id, uint32_t ext_ip)
582 {
583 ASSERT(!server_ready)
584  
585 // remember our ID
586 my_id = param_my_id;
587  
588 // init flooding
589  
590 // init source
591 PacketRecvInterface_Init(&flood_source, SC_MAX_ENC, flood_source_handler_recv, NULL, BReactor_PendingGroup(&ss));
592  
593 // init encoder
594 PacketProtoEncoder_Init(&flood_encoder, &flood_source, BReactor_PendingGroup(&ss));
595  
596 // init buffer
597 if (!SinglePacketBuffer_Init(&flood_buffer, PacketProtoEncoder_GetOutput(&flood_encoder), ServerConnection_GetSendInterface(&server), BReactor_PendingGroup(&ss))) {
598 BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed, exiting");
599 goto fail1;
600 }
601  
602 // set not blocking
603 flood_blocking = 0;
604  
605 // set server ready
606 server_ready = 1;
607  
608 BLog(BLOG_INFO, "server: ready, my ID is %d", (int)my_id);
609  
610 return;
611  
612 fail1:
613 PacketProtoEncoder_Free(&flood_encoder);
614 PacketRecvInterface_Free(&flood_source);
615 terminate();
616 }
617  
618 void server_handler_newclient (void *user, peerid_t peer_id, int flags, const uint8_t *cert, int cert_len)
619 {
620 ASSERT(server_ready)
621  
622 BLog(BLOG_INFO, "newclient %d", (int)peer_id);
623 }
624  
625 void server_handler_endclient (void *user, peerid_t peer_id)
626 {
627 ASSERT(server_ready)
628  
629 BLog(BLOG_INFO, "endclient %d", (int)peer_id);
630 }
631  
632 void server_handler_message (void *user, peerid_t peer_id, uint8_t *data, int data_len)
633 {
634 ASSERT(server_ready)
635 ASSERT(data_len >= 0)
636 ASSERT(data_len <= SC_MAX_MSGLEN)
637  
638 BLog(BLOG_INFO, "message from %d", (int)peer_id);
639 }
640  
641 void flood_source_handler_recv (void *user, uint8_t *data)
642 {
643 ASSERT(server_ready)
644 ASSERT(!flood_blocking)
645 if (options.num_floods > 0) {
646 ASSERT(flood_next >= 0)
647 ASSERT(flood_next < options.num_floods)
648 }
649  
650 if (options.num_floods == 0) {
651 flood_blocking = 1;
652 return;
653 }
654  
655 peerid_t peer_id = options.floods[flood_next];
656 flood_next = (flood_next + 1) % options.num_floods;
657  
658 BLog(BLOG_INFO, "message to %d", (int)peer_id);
659  
660 struct sc_header header;
661 header.type = SCID_OUTMSG;
662 memcpy(data, &header, sizeof(header));
663  
664 struct sc_client_outmsg omsg;
665 omsg.clientid = htol16(peer_id);
666 memcpy(data + sizeof(header), &omsg, sizeof(omsg));
667  
668 memset(data + sizeof(struct sc_header) + sizeof(struct sc_client_outmsg), 0, SC_MAX_MSGLEN);
669  
670 PacketRecvInterface_Done(&flood_source, sizeof(struct sc_header) + sizeof(struct sc_client_outmsg) + SC_MAX_MSGLEN);
671 }