// Lets use some libs to help us out.
const fs = require('fs')
Tail = require('tail').Tail;

sshTail = new Tail("/var/log/auth.log");
const cmd = require('cmd-promise')

// Setting up our main storage logic - for now this program does not use a database system.
let serverStatusCount = 0;
let attackData = []
let blockedIPs = []
let ipToBlock

console.log("Welcome to the security notification system secuNotify by Discord-Linux!");
console.log("We currently will notify you about login events, such as failed logins and successful logins.");

// Setting up our notification function - This allows us to direct message our user.
function notify(message) {
    const { spawn } = require('child_process');
    const notif = spawn('notif', [message]);

    notif.stdout.on('data', (data) => {
        console.log(`stdout: ${data}`);
    });

    notif.stderr.on('data', (data) => {
        console.error(`stderr: ${data}`);
    });

    notif.on('close', (code) => {
        console.log(`Code: ${code} - Continuing to monitor`);
    });
}

function listenAuthLog(logLocation) {
    sshTail.on("line", function (info) {
        let infoString = info.toString();

        if (infoString.includes("Failed password for root")) {
            console.log(info);
            notify("secuNotify Service Alert: \n" + info);
        }

        if (infoString.includes("Accepted password for")) {
            console.log(info);
            notify("secuNotify Service Alert: \n" + info + "This does mean that someone (Maybe you) has logged in successfully!");
        }
        if (infoString.includes("Invalid user")) {
            console.log(info);
            notify("secuNotify Service Alert: \n" + info + "This means that someone (Maybe you) has tried to login with an invalid username!");
        }
    })

        ;
}

function listenWPLog(logLocation) {
    // Check to see if we are a wordpress user, if so, activate the wordpress notification service 
    try {
        if (fs.existsSync("/var/www/html/wp-config.php")) {
            console.log("We are a wordpress user, activating wordpress notification service");

            // Tail Logs section, if we have a lot, it will have a listeniner below.
            wpTail.on("line", function (info) {

                // Convert Data to String
                let requestInfo = info.toString()
                // FIND IP Address from this request
                var ipRegEx = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/; // RegEx IPAddress Format
                var ipRegExMatched = requestInfo.match(ipRegEx); // Set up our match
                let remoteIP = ipRegExMatched[0] // Set our var

                // // Grab the whitelist
                // let whitelistData = process.env.WHITELIST
                // let whitelist = whitelistData.split(",")

                // // If an IP is found to be in the whitelist, return as to do nothing. 
                // for (const [key, value] of Object.entries(whitelist)) {
                //     if (value === remoteIP) return
                // }

                // Filtering out any server-status requests - These are annoying. 
                if (requestInfo.includes("server-status")) {
                    // Add to the server status count so we may keep track of these requests. 
                    serverStatusCount++
                    // Lets return the data as no not proceed with any further code, as it is not needed.
                    // We return to stdout here to update the cli without adding a new line line a clock
                    return process.stdout.write("Server Status Count: " + serverStatusCount + "\r");
                }

                // If request contans wp-login lets process its request
                if (requestInfo.includes("wp-login.php") && requestInfo.includes("POST")) {
                    // Lets start the process of logging attack attempts to determine request intent.
                    // Over the threshhold here will automatically CSF D the IP Address.
                    // In this simple version, we will just log each IP Address as they come in within an array
                    // We will then roll and count this array after each detection to determine the IPs intent.
                    console.log("---------\nWP LOGIN REQUEST DETECTED!\n---------")
                    console.log(info + "\n----------");
                    attackData.push(remoteIP)

                    // Lets count the attack data per IP Address to ensure its logged properly.
                    var counts = {};

                    // For each IP Address recorded into the main attackData array, count them and see outmany bad requests they have made.
                    attackData.forEach(function (x) {
                        // Add a point for each entry
                        counts[x] = (counts[x] || 0) + 1;
                        // 
                        for ([key, value] of Object.entries(counts)) {
                            // If the count has hit the blockON Count we start the blocking process

                            if (counts[x] === 5) {
                                console.log("counts: " + counts[x])
                                counts = {}

                                
                                // Preserve the key for later blocklist addition
                                ipToBlock = key

                                // Check the already blocked IPs - If the remoteIP is in the list do nothing
                                if (blockedIPs.includes(key)) {
                                    return

                                } else {
                                    // The remoteIP is not listed, lets add it.
                                    blockedIPs.push(ipToBlock)
                                    // Let the log know we are blocking the IP
                                    console.log("Starting to block bad IP")
                                    // Run the block, wait for the promise - Requests are still going on
                                    cmd(`/var/tools/firewallctl ` + key + " WP-Login Brute Force Blocked Via secuNotify").then(out => {
                                        notify("secuNotify Service Alert:\n " + key + " has been blocked for 5 bad wordpress login attempts!");

                                        // The block has finished - remoteIP no longer has access
                                    }).catch(err => {
                                        // IF we see an error, give its output
                                        console.log('CSF Error: ', err)
                                    }).then(out2 => {
                                        // Set IPBLOCK to null for a reset and start scanning for new attacks
                                        ipToBlock = null;
                                        console.log("Attack Stopped, Looking for new attacks....")
                                        // Live view of the counts
                                    })
                         

                                    if (blockedIPs.length == 0) {
                                        console.log("No IPs have been blocked yet.")
                                    } else {
                                        console.log("Blocked IP List (Since Service start): " + blockedIPs)
                                    }
                                }
                            }
                        }

                    });


                }
            })
        }
    } catch (err) {
        console.log(err)
    }
}


listenAuthLog("/var/log/auth.log")

fs.exists("/var/log/apache2/access.log", function (isExist) {
    if (isExist) {
        wpTail = new Tail("/var/log/apache2/access.log");
        listenWPLog("/var/log/apache2/access.log")
    } else {
        console.log("ApacheHTTP Server is not installed, not enabling WP protection.");
    }
});





