This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats-opsb/proxy.c

378 lines
12 KiB
C

/* NeoStats - IRC Statistical Services Copyright (c) 1999-2004 NeoStats Group Inc.
** Copyright (c) 1999-2004 Adam Rutter, Justin Hammond
** http://www.neostats.net/
**
** Portions Copyright (c) 2004 Erik Fears
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
** USA
**
** NeoStats CVS Identification
** $Id$
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include "neostats.h"
#include "opsb.h"
#include "opm.h"
#include "opm_types.h"
#include "opm_error.h"
int proxy_connect(unsigned long ipaddr, int port, char *who);
void open_proxy(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused);
void negfailed(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused);
void timeout(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused);
void scan_end(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused);
void scan_error(OPM_T *scanner, OPM_REMOTE_T *remote, int opmerr, void *unused);
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
OPM_T *scanner;
proxy_type proxy_list[] = {
{ OPM_TYPE_HTTP, "HTTP" },
{ OPM_TYPE_SOCKS4, "SOCKS4" },
{ OPM_TYPE_SOCKS5, "SOCKS5" },
{ OPM_TYPE_WINGATE, "WINGATE" },
{ OPM_TYPE_ROUTER, "ROUTER"},
{ OPM_TYPE_HTTPPOST, "HTTPPOST" },
{ 0, "" }
};
char *type_of_proxy(int type) {
return proxy_list[type-1].name;
}
int get_proxy_by_name(const char *name) {
int i;
for (i=0; proxy_list[i].type != 0; i++) {
if (!strcasecmp(proxy_list[i].name, name)) {
return proxy_list[i].type;
}
}
return 0;
}
void add_port(int type, int port) {
opm_addtype(scanner, type, port);
}
int load_ports() {
char *portname, **av;
int i, j, ac, ok;
port_list *prtlst;
lnode_t *pn;
ok = 0;
for (i = 0; proxy_list[i].type != 0; i++) {
if (GetConf((void *)&portname, CFGSTR, proxy_list[i].name) <= 0) {
nlog(LOG_WARNING, LOG_MOD, "Warning, No Ports defined for Protocol %s", proxy_list[i].name);
} else {
ac = split_buf(portname, &av, 0);
for (j = 0; j < ac; j++) {
if (atoi(av[j]) == 0) {
nlog(LOG_WARNING, LOG_MOD, "Invalid Port %s for Proxy Type %s", av[j], proxy_list[i].name);
continue;
}
if (list_isfull(opsb.ports)) {
nlog(LOG_MOD, LOG_WARNING, "Ports List is Full.");
break;
}
prtlst = malloc(sizeof(port_list));
prtlst->type = proxy_list[i].type;
prtlst->port = atoi(av[j]);
prtlst->noopen = 0;
pn = lnode_create(prtlst);
list_append(opsb.ports, pn);
nlog(LOG_DEBUG1, LOG_MOD, "Added Port %d for Protocol %s", prtlst->port, proxy_list[i].name);
ok = 1;
}
free(av);
free(portname);
}
}
return ok;
}
int init_libopm() {
lnode_t *pn;
port_list *pl;
scanner = opm_create();
/* setup the callbacks to our code */
opm_callback(scanner, OPM_CALLBACK_OPENPROXY, &open_proxy, NULL);
opm_callback(scanner, OPM_CALLBACK_NEGFAIL, &negfailed, NULL);
opm_callback(scanner, OPM_CALLBACK_TIMEOUT, &timeout, NULL);
opm_callback(scanner, OPM_CALLBACK_END, &scan_end, NULL);
opm_callback(scanner, OPM_CALLBACK_ERROR, &scan_error, NULL);
/* max number of socks we allow */
opm_config(scanner, OPM_CONFIG_FD_LIMIT, &opsb.socks);
/* host to try to connect to */
opm_config(scanner, OPM_CONFIG_SCAN_IP, opsb.targethost);
/* port to try to connect to */
opm_config(scanner, OPM_CONFIG_SCAN_PORT, &opsb.targetport);
/* string to look for */
opm_config(scanner, OPM_CONFIG_TARGET_STRING, opsb.lookforstring);
/* also look for throttle messages */
opm_config(scanner, OPM_CONFIG_TARGET_STRING, "ERROR :Trying to reconnect too fast");
/* timeout */
opm_config(scanner, OPM_CONFIG_TIMEOUT, &opsb.timeout);
/* max bytes read */
opm_config(scanner, OPM_CONFIG_MAX_READ, &opsb.maxbytes);
/* read the proxy types directly from keeper :) */
pn = list_first(opsb.ports);
while (pn) {
pl = lnode_get(pn);
opm_addtype(scanner, pl->type, pl->port);
pn = list_next(opsb.ports, pn);
}
/* add the sock poll interface into neo */
add_sockpoll("libopm_before_poll", "libopm_after_poll", "opsb", "opsb", scanner);
return 1;
}
void open_proxy(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused)
{
#if 0
FILE *fp;
#endif
scaninfo *scandata;
SET_SEGV_LOCATION();
scandata = remote->data;
if (scandata->doneban == 1)
return;
++opsb.open;
nlog(LOG_CRITICAL, LOG_MOD, "OPSB: Banning %s (%s) for Open Proxy - %s(%d)", scandata->who, remote->ip, type_of_proxy(remote->protocol), remote->port);
chanalert(s_opsb, "Banning %s (%s) for Open Proxy - %s(%d)", scandata->who, remote->ip, type_of_proxy(remote->protocol), remote->port);
globops(s_opsb, "Banning %s (%s) for Open Proxy - %s(%d)", scandata->who, remote->ip, type_of_proxy(remote->protocol), remote->port);
if (scandata->u) prefmsg(scandata->u->nick, s_opsb, "Banning %s (%s) for Open Proxy - %s(%d)", scandata->who, remote->ip, type_of_proxy(remote->protocol), remote->port);
if (opsb.doban) sakill_cmd(remote->ip, "*", s_opsb, opsb.bantime, "Open Proxy found on your host. %s(%d)", type_of_proxy(remote->protocol), remote->port);
#if 0
/* write out to a logfile */
if ((fp = fopen("logs/openproxies.log", "a")) == NULL) return;
fprintf(fp, "%d:%s:%s\n", remote->protocol, remote->ip, "empty");
fclose(fp);
#endif
/* no point continuing the scan if they are found open */
scandata->state = GOTOPENPROXY;
opm_end(scanner, remote);
#if 0
if (scandata->dnsstate == OPMLIST) {
scandata->doneban = 1;
nlog(LOG_CRITICAL, LOG_MOD, "OPSB: Banning %s (%s) as its listed in %s", scandata->who, inet_ntoa(scandata->ipaddr), opsb.opmdomain);
chanalert(s_opsb, "Banning %s (%s) as its listed in %s", scandata->who, inet_ntoa(scandata->ipaddr), opsb.opmdomain);
globops(s_opsb, "Banning %s (%s) as its listed in %s", scandata->who, inet_ntoa(scandata->ipaddr), opsb.opmdomain);
if (scandata->u) prefmsg(scandata->u->nick, s_opsb, "Banning %s (%s) as its listed in %s", scandata->who, inet_ntoa(scandata->ipaddr), opsb.opmdomain);
sakill_cmd(inet_ntoa(scandata->ipaddr), "*", s_opsb, opsb.bantime, "Your host is listed as an Open Proxy. Please visit the following website for more info: www.blitzed.org/proxy?ip=%s", inet_ntoa(scandata->ipaddr));
}
#endif
}
void negfailed(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused) {
scaninfo *scandata;
SET_SEGV_LOCATION();
scandata = remote->data;
if (scandata->u) {
prefmsg(scandata->u->nick, s_opsb, "Negitiation failed for protocol %s(%d)", type_of_proxy(remote->protocol), remote->port);
}
}
void timeout(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused) {
scaninfo *scandata;
SET_SEGV_LOCATION();
scandata = remote->data;
if (scandata->u) {
prefmsg(scandata->u->nick, s_opsb, "Timeout on Protocol %s(%d)", type_of_proxy(remote->protocol), remote->port);
}
}
void scan_end(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *unused) {
scaninfo *scandata;
SET_SEGV_LOCATION();
scandata = remote->data;
if (scandata->u) {
prefmsg(scandata->u->nick, s_opsb, "scan finished on %s", scandata->who);
}
opm_remote_free(remote);
if (scandata->state != GOTOPENPROXY) scandata->state = FIN_SCAN;
check_scan_free(scandata);
}
void scan_error(OPM_T *scanner, OPM_REMOTE_T *remote, int opmerr, void *unused) {
scaninfo *scandata;
SET_SEGV_LOCATION();
scandata = remote->data;
if (scandata->u) {
if (opmerr == 5) {
prefmsg(scandata->u->nick, s_opsb, "Closed Proxy on Protocol %s (%d)", type_of_proxy(remote->protocol), remote->port);
} else {
prefmsg(scandata->u->nick, s_opsb, "scan error on Protocol %s (%d) - %d", type_of_proxy(remote->protocol), remote->port, opmerr);
}
}
}
int do_status(User *u, char **av, int ac)
{
lnode_t *node;
scaninfo *scandata;
SET_SEGV_LOCATION();
prefmsg(u->nick, s_opsb, "Proxy Results:");
prefmsg(u->nick, s_opsb, "Hosts Scanned: %d Hosts found Open: %d Exceptions %d", opsb.scanned, opsb.open, (int)list_count(exempt));
prefmsg(u->nick, s_opsb, "Cache Entries: %d", (int)list_count(cache));
prefmsg(u->nick, s_opsb, "Cache Hits: %d", opsb.cachehits);
prefmsg(u->nick, s_opsb, "Blacklist Hits: %d", opsb.opmhits);
#if 0
for (i = 0; i < NUM_PROXIES; i++) {
prefmsg(u->nick, s_opsb, "Proxy %s (%d) Found %d Open %d", proxy_list[i].type, proxy_list[i].port, proxy_list[i].nofound, proxy_list[i].noopen);
}
#endif
prefmsg(u->nick, s_opsb, "Currently Scanning %d Proxies (%d in queue):", (int)list_count(opsbl), (int)list_count(opsbq));
node = list_first(opsbl);
while (node) {
scandata = lnode_get(node);
if (scandata->u)
prefmsg(u->nick, s_opsb, "Scanning %s by request of %s", scandata->lookup, scandata->u->nick);
else
prefmsg(u->nick, s_opsb, "Scanning %s (%s) - %s", scandata->lookup, inet_ntoa(scandata->ipaddr), scandata->who);
switch(scandata->dnsstate) {
case REPORT_DNS:
prefmsg(u->nick, s_opsb, "Looking up IP Address");
break;
case DO_DNS_HOST_LOOKUP:
prefmsg(u->nick, s_opsb, "Looking up IP address for Scan");
break;
case DO_OPM_LOOKUP:
prefmsg(u->nick, s_opsb, "Looking up DNS blacklist");
break;
case OPMLIST:
prefmsg(u->nick, s_opsb, "Host is listed in %s", opsb.opmdomain);
break;
case NOOPMLIST:
prefmsg(u->nick, s_opsb, "Host is Not listed in %s", opsb.opmdomain);
break;
default:
prefmsg(u->nick, s_opsb, "Unknown State (DNS)");
}
switch(scandata->state) {
case DOING_SCAN:
prefmsg(u->nick, s_opsb, "Scanning for Open Proxies");
break;
case GOTOPENPROXY:
prefmsg(u->nick, s_opsb, "Contains an Open Proxy");
break;
default:
prefmsg(u->nick, s_opsb, "Unknown State (Scan)");
}
node = list_next(opsbl, node);
}
return 0;
}
void start_proxy_scan(lnode_t *scannode) {
scaninfo *scandata;
OPM_REMOTE_T *remote;
int i;
SET_SEGV_LOCATION();
scandata = lnode_get(scannode);
/* if we are configured not to scan, and its not a request, bail out */
if ((opsb.doscan == 0) && (!scandata->u)) {
scandata->state = FIN_SCAN;
check_scan_free(scandata);
return;
}
if (scandata->u) chanalert(s_opsb, "Starting proxy scan on %s (%s) by Request of %s", scandata->who, scandata->lookup, scandata->u->nick);
scandata->state = DOING_SCAN;
/* this is so we can timeout scans */
scandata->started = time(NULL);
if ((opsb.doscan == 1) || (scandata->u)) {
remote = opm_remote_create(inet_ntoa(scandata->ipaddr));
remote->data = scandata;
switch(i = opm_scan(scanner, remote))
{
case OPM_SUCCESS:
nlog(LOG_DEBUG2, LOG_MOD, "Starting Scan on %s", inet_ntoa(scandata->ipaddr));
break;
case OPM_ERR_BADADDR:
nlog(LOG_WARNING, LOG_MOD, "Scan of %s %s Failed. Bad Address?", scandata->who, inet_ntoa(scandata->ipaddr));
opm_remote_free(remote);
scandata->state = FIN_SCAN;
check_scan_free(scandata);
}
}
}
void check_scan_free(scaninfo *scandata) {
lnode_t *scannode;
if ((scandata->dnsstate == DO_OPM_LOOKUP) || (scandata->dnsstate == DO_DNS_HOST_LOOKUP) || (scandata->state == DOING_SCAN)) {
nlog(LOG_DEBUG2, LOG_MOD, "Not Cleaning up Scaninfo for %s yet. Scan hasn't completed", scandata->who);
return;
}
if ((scandata->dnsstate != OPMLIST) && (scandata->state != GOTOPENPROXY)) {
addtocache(scandata->ipaddr.s_addr);
nlog(LOG_DEBUG1, LOG_MOD, "%s's Host is clean. Adding to Cache", scandata->who);
}
scannode = list_find(opsbl, scandata->who, findscan);
if (scannode) {
nlog(LOG_DEBUG1, LOG_MOD, "%s scan finished. Cleaning up", scandata->who);
list_delete(opsbl, scannode);
lnode_destroy(scannode);
scandata->u = NULL;
free(scandata);
} else {
nlog(LOG_WARNING, LOG_MOD, "Damn, Can't find ScanNode %s. Something is fubar", scandata->who);
}
checkqueue();
}