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