ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/branches/1.1.x/src/libopm/src/libopm.c
Revision: 5673
Committed: Wed Mar 11 18:55:56 2015 UTC (9 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: hopm/trunk/src/libopm/src/libopm.c
File size: 30249 byte(s)
Log Message:
- libopm.c: fixed an off by one in opm_callback() and libopm_do_callback() that potentially
  allowed to write to out-of-bounds memory

File Contents

# Content
1 /*
2 * Copyright (C) 2002-2003 Erik Fears
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (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 General Public License
15 * along with this program; if not, write to
16 *
17 * The Free Software Foundation, Inc.
18 * 59 Temple Place - Suite 330
19 * Boston, MA 02111-1307, USA.
20 *
21 *
22 */
23
24 #include "setup.h"
25
26 #include "config.h"
27 #include "libopm.h"
28 #include "malloc.h"
29 #include "opm_error.h"
30 #include "opm_types.h"
31 #include "opm_common.h"
32 #include "list.h"
33 #include "inet.h"
34 #include "proxy.h"
35
36 #include <errno.h>
37 #include <sys/time.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <poll.h>
42
43
44 static OPM_PROTOCOL_CONFIG_T *libopm_protocol_config_create(void);
45 static void libopm_protocol_config_free(OPM_PROTOCOL_CONFIG_T *);
46
47 /*
48 * XXX - does not appear to be used anywhere?
49 * -grifferz
50 */
51 #if 0
52 static OPM_PROTOCOL_T *libopm_protocol_create(void);
53 static void libopm_protocol_free(OPM_PROTOCOL_T *);
54 #endif
55
56 static OPM_SCAN_T *libopm_scan_create(OPM_T *, OPM_REMOTE_T *);
57 static void libopm_scan_free(OPM_SCAN_T *);
58
59 static OPM_CONNECTION_T *libopm_connection_create(void);
60 static void libopm_connection_free(OPM_CONNECTION_T *);
61
62 static void libopm_check_establish(OPM_T *);
63 static void libopm_check_poll(OPM_T *);
64 static void libopm_check_closed(OPM_T *);
65 static void libopm_check_queue(OPM_T *);
66
67 static void libopm_do_connect(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
68 static void libopm_do_readready(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
69 static void libopm_do_writeready(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
70 static void libopm_do_hup(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
71 static void libopm_do_read(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
72 static void libopm_do_openproxy(OPM_T *, OPM_SCAN_T *, OPM_CONNECTION_T *);
73 static void libopm_do_callback(OPM_T *, OPM_REMOTE_T *, int, int);
74
75 static OPM_REMOTE_T *libopm_setup_remote(OPM_REMOTE_T *, OPM_CONNECTION_T *);
76
77
78 /* OPM_PROTOCOLS hash
79 *
80 * OPM_PPROTOCOLS hashes the protocol types (int) to functions
81 * which handle the protocol (sending/receiving protocol specific
82 * data).
83 *
84 */
85 static OPM_PROTOCOL_T OPM_PROTOCOLS[] =
86 {
87 { OPM_TYPE_HTTP, libopm_proxy_http_write, NULL },
88 { OPM_TYPE_SOCKS4, libopm_proxy_socks4_write, NULL },
89 { OPM_TYPE_SOCKS5, libopm_proxy_socks5_write, NULL },
90 { OPM_TYPE_ROUTER, libopm_proxy_router_write, NULL },
91 { OPM_TYPE_WINGATE, libopm_proxy_wingate_write, NULL },
92 { OPM_TYPE_HTTPPOST, libopm_proxy_httppost_write, NULL }
93 };
94
95 /* opm_create
96 *
97 * Initialize a new scanner and return a pointer to it.
98 *
99 * Parameters:
100 * None
101 *
102 * Return
103 * Pointer to new OPM_T (scanner)
104 */
105 OPM_T *
106 opm_create(void)
107 {
108 int i;
109 OPM_T *ret;
110
111 ret = xcalloc(sizeof *ret);
112
113 ret->config = libopm_config_create();
114 ret->scans = libopm_list_create();
115 ret->queue = libopm_list_create();
116 ret->protocols = libopm_list_create();
117 ret->fd_use = 0;
118
119 /* Setup callbacks */
120 ret->callbacks = xcalloc(sizeof(OPM_CALLBACK_T) * CBLEN);
121
122 for (i = 0; i < CBLEN; i++)
123 {
124 ret->callbacks[i].func = NULL;
125 ret->callbacks[i].data = NULL;
126 }
127
128 return ret;
129 }
130
131 /* opm_remote_create
132 *
133 * Create OPM_REMOTE_T struct, fill it with neccessary
134 * default values and return it to the client.
135 *
136 * Parameters:
137 * ip: IP of remote host
138 *
139 * Return:
140 * Address of OPM_REMOTE_T created
141 *
142 */
143 OPM_REMOTE_T *
144 opm_remote_create(const char *ip)
145 {
146 OPM_REMOTE_T *ret;
147
148 ret = xcalloc(sizeof *ret);
149 ret->ip = libopm_xstrdup(ip);
150 ret->protocols = libopm_list_create(); /* Setup protocol list */
151
152 return ret;
153 }
154
155 /* opm_remote_free
156 *
157 * Free OPM_REMOTE_T struct and cleanup
158 *
159 * Parameters:
160 * remote: Struct to free
161 *
162 * Return:
163 * None
164 */
165 void
166 opm_remote_free(OPM_REMOTE_T *remote)
167 {
168 OPM_NODE_T *p, *next;
169 OPM_PROTOCOL_CONFIG_T *ppc;
170
171 MyFree(remote->ip);
172
173 LIST_FOREACH_SAFE(p, next, remote->protocols->head)
174 {
175 ppc = p->data;
176
177 libopm_protocol_config_free(ppc);
178 libopm_list_remove(remote->protocols, p);
179 libopm_node_free(p);
180 }
181
182 libopm_list_free(remote->protocols);
183
184 MyFree(remote);
185 }
186
187 /* opm_callback
188 * Register scanner level callback
189 *
190 * Parameters
191 * scanner: scanner struct
192 * type: callback type
193 * Return:
194 * Error code
195 */
196
197 OPM_ERR_T
198 opm_callback(OPM_T *scanner, int type, OPM_CALLBACK_FUNC *function, void *data)
199 {
200 if (type < 0 || type >= CBLEN)
201 return OPM_ERR_CBNOTFOUND;
202
203 scanner->callbacks[type].func = function;
204 scanner->callbacks[type].data = data;
205
206 return OPM_SUCCESS;
207 }
208
209 /* opm_free
210 *
211 * Free OPM_T (scanner) and cleanup
212 *
213 * Parameters:
214 * scanner: Address of OPM_T to cleanup
215 *
216 * Return:
217 * None
218 */
219 void
220 opm_free(OPM_T *scanner)
221 {
222 OPM_NODE_T *p, *next;
223 OPM_PROTOCOL_CONFIG_T *ppc;
224 OPM_SCAN_T *scan;
225
226 libopm_config_free(scanner->config);
227
228 LIST_FOREACH_SAFE(p, next, scanner->protocols->head)
229 {
230 ppc = p->data;
231
232 libopm_protocol_config_free(ppc);
233 libopm_list_remove(scanner->protocols, p);
234 libopm_node_free(p);
235 }
236
237 LIST_FOREACH_SAFE(p, next, scanner->scans->head)
238 {
239 scan = p->data;
240
241 libopm_scan_free(scan);
242 libopm_list_remove(scanner->scans, p);
243 libopm_node_free(p);
244 }
245
246 LIST_FOREACH_SAFE(p, next, scanner->queue->head)
247 {
248 scan = p->data;
249
250 libopm_scan_free(scan);
251 libopm_list_remove(scanner->queue, p);
252 libopm_node_free(p);
253 }
254
255 libopm_list_free(scanner->protocols);
256 libopm_list_free(scanner->scans);
257 libopm_list_free(scanner->queue);
258
259 MyFree(scanner->callbacks);
260 MyFree(scanner);
261 }
262
263 /* opm_config
264 *
265 * Wrapper to config_set. Set configuration variables
266 * on the config struct.
267 *
268 * Parameters:
269 * scanner: OPM_T struct the config struct resides in
270 * key: Variable within the config struct to set
271 * value: Address of value to set variable (key) to
272 *
273 * Return:
274 * OPM_ERR_T containing error code
275 */
276 OPM_ERR_T
277 opm_config(OPM_T *scanner, int key, const void *value)
278 {
279 return libopm_config_set((scanner->config), key, value);
280 }
281
282 /* opm_addtype
283 *
284 * Add a proxy type and port to the list of protocols
285 * a scanner will use.
286 *
287 * Parameters:
288 * scanner: pointer to scanner struct
289 * type: type of proxy to scan (used in hashing to the functions)
290 * port: port this specific type/protocol will scan on
291 * Return:
292 * OPM_SUCCESS: Successful protocol add
293 * OPM_ERR_BADPROTOCOL: Protocol is unknown
294 */
295 OPM_ERR_T
296 opm_addtype(OPM_T *scanner, int type, unsigned short int port)
297 {
298 OPM_NODE_T *node;
299 OPM_PROTOCOL_CONFIG_T *protocol_config;
300
301 for (unsigned int i = 0; i < sizeof(OPM_PROTOCOLS) / sizeof(OPM_PROTOCOL_T); ++i)
302 {
303 if (type == OPM_PROTOCOLS[i].type)
304 {
305 protocol_config = libopm_protocol_config_create();
306 protocol_config->type = &OPM_PROTOCOLS[i];
307 protocol_config->port = port;
308
309 node = libopm_node_create(protocol_config);
310 libopm_list_add(scanner->protocols, node);
311
312 return OPM_SUCCESS;
313 }
314 }
315
316 return OPM_ERR_BADPROTOCOL;
317 }
318
319 /* opm_remote_addtype
320 *
321 * Add a proxy type and port to the list of protocols
322 * a scanner will use.
323 *
324 * Parameters:
325 * remote: pointer to scanner struct
326 * type: type of proxy to scan (used in hashing to the functions)
327 * port: port this specific type/protocol will scan on
328 * Return:
329 * OPM_SUCCESS: Successful protocol add
330 * OPM_ERR_BADPROTOCOL: Protocol is unknown
331 */
332 OPM_ERR_T opm_remote_addtype(OPM_REMOTE_T *remote, int type, unsigned short int port)
333 {
334 OPM_NODE_T *node;
335 OPM_PROTOCOL_CONFIG_T *protocol_config;
336
337 for (unsigned int i = 0; i < sizeof(OPM_PROTOCOLS) / sizeof(OPM_PROTOCOL_T); ++i)
338 {
339 if (type == OPM_PROTOCOLS[i].type)
340 {
341 protocol_config = libopm_protocol_config_create();
342 protocol_config->type = &OPM_PROTOCOLS[i];
343 protocol_config->port = port;
344
345 node = libopm_node_create(protocol_config);
346 libopm_list_add(remote->protocols, node);
347
348 return OPM_SUCCESS;
349 }
350 }
351
352 return OPM_ERR_BADPROTOCOL;
353 }
354
355 /* libopm_protocol_create
356 *
357 * Create OPM_PROTOCOL_T struct.
358 *
359 * Parameters:
360 * None
361 * Return:
362 * Pointer to new struct
363 *
364 * XXX - does not appear to be used anywhere?
365 * -grifferz
366 */
367 #if 0
368 static OPM_PROTOCOL_T *libopm_protocol_create(void)
369 {
370 OPM_PROTOCOL_T *ret;
371 ret = xcalloc(sizeof(OPM_PROTOCOL_T));
372
373 ret->type = 0;
374 ret->write_function = NULL;
375 ret->read_function = NULL;
376
377 return ret;
378 }
379 #endif
380
381 /* libopm_protocol_free
382 *
383 * Free an OPM_PROTOCOL_T struct. Assume that if
384 * format is not NULL, it is pointed to dynamically
385 * allocated memory and free it.
386 *
387 * Parameters:
388 * protocol: struct to free
389 *
390 * Return:
391 * None
392 *
393 * XXX - apparently no longer used?
394 * -grifferz
395 */
396 #if 0
397 static void
398 libopm_protocol_free(OPM_PROTOCOL_T *protocol)
399 {
400 MyFree(protocol);
401 }
402 #endif
403
404 /* libopm_protocol_config_create
405 *
406 * Allocate and return address of a new OPM_PROTOCOL_CONFIG_T
407 *
408 * Parameters:
409 * None
410 *
411 * Return:
412 * Address of new OPM_PROTOCOL_CONFIG_T
413 */
414 static OPM_PROTOCOL_CONFIG_T *
415 libopm_protocol_config_create(void)
416 {
417 OPM_PROTOCOL_CONFIG_T *ret;
418
419 ret = xcalloc(sizeof *ret);
420
421 return ret;
422 }
423
424 /* protocol_config_free
425 *
426 * Free OPM_PROTOCOL_CONFIG_T struct
427 *
428 * Parameters:
429 * protocol: struct to free
430 *
431 * Return:
432 * None
433 */
434 static void
435 libopm_protocol_config_free(OPM_PROTOCOL_CONFIG_T *protocol)
436 {
437 MyFree(protocol);
438 }
439
440 /* opm_scan
441 *
442 * Scan remote host. The opm_scan function takes an OPM_REMOTE_T
443 * struct, calculates the in_addr of the remote host, and creates
444 * a scan list based on protocols defined in the scanner.
445 *
446 * Parameters:
447 * scanner: Scanner to scan host on
448 * remote: OPM_REMOTE_T defining remote host
449 *
450 * Return:
451 * (to be written)
452 */
453 OPM_ERR_T
454 opm_scan(OPM_T *scanner, OPM_REMOTE_T *remote)
455 {
456 OPM_SCAN_T *scan; /* New scan for OPM_T */
457 OPM_NODE_T *node; /* Node we'll add scan to when we link it to scans */
458 unsigned int fd_limit;
459
460 fd_limit = *(int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
461
462 if (LIST_SIZE(scanner->protocols) == 0 &&
463 LIST_SIZE(remote->protocols) == 0)
464 return OPM_ERR_NOPROTOCOLS;
465
466 scan = libopm_scan_create(scanner, remote);
467
468 if (inet_pton(AF_INET, remote->ip, &(scan->addr.sa4.sin_addr)) <= 0)
469 {
470 libopm_scan_free(scan);
471 return OPM_ERR_BADADDR;
472 }
473
474 node = libopm_node_create(scan);
475 libopm_list_add(scanner->queue, node);
476
477 return OPM_SUCCESS;
478 }
479
480 /* opm_end
481 *
482 * End a scan prematurely.
483 *
484 * Parameters:
485 * scanner: Scanner to end scan on
486 * remote: Pointer to remote struct to search for and end
487 *
488 * Return:
489 * No return. OPM_CALLBACK_END will still be called as normal.
490 */
491 void
492 opm_end(OPM_T *scanner, OPM_REMOTE_T *remote)
493 {
494 OPM_NODE_T *node1, *node2, *next1, *next2;
495 OPM_SCAN_T *scan;
496 OPM_CONNECTION_T *conn;
497
498 /* End active scans */
499 opm_endscan(scanner, remote);
500
501 /*
502 * Secondly remove all traces of it in the queue. Once removed we have to call
503 * OPM_CALLBACK_END
504 */
505 LIST_FOREACH_SAFE(node1, next1, scanner->queue->head)
506 {
507 scan = node1->data;
508
509 if (scan->remote == remote)
510 {
511 /* Free all connections */
512 LIST_FOREACH_SAFE(node2, next2, scan->connections->head)
513 {
514 conn = node2->data;
515
516 libopm_list_remove(scan->connections, node2);
517 libopm_connection_free(conn);
518 libopm_node_free(node2);
519 continue;
520 }
521
522 /* OPM_CALLBACK_END because check_closed normally handles this */
523 libopm_do_callback(scanner, scan->remote, OPM_CALLBACK_END, 0);
524
525 /* Free up the scan */
526 libopm_list_remove(scanner->queue, node1);
527 libopm_scan_free(scan);
528 libopm_node_free(node1);
529 }
530 }
531 }
532
533 /* opm_endscan
534 *
535 * End a scan prematurely. Only end non-queued scans. This is useful
536 * because it only checks the active scan list (saving time), where
537 * opm_end checks both the scan and the possibly large queue.
538 *
539 * Parameters:
540 * scanner: Scanner to end scan on
541 * remote: Pointer to remote struct to search for and end
542 *
543 * Return:
544 * No return. OPM_CALLBACK_END will still be called as normal.
545 */
546 void
547 opm_endscan(OPM_T *scanner, OPM_REMOTE_T *remote)
548 {
549 OPM_NODE_T *node1, *node2;
550 OPM_SCAN_T *scan;
551 OPM_CONNECTION_T *conn;
552
553 /*
554 * First check to see if it's in the queue, if it is set all connections closed
555 * Next cycle of libopm_check_closed will take care of the garbage and handle
556 * OPM_CALLBACK_END
557 */
558 LIST_FOREACH(node1, scanner->scans->head)
559 {
560 scan = node1->data;
561
562 if (scan->remote == remote)
563 {
564 LIST_FOREACH(node2, scan->connections->head)
565 {
566 conn = (OPM_CONNECTION_T *) node2->data;
567 conn->state = OPM_STATE_CLOSED;
568 }
569 }
570 }
571 }
572
573 /* opm_active
574
575 Return number of scans in a scanner left.
576
577 Parameters:
578 scanner: Scanner to return active scans on
579
580 Return:
581 Number of active scans, both queued and active.
582 */
583 size_t
584 opm_active(OPM_T *scanner)
585 {
586 return LIST_SIZE(scanner->queue) + LIST_SIZE(scanner->scans);
587 }
588
589 /* scan_create
590 *
591 * Create new OPM_SCAN_T struct
592 *
593 * Parameters:
594 * scanner: Scanner the scan is being created for. This
595 * is needed to get information on currently set
596 * protocols/config.
597 *
598 * remote: Remote host this scan will be scanning
599 *
600 * Return
601 * Address of new struct
602 */
603 static OPM_SCAN_T *
604 libopm_scan_create(OPM_T *scanner, OPM_REMOTE_T *remote)
605 {
606 OPM_SCAN_T *ret;
607 OPM_CONNECTION_T *conn;
608 OPM_NODE_T *node, *p;
609
610 ret = xcalloc(sizeof *ret);
611
612 ret->remote = remote;
613 ret->connections = libopm_list_create();
614
615 /* Setup list of connections, one for each protocol */
616 LIST_FOREACH(p, scanner->protocols->head)
617 {
618 conn = libopm_connection_create();
619
620 conn->protocol = ((OPM_PROTOCOL_CONFIG_T *)p->data)->type;
621 conn->port = ((OPM_PROTOCOL_CONFIG_T *)p->data)->port;
622
623 node = libopm_node_create(conn);
624 libopm_list_add(ret->connections, node);
625 }
626
627 /*
628 * Do the same for any specific protocols the remote struct might be configured with
629 */
630 LIST_FOREACH(p, remote->protocols->head)
631 {
632 conn = libopm_connection_create();
633
634 conn->protocol = ((OPM_PROTOCOL_CONFIG_T *)p->data)->type;
635 conn->port = ((OPM_PROTOCOL_CONFIG_T *)p->data)->port;
636
637 node = libopm_node_create(conn);
638 libopm_list_add(ret->connections, node);
639 }
640
641 memset(&(ret->addr), 0, sizeof(opm_sockaddr));
642 return ret;
643 }
644
645 /* scan_free
646 *
647 * Free and cleanup OPM_SCAN_T struct
648 *
649 * Parametsr:
650 * scan: Scan struct to free
651 *
652 * Return:
653 * None
654 */
655 static void
656 libopm_scan_free(OPM_SCAN_T *scan)
657 {
658 OPM_NODE_T *p, *next;
659 OPM_CONNECTION_T *conn;
660
661 LIST_FOREACH_SAFE(p, next, scan->connections->head)
662 {
663 conn = p->data;
664
665 libopm_connection_free(conn);
666 libopm_list_remove(scan->connections, p);
667 libopm_node_free(p);
668 }
669
670 libopm_list_free(scan->connections);
671
672 MyFree(scan);
673 }
674
675 /* connection_create
676 *
677 * Allocate new OPM_CONNECTION_T
678 *
679 * Parameters:
680 * None
681 *
682 * Return:
683 * Address of new OPM_CONNECTION_T
684 */
685 static OPM_CONNECTION_T *
686 libopm_connection_create(void)
687 {
688 OPM_CONNECTION_T *ret;
689
690 ret = xcalloc(sizeof *ret);
691
692 ret->fd = 0;
693 ret->bytes_read = 0;
694 ret->readlen = 0;
695 ret->protocol = 0;
696 ret->port = 0;
697
698 ret->state = OPM_STATE_UNESTABLISHED;
699
700 return ret;
701 }
702
703 /* connection_free
704 *
705 * Free OPM_CONNECTION_T struct
706 *
707 * Parameters:
708 * conn: Address of struct to free
709 *
710 * Return:
711 * None
712 */
713 static void
714 libopm_connection_free(OPM_CONNECTION_T *conn)
715 {
716 MyFree(conn);
717 }
718
719 /* opm_cycle
720 *
721 * Perform tasks (called by client's loop)
722 *
723 * Parameters:
724 * None
725 * Return:
726 * None
727 */
728 void
729 opm_cycle(OPM_T *scanner)
730 {
731 libopm_check_queue(scanner); /* Move scans from the queue to the live scan list */
732 libopm_check_establish(scanner); /* Make new connections if possible */
733 libopm_check_poll(scanner); /* Poll connections for IO and proxy test */
734 libopm_check_closed(scanner); /* Check for closed or timed out connections */
735 }
736
737 /* check_queue
738 *
739 * Move scans from the queue to the live scan list as long as there is
740 * room.
741 *
742 * Parameters:
743 * scanner: Scanner to check queue on
744 *
745 * Return:
746 * None
747 */
748 static void
749 libopm_check_queue(OPM_T *scanner)
750 {
751 OPM_NODE_T *node;
752 OPM_SCAN_T *scan;
753 unsigned int protocols, projected, fd_limit;
754
755 if (LIST_SIZE(scanner->queue) == 0)
756 return;
757
758 fd_limit = *(int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
759 projected = scanner->fd_use;
760
761 /*
762 * We want to keep the live scan list as small as possible, so only move
763 * queued scans to the live list if they will not push above fd_limit
764 */
765 while (LIST_SIZE(scanner->queue) > 0)
766 {
767 /* Grab the top scan */
768 scan = scanner->queue->head->data;
769 protocols = LIST_SIZE(scan->connections);
770
771 /* Check if it will fit in the live scan list */
772 if ((protocols + projected) > fd_limit)
773 break;
774
775 /*
776 * Scans on the top of the queue were added first, swap the head off the
777 * top of the queue and add it to the tail of the live scan list
778 */
779 node = libopm_list_remove(scanner->queue, scanner->queue->head);
780 libopm_list_add(scanner->scans, node);
781 projected += protocols;
782 }
783 }
784
785 /* check_establish
786 *
787 * Make new connections if there are free file descriptors and connections
788 * to be made.
789 *
790 * Parameters:
791 * scanner: Scanner to check for establish on
792 * Return:
793 * None
794 */
795 static void
796 libopm_check_establish(OPM_T *scanner)
797 {
798 OPM_NODE_T *node1, *node2;
799 OPM_SCAN_T *scan;
800 OPM_CONNECTION_T *conn;
801 unsigned int fd_limit;
802
803 if (LIST_SIZE(scanner->scans) == 0)
804 return;
805
806 fd_limit = *(int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT);
807
808 if (scanner->fd_use >= fd_limit)
809 return;
810
811 LIST_FOREACH(node1, scanner->scans->head)
812 {
813 scan = node1->data;
814
815 LIST_FOREACH(node2, scan->connections->head)
816 {
817 /* Only scan if we have free file descriptors */
818 if (scanner->fd_use >= fd_limit)
819 return;
820
821 conn = node2->data;
822
823 if (conn->state == OPM_STATE_UNESTABLISHED)
824 libopm_do_connect(scanner, scan, conn);
825 }
826 }
827 }
828
829 /* check_closed
830 *
831 * Check for connections which have timed out or are
832 * closed. Connections timed out still need to be closed.
833 *
834 * Remove the connection from the list of connections, free
835 * the connection struct and free the list node. Then if this is
836 * the last connection of the scan, consider the scan completed and
837 * free the scan aswell (and callback that the scan ended).
838 *
839 * Parameters:
840 * scanner: Scanner to check on
841 * Return:
842 * None
843 */
844 static void
845 libopm_check_closed(OPM_T *scanner)
846 {
847 time_t present;
848 int timeout;
849 OPM_NODE_T *node1, *node2, *next1, *next2;
850 OPM_SCAN_T *scan;
851 OPM_CONNECTION_T *conn;
852
853 if (LIST_SIZE(scanner->scans) == 0)
854 return;
855
856 time(&present);
857 timeout = *(int *)libopm_config(scanner->config, OPM_CONFIG_TIMEOUT);
858
859 LIST_FOREACH_SAFE(node1, next1, scanner->scans->head)
860 {
861 scan = node1->data;
862
863 LIST_FOREACH_SAFE(node2, next2, scan->connections->head)
864 {
865 conn = node2->data;
866
867 if (conn->state == OPM_STATE_CLOSED)
868 {
869 if (conn->fd > 0)
870 close(conn->fd);
871
872 scanner->fd_use--;
873
874 libopm_list_remove(scan->connections, node2);
875 libopm_connection_free(conn);
876 libopm_node_free(node2);
877 continue;
878 }
879
880 if (((present - conn->creation) >= timeout) && conn->state != OPM_STATE_UNESTABLISHED)
881 {
882 close(conn->fd);
883 scanner->fd_use--;
884
885 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_TIMEOUT, 0);
886 libopm_list_remove(scan->connections, node2);
887 libopm_connection_free(conn);
888 libopm_node_free(node2);
889 continue;
890 }
891 }
892
893 /*
894 * No more connections left in this scan, let the client know the scan has
895 * ended, then remove the scan from the scanner, and free it up.
896 */
897 if (LIST_SIZE(scan->connections) == 0)
898 {
899 libopm_do_callback(scanner, scan->remote, OPM_CALLBACK_END, 0);
900 libopm_list_remove(scanner->scans, node1);
901 libopm_scan_free(scan);
902 libopm_node_free(node1);
903 }
904 }
905 }
906
907 /* do_connect
908 *
909 * Call socket() and connect() to start a scan.
910 *
911 * Parametsr:
912 * scan: Scan struct containing the connection
913 * conn: Connection to establish
914 * Return:
915 * None
916 */
917 static void
918 libopm_do_connect(OPM_T * scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
919 {
920 opm_sockaddr *bind_ip;
921 struct sockaddr_in *addr; /* Outgoing host */
922 struct sockaddr_in local_addr; /* For binding */
923
924 addr = (struct sockaddr_in *)&(scan->addr.sa4); /* Already have the IP in byte format from opm_scan */
925 addr->sin_family = AF_INET;
926 addr->sin_port = htons(conn->port);
927
928 bind_ip = (opm_sockaddr *)libopm_config(scanner->config, OPM_CONFIG_BIND_IP);
929
930 conn->fd = socket(PF_INET, SOCK_STREAM, 0);
931 scanner->fd_use++; /* Increase file descriptor use */
932
933 if (conn->fd == -1)
934 {
935 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_NOFD);
936 conn->state = OPM_STATE_CLOSED;
937 return;
938 }
939
940 if (bind_ip)
941 {
942 memset(&local_addr, 0, sizeof(local_addr));
943
944 local_addr.sin_addr.s_addr = bind_ip->sa4.sin_addr.s_addr;
945 local_addr.sin_family = AF_INET;
946 local_addr.sin_port = htons(0);
947
948 if (bind(conn->fd, (struct sockaddr *)&(local_addr), sizeof(local_addr)) == -1)
949 {
950 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_BIND);
951 conn->state = OPM_STATE_CLOSED;
952 return;
953 }
954 }
955
956 /* Set socket non blocking */
957 fcntl(conn->fd, F_SETFL, O_NONBLOCK);
958
959 connect(conn->fd, (struct sockaddr *)addr, sizeof(*addr));
960
961 conn->state = OPM_STATE_ESTABLISHED;
962 time(&conn->creation); /* Stamp creation time, for timeout */
963 }
964
965 /* check_poll
966 *
967 * Check sockets for ready read/write
968 *
969 * Parameters:
970 * scanner: Scanner to isolate check on
971 * Return:
972 * None
973 */
974 static void
975 libopm_check_poll(OPM_T *scanner)
976 {
977 OPM_NODE_T *node1, *node2;
978 OPM_SCAN_T *scan;
979 OPM_CONNECTION_T *conn;
980 unsigned int size = 0;
981 static unsigned int ufds_size;
982 static struct pollfd *ufds = NULL;
983
984 /* Grow pollfd array (ufds) as needed */
985 if (ufds_size < (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)))
986 {
987 MyFree(ufds);
988
989 ufds = xcalloc((sizeof *ufds) * (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT)));
990 ufds_size = (*(unsigned int *)libopm_config(scanner->config, OPM_CONFIG_FD_LIMIT));
991 }
992
993 if (LIST_SIZE(scanner->scans) == 0)
994 return;
995
996 LIST_FOREACH(node1, scanner->scans->head)
997 {
998 scan = node1->data;
999
1000 LIST_FOREACH(node2, scan->connections->head)
1001 {
1002 if (size >= ufds_size)
1003 break;
1004
1005 conn = node2->data;
1006
1007 if (conn->state < OPM_STATE_ESTABLISHED ||
1008 conn->state == OPM_STATE_CLOSED)
1009 continue;
1010
1011 ufds[size].events = 0;
1012 ufds[size].revents = 0;
1013 ufds[size].fd = conn->fd;
1014
1015 /* Check for HUNG UP. */
1016 ufds[size].events |= POLLHUP;
1017 /* Check for INVALID FD */
1018 ufds[size].events |= POLLNVAL;
1019
1020 switch (conn->state)
1021 {
1022 case OPM_STATE_ESTABLISHED:
1023 ufds[size].events |= POLLOUT;
1024 break;
1025 case OPM_STATE_NEGSENT:
1026 ufds[size].events |= POLLIN;
1027 break;
1028 }
1029
1030 size++;
1031 }
1032 }
1033
1034 switch (poll(ufds, size, 0))
1035 {
1036 case -1:
1037 /* error in select/poll */
1038 return;
1039 case 0:
1040 /* Nothing to do */
1041 return;
1042
1043 /* Pass pointer to connection to handler. */
1044 }
1045
1046 LIST_FOREACH(node1, scanner->scans->head)
1047 {
1048 scan = node1->data;
1049
1050 LIST_FOREACH(node2, scan->connections->head)
1051 {
1052 conn = node2->data;
1053
1054 for (unsigned int i = 0; i < size; ++i)
1055 {
1056 if ((ufds[i].fd == conn->fd) && (conn->state != OPM_STATE_CLOSED))
1057 {
1058 if (ufds[i].revents & POLLIN)
1059 libopm_do_readready(scanner, scan, conn);
1060 if (ufds[i].revents & POLLOUT)
1061 libopm_do_writeready(scanner, scan, conn);
1062 if (ufds[i].revents & POLLHUP)
1063 libopm_do_hup(scanner, scan, conn);
1064 }
1065 }
1066 }
1067 }
1068 }
1069
1070 /* do_readready
1071 *
1072 * Remote connection is read ready, read the data into a buffer and check it against
1073 * the target_string if neccessary
1074 *
1075 * Parameters:
1076 * scanner: Scanner doing the scan
1077 * scan: Specific scan
1078 * conn: Specific connection in the scan
1079 *
1080 * Return:
1081 * None
1082 */
1083 static void
1084 libopm_do_readready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1085 {
1086 int max_read;
1087 char c;
1088
1089 /*
1090 * If protocol has a specific read function, call that instead of
1091 * reading data from here.
1092 */
1093 if (conn->protocol->read_function)
1094 {
1095 conn->protocol->read_function(scanner, scan, conn);
1096 return;
1097 }
1098
1099 max_read = *(int *)libopm_config(scanner->config, OPM_CONFIG_MAX_READ);
1100
1101 while (1)
1102 {
1103 switch (read(conn->fd, &c, 1))
1104 {
1105 case 0:
1106 libopm_do_hup(scanner, scan, conn);
1107 return;
1108
1109 case -1:
1110 if (errno != EAGAIN)
1111 libopm_do_hup(scanner, scan, conn);
1112 return;
1113
1114 default:
1115 conn->bytes_read++;
1116
1117 if (conn->bytes_read >= max_read)
1118 {
1119 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_ERROR, OPM_ERR_MAX_READ);
1120 conn->state = OPM_STATE_CLOSED;
1121 return;
1122 }
1123
1124 if (c == '\0' || c == '\r')
1125 continue;
1126
1127 if (c == '\n')
1128 {
1129 conn->readbuf[conn->readlen] = '\0';
1130 conn->readlen = 0;
1131
1132 libopm_do_read(scanner, scan, conn);
1133
1134 if (conn->state == OPM_STATE_CLOSED)
1135 return;
1136
1137 continue;
1138 }
1139
1140 if (conn->readlen < READBUFLEN)
1141 conn->readbuf[++(conn->readlen) - 1] = c; /* -1 to pad for null term */
1142 }
1143 }
1144 }
1145
1146 /* do_read
1147 *
1148 * A line of data has been read from the socket, check it against
1149 * target string.
1150 *
1151 *
1152 *
1153 * Parameters:
1154 * scanner: Scanner doing the scan
1155 * scan: Specific scan
1156 * conn: Specific connection in the scan
1157 *
1158 * Return:
1159 * None
1160 */
1161 static void
1162 libopm_do_read(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1163 {
1164 OPM_LIST_T *list;
1165 OPM_NODE_T *node;
1166 char *target_string;
1167
1168 /* Check readbuf against target strings */
1169 list = (OPM_LIST_T *)libopm_config(scanner->config, OPM_CONFIG_TARGET_STRING);
1170
1171 LIST_FOREACH(node, list->head)
1172 {
1173 target_string = node->data;
1174
1175 if (strstr(conn->readbuf, target_string))
1176 {
1177 libopm_do_openproxy(scanner, scan, conn);
1178 break;
1179 }
1180 }
1181 }
1182
1183 /* do_openproxy
1184 *
1185 * An open proxy was found on connection conn. Cleanup the connection and
1186 * call the appropriate callback to let the client know the proxy was found.
1187 *
1188 * Parameters:
1189 * scanner: Scanner doing the scan
1190 * scan: Specific scan
1191 * conn: Specific connection in the scan
1192 *
1193 * Return:
1194 * None
1195 */
1196 static void
1197 libopm_do_openproxy(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1198 {
1199 OPM_REMOTE_T *remote;
1200
1201 remote = scan->remote;
1202
1203 /* Mark the connection for close */
1204 conn->state = OPM_STATE_CLOSED;
1205
1206 /* Call client's open proxy callback */
1207 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_OPENPROXY, 0);
1208 }
1209
1210 /* do_writeready
1211 *
1212 * Remote connection is write ready, call the specific protocol
1213 * function for writing to this socket.
1214 *
1215 * Parameters:
1216 * scanner: Scanner doing the scan
1217 * scan: Specific scan
1218 * conn: Specific connection in the scan
1219 *
1220 * Return:
1221 * None
1222 */
1223 static void
1224 libopm_do_writeready(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1225 {
1226 OPM_PROTOCOL_T *protocol;
1227
1228 protocol = conn->protocol;
1229
1230 /* Call write function for specific protocol */
1231 if (protocol->write_function)
1232 protocol->write_function(scanner, scan, conn);
1233
1234 /* Flag as NEGSENT so we don't have to send data again*/
1235 conn->state = OPM_STATE_NEGSENT;
1236 }
1237
1238 /* do_hup
1239 *
1240 * Connection ended prematurely
1241 *
1242 * Parameters:
1243 * scanner: Scanner doing the scan
1244 * scan: Specific scan
1245 * conn: Specific connection in the scan
1246 * error: OPM_ERR_T containing the error type
1247 * Return:
1248 * None
1249 */
1250 static void
1251 libopm_do_hup(OPM_T *scanner, OPM_SCAN_T *scan, OPM_CONNECTION_T *conn)
1252 {
1253 OPM_REMOTE_T *remote;
1254
1255 remote = scan->remote;
1256
1257 /* Mark the connection for close */
1258 conn->state = OPM_STATE_CLOSED;
1259
1260 libopm_do_callback(scanner, libopm_setup_remote(scan->remote, conn), OPM_CALLBACK_NEGFAIL, 0);
1261 }
1262
1263 /* do_callback
1264 *
1265 * Call callback
1266 *
1267 * Parameters:
1268 * scanner: scanner remote is on
1269 * remote: remote callback is for
1270 * type: callback type
1271 * var: optional var passed back (error codes, etc )
1272 * Return:
1273 * None
1274 */
1275 static void
1276 libopm_do_callback(OPM_T *scanner, OPM_REMOTE_T *remote, int type, int var)
1277 {
1278 /* Callback is out of range */
1279 if (type < 0 || type >= CBLEN)
1280 return;
1281
1282 if (scanner->callbacks[type].func)
1283 (scanner->callbacks[type].func)(scanner, remote, var, scanner->callbacks[type].data);
1284 }
1285
1286 /* setup_remote
1287 *
1288 * Setup an OPM_REMOTE_T with information from an OPM_CONNECTION_T
1289 * for callback
1290 *
1291 * Parameters:
1292 * remote, conn
1293 *
1294 * Return:
1295 * remote
1296 */
1297 static OPM_REMOTE_T *
1298 libopm_setup_remote(OPM_REMOTE_T *remote, OPM_CONNECTION_T *conn)
1299 {
1300 remote->port = conn->port;
1301 remote->bytes_read = conn->bytes_read;
1302 remote->protocol = conn->protocol->type;
1303
1304 return remote;
1305 }

Properties

Name Value
svn:eol-style native
svn:keywords Id