Files
Paradise/code/modules/admin/ipintel.dm
AffectedArc07 56752b0e78 SShttp + SSdiscord | ASYNCHRONOUS STUFF IN BYOND! (#14762)
* SShttp + SSdiscord | ASYNCHRONOUS STUFF IN BYOND!

* Cleanup

* HTTP Callback example

* Fixes rust instability

* More refactors

* This works

* The sanitizer (Now worth £3000)

* New configs + other stuff

* Lets give this a shot

* Farie changes

* Mentor support

* Farie fixes
2020-11-07 11:57:47 -05:00

230 lines
7.7 KiB
Plaintext

/datum/ipintel
var/ip
var/intel = 0
var/cache = FALSE
var/cacheminutesago = 0
var/cachedate = ""
var/cacherealtime = 0
/datum/ipintel/New()
cachedate = SQLtime()
cacherealtime = world.realtime
/datum/ipintel/proc/is_valid()
. = FALSE
if(intel < 0)
return
if(intel <= config.ipintel_rating_bad)
if(world.realtime < cacherealtime + (config.ipintel_save_good HOURS))
return TRUE
else
if(world.realtime < cacherealtime + (config.ipintel_save_bad HOURS))
return TRUE
/proc/get_ip_intel(ip, bypasscache = FALSE, updatecache = TRUE)
var/datum/ipintel/res = new()
ip = sanitizeSQL(ip)
res.ip = ip
. = res
if(!ip || !config.ipintel_email || !SSipintel.enabled)
return
if(!bypasscache)
var/datum/ipintel/cachedintel = SSipintel.cache[ip]
if(cachedintel && cachedintel.is_valid())
cachedintel.cache = TRUE
return cachedintel
if(GLOB.dbcon.IsConnected())
var/rating_bad = config.ipintel_rating_bad
var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery({"
SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW())
FROM [format_table_name("ipintel")]
WHERE
ip = INET_ATON('[ip]')
AND ((
intel < [rating_bad]
AND
date + INTERVAL [config.ipintel_save_good] HOUR > NOW()
) OR (
intel >= [rating_bad]
AND
date + INTERVAL [config.ipintel_save_bad] HOUR > NOW()
))
"})
if(!query_get_ip_intel.Execute())
qdel(query_get_ip_intel)
return
if(query_get_ip_intel.NextRow())
res.cache = TRUE
res.cachedate = query_get_ip_intel.item[1]
res.intel = text2num(query_get_ip_intel.item[2])
res.cacheminutesago = text2num(query_get_ip_intel.item[3])
res.cacherealtime = world.realtime - (text2num(query_get_ip_intel.item[3])*10*60)
SSipintel.cache[ip] = res
qdel(query_get_ip_intel)
return
qdel(query_get_ip_intel)
res.intel = ip_intel_query(ip)
if(updatecache && res.intel >= 0)
SSipintel.cache[ip] = res
if(GLOB.dbcon.IsConnected())
var/DBQuery/query_add_ip_intel = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()")
query_add_ip_intel.Execute()
qdel(query_add_ip_intel)
/proc/ip_intel_query(ip, var/retryed=0)
. = -1 //default
if(!ip)
return
if(SSipintel.throttle > world.timeofday)
return
if(!SSipintel.enabled)
return
// Do not refactor this to use SShttp, because that requires the subsystem to be firing for requests to be made, and this will be triggered before the MC has finished loading
var/list/http[] = world.Export("http://[config.ipintel_domain]/check.php?ip=[ip]&contact=[config.ipintel_email]&format=json&flags=b")
if(http)
var/status = text2num(http["STATUS"])
if(status == 200)
var/response = json_decode(file2text(http["CONTENT"]))
if(response)
if(response["status"] == "success")
var/intelnum = text2num(response["result"])
if(isnum(intelnum))
return text2num(response["result"])
else
ipintel_handle_error("Bad intel from server: [response["result"]].", ip, retryed)
if(!retryed)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Bad response from server: [response["status"]].", ip, retryed)
if(!retryed)
sleep(25)
return .(ip, 1)
else if(status == 429)
ipintel_handle_error("Error #429: We have exceeded the rate limit.", ip, 1)
return
else
ipintel_handle_error("Unknown status code: [status].", ip, retryed)
if(!retryed)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Unable to connect to API.", ip, retryed)
if(!retryed)
sleep(25)
return .(ip, 1)
/proc/ipintel_handle_error(error, ip, retryed)
if(retryed)
SSipintel.errors++
error += " Could not check [ip]. Disabling IPINTEL for [SSipintel.errors] minute[( SSipintel.errors == 1 ? "" : "s" )]"
SSipintel.throttle = world.timeofday + (2 * SSipintel.errors MINUTES)
else
error += " Attempting retry on [ip]."
log_ipintel(error)
/proc/log_ipintel(text)
log_game("IPINTEL: [text]")
log_debug("IPINTEL: [text]")
/proc/ipintel_is_banned(t_ckey, t_ip)
if(!config.ipintel_email)
return FALSE
if(!config.ipintel_whitelist)
return FALSE
if(!GLOB.dbcon.IsConnected())
return FALSE
if(!ipintel_badip_check(t_ip))
return FALSE
if(vpn_whitelist_check(t_ckey))
return FALSE
return TRUE
/proc/ipintel_badip_check(target_ip)
var/rating_bad = config.ipintel_rating_bad
if(!rating_bad)
log_debug("ipintel_badip_check reports misconfigured rating_bad directive")
return FALSE
var/valid_hours = config.ipintel_save_bad
if(!valid_hours)
log_debug("ipintel_badip_check reports misconfigured ipintel_save_bad directive")
return FALSE
target_ip = sanitizeSQL(target_ip)
rating_bad = sanitizeSQL(rating_bad)
valid_hours = sanitizeSQL(valid_hours)
var/check_sql = {"SELECT * FROM [format_table_name("ipintel")] WHERE ip = INET_ATON('[target_ip]') AND intel >= [rating_bad] AND (date + INTERVAL [valid_hours] HOUR) > NOW()"}
var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery(check_sql)
if(!query_get_ip_intel.Execute())
log_debug("ipintel_badip_check reports failed query execution")
qdel(query_get_ip_intel)
return FALSE
if(!query_get_ip_intel.NextRow())
qdel(query_get_ip_intel)
return FALSE
qdel(query_get_ip_intel)
return TRUE
/proc/vpn_whitelist_check(target_ckey)
if(!config.ipintel_whitelist)
return FALSE
var/target_sql_ckey = ckey(target_ckey)
var/DBQuery/query_whitelist_check = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
if(!query_whitelist_check.Execute())
var/err = query_whitelist_check.ErrorMsg()
log_debug("SQL ERROR on proc/vpn_whitelist_check for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
return FALSE
if(query_whitelist_check.NextRow())
return TRUE // At least one row in the whitelist names their ckey. That means they are whitelisted.
return FALSE
/proc/vpn_whitelist_add(target_ckey)
var/target_sql_ckey = ckey(target_ckey)
var/reason_string = input(usr, "Enter link to the URL of their whitelist request on the forum.","Reason required") as message|null
if(!reason_string)
return FALSE
reason_string = sanitizeSQL(reason_string)
var/DBQuery/query_whitelist_add = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("vpn_whitelist")] (ckey,reason) VALUES ('[target_sql_ckey]','[reason_string]')")
if(!query_whitelist_add.Execute())
var/err = query_whitelist_add.ErrorMsg()
log_debug("SQL ERROR on proc/vpn_whitelist_add for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
return FALSE
return TRUE
/proc/vpn_whitelist_remove(target_ckey)
var/target_sql_ckey = ckey(target_ckey)
var/DBQuery/query_whitelist_remove = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'")
if(!query_whitelist_remove.Execute())
var/err = query_whitelist_remove.ErrorMsg()
log_debug("SQL ERROR on proc/vpn_whitelist_remove for ckey '[target_sql_ckey]'. Error : \[[err]\]\n")
return FALSE
return TRUE
/proc/vpn_whitelist_panel(target_ckey as text)
if(!check_rights(R_ADMIN))
return
if(!target_ckey)
return
var/is_already_whitelisted = vpn_whitelist_check(target_ckey)
if(is_already_whitelisted)
var/confirm = alert("[target_ckey] is already whitelisted. Remove them?", "Confirm Removal", "No", "Yes")
if(!confirm || confirm != "Yes")
to_chat(usr, "VPN whitelist alteration cancelled.")
return
else if(vpn_whitelist_remove(target_ckey))
to_chat(usr, "[target_ckey] was removed from the VPN whitelist.")
else
to_chat(usr, "VPN whitelist unchanged.")
else
if(vpn_whitelist_add(target_ckey))
to_chat(usr, "[target_ckey] was added to the VPN whitelist.")
else
to_chat(usr, "VPN whitelist unchanged.")