############################
### PortCheck.tcl	 ###
### Version 1.4		 ###
### By Wcc		 ###
### irc.dal.net		 ###
############################

##########################################################################################
## This script scans up to 2 ports on join, and scans a port via a pub or dcc command.  ##
## NOTE: This script uses the +E flag to exempt a nick from scanning.                   ##
##########################################################################################

##############
## COMMANDS ##
########################################################
## DCC ## .portcheck <host/ip> <port>		      ##	
######### Checks weather or not the specified port is ##		
######### is open on the specified host or ip.        ##			
########################################################
## PUB ## !checknick <nick> <port>		      ##
######### Checks weather or not the spefified port is ##
######### open on the specified nicks host.	      ##
######### ------------------------------------------- ##
######### !checkhost <host/ip> <port>		      ##
######### Checks weather or not the specified port is ##
######### open on the specified host or ip	      ##
########################################################

#############################################################
## Just load the script, set the variables, and rehash.    ##
#############################################################

#################
# Scan on join? #
#################

set scanonjoin "0"

################################################
# What channel would you like to scan on join? #
################################################

set soxchan "#channel"


####################################
# Set ports you scan on join here. #
####################################

set soxport1 "23"
set soxport2 "1080"

#####################################################
# Set flag required for public portscans on a nick. #
####################################################

set pub_scan_flag "+o"

#########################################################################################
# Set flag required for public portscans on a host. Hosts are not exempt from scanning. #
#########################################################################################

set pub_host_scan_flag "+o"

########################################
# Set flag required for dcc portscans. #
########################################

set dcc_scan_flag "+o|+o $soxchan"

####################
# Code begins here #
####################

bind join - "$soxchan *!*@*" soxportcheck1
bind join - "$soxchan *!*@*" soxportcheck2
bind pub $pub_scan_flag|$pub_scan_flag !checknick pubnickscanport
bind pub $pub_host_scan_flag|$pub_host_scan_flag !checkhost pubhostscanport
bind dcc $dcc_scan_flag portcheck dcchostscanport

proc soxportcheck1 {nick uhost hand chan} {
	global botnick soxport1 soxport2 soxchan scanonjoin
	if {$scanonjoin} {
		if {($soxport1 != "") && ($soxchan != "")} {
			if {(![matchattr $hand +E|+E $soxchan])} {
				set host2scan [lindex [split $uhost @] 1]
				set port1found ""
				catch {socket $host2scan $soxport1} port1sock
				if {([string range $port1sock 0 3] == "sock") && ([lindex $port1sock 1] == "")} {
					close $port1sock
					set port1found "1"
				}
				if {$port1found == ""} {
					set port1found "0"
				}
				if {$port1found} {
					putlog "PORTCHECK: Bad port found: $nick $banmask in $chan"
						if {([botisop $soxchan])} {
						foreach u [chanlist $chan] {
							if {[isop $u $chan]} {
								putserv "NOTICE $u :PORTCHECK: $nick \($uhost\) Has an open SOCKS proxy on $soxport1 - detected on $chan"
							}
						}
					}
				}
			}
		}
	}
}
proc soxportcheck2 {nick uhost hand chan} {
	global botnick soxport1 soxport2 soxchan scanonjoin
	if {$scanonjoin} {
		if {($soxport2 != "") && ($soxchan != "")} {
			if {(![matchattr $hand +E|+E])} {
				set host2scan [lindex [split $uhost @] 1]
				set port1found ""
				catch {socket $host2scan $soxport2} port1sock
				if {([string range $port1sock 0 3] == "sock") && ([lindex $port1sock 1] == "")} {
					close $port1sock
					lappend port1found "1"
				}
				if {$port1found == ""} {
					set port1found "0"
				}
				if {$port1found} {
					putlog "PORTCHECK: Bad port found: $nick $banmask in $chan"
					if {([botisop $soxchan])} {
						foreach u [chanlist $chan] {
							if {[isop $u $chan]} {
								putserv "NOTICE $u :PORTCHECK: $nick \($uhost\) Has an open  proxy on $soxport2 - detected on $chan."
							}
						}
					}
				}
			}
		}
	}
}

proc pubnickscanport {nick uhost hand chan text} {
	global botnick
	if {([lindex $text 0] == "") || ([lindex $text 1] == "")} {
		putserv "NOTICE $nick :PORTCHECK: Usage: !checknick <nick> <port>"
	} elseif {(![onchan [lindex $text 0] $chan])} {
		putserv "NOTICE $nick :[lindex $text 0] is not on $chan."
	} else {
		set target [lindex [split [getchanhost [lindex $text 0]] @] 1]
		if {([matchattr [nick2hand [lindex $text 0]] +E|+E])} {
			putserv "NOTICE $nick :PORTCHECK: [lindex $text 0] is exempt from scanning."
		} else {
			set port [lindex $text 1]
			set port1found ""
			catch {socket $target $port} port1sock
			if {([string range $port1sock 0 3] == "sock") && ([lindex $port1sock 1] == "")} {
				close $port1sock
				lappend port1found "1"
			}
			if {$port1found == ""} {
				set port1found "0"
			}
			if {($port1found)} {
				putserv "NOTICE $nick :PORTCHECK: Port $port is open on $target."
			} elseif {(!$port1found)} {
				putserv "NOTICE $nick :PORTCHECK: Port $port is closed $target."
		
			}
		}
	}
}
proc pubhostscanport {nick uhost hand chan text} {
	global botnick
	if {([lindex $text 0] == "") || ([lindex $text 1] == "")} {
		putserv "NOTICE $nick :PORTCHECK: Usage: !checkhost <host/ip> <port>"
	} else {
		set target [lindex $text 0]
		set port [lindex $text 1]
		set port1found ""
		catch {socket $target $port} port1sock
		if {([string range $port1sock 0 3] == "sock") && ([lindex $port1sock 1] == "")} {
			close $port1sock
			lappend port1found "1"
		}
		if {$port1found == ""} {
			set port1found "0"
		}
		if {($port1found)} {
			putserv "NOTICE $nick :PORTCHECK: Port $port is open on $target."
		} elseif {(!$port1found)} {
			putserv "NOTICE $nick :PORTCHECK: Port $port is closed on $target."
	
		}
	}
}

proc dcchostscanport {hand idx text} {
	global botnick
	if {([lindex $text 0] == "") || ([lindex $text 1] == "")} {
		putidx $idx "PORTCHECK: Usage: .portcheck <host/ip> <port>"
	} else {
		set target [lindex $text 0]
		set port [lindex $text 1]
		set port1found ""
		catch {socket $target $port} port1sock
		if {([string range $port1sock 0 3] == "sock") && ([lindex $port1sock 1] == "")} {
			close $port1sock
			lappend port1found "1"
		}
		if {$port1found == ""} {
			set port1found "0"
		}
		if {($port1found)} {
			putidx $idx "PORTCHECK: Port $port is open on $target."
		} elseif {(!$port1found)} {
			putidx $idx "PORTCHECK: Port $port is closed on $target."
	
		}
	}
}

putlog "PORTCHECK: PortCheck.tcl Version 1.4 by wcc is loaded."
if {$scanonjoin} {
	putlog "PORTCHECK: Scanning users joining $soxchan for open ports $soxport1 or $soxport2."
}