; c o d e r e d  --  Absorb and log attacks on TCP Port 80.
;
; Works for any HTTP (TCP port 80) attack: Code Red, Nimba, etc.
; Requires privilege in UNIX but not in Windows, and also requires
; that no other process is listening on por 80.
;
; F. da Cruz, Columbia University, August 2001.
; Requires C-Kermit 8.0 Beta.03 or later or concurrent K95 version.
;
.truncate := 0                          ; 1 = truncate log records at 79 cols.
.\%n = 0                                ; Event count
.start := \fcvtdate()                   ; Start date-time

if < \v(version) 800200 exit 1 Fatal - C-Kermit 8.0 required.

define ON_CTRLC {                       ; Ctrl-C trap
    echo Connections: \%n in \fdiffdate(now,\m(start))
}

if K-95 {                               ; K95: Appropriate window color
    set command color white red
    cls
}

set input echo off                      ; Input is logged to a file
set tcp reverse-dns off                 ; For accurate source reporting
while true {
    echo "-----------------"
    .stamp := \fcvtdate()
    xecho \m(stamp)...        
    set host * 80                       ; Wait for incoming HTTP connection
    if fail {
        echo Net Open Failure: \v(errstring)
        if ( = \v(errno) 13 || = \v(errno) 48 ) exit 1
        hangup
        continue
    }
    clear input                         ; Capture the attack string
    input 8 \10                         ; (terminate at linefeed = ASCII 10)
    increment \%n                                 ; Count this probe
    echo \flpad(\%n,4). \m(stamp): \v(line)       ; Log to screen
    if ( = 0 \fverify(0123456789.,\v(line)) ) {   ; Have IP address
	.addr := \v(line)
	.name := \faddr2name(\m(addr))            ; Lookup name in DNS
    } else {                                      ; Have IP name
	.name := \v(line)
	.addr := \fname2addr(\m(name))            ; Get its address
    }
    hangup                                        ; Close connection quickly

    .record := \m(stamp): \m(name) [\m(addr)] "\ftrim(\v(input))"
    if \m(truncate) if > \flen(\m(record)) 79 .record := \s(record[1:76]).."

    set flag off
    for \%i 1 3 1 {                               ; Write to log
        fopen /append \%c codered.log             ; It might be busy
        if fail {
            echo LOG APPEND FAILURE: \f_errmsg()
            sleep \%i
            continue
        }
        fwrite /line \%c \m(record)
        if success set flag on
        fclose \%c
        if flag break
    }
    if not flag echo RECORD LOST: \m(record)        
}
