#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include "global.h"
#include "utils.h"
#include "comm.h"
#include "modify.h"
#include "interpreter.h"
#include "db.h"
#include "sql.h"
#include "bug.h"
#define __BAN_C__
#include "ban.h"
EXEC SQL INCLUDE sqlca;
static char old_banned_names[MAX_STRING_LENGTH] = "\0\0\0"; /* dumbfuck asshole and friends */
EXEC SQL BEGIN DECLARE SECTION;
static char **banned_names = NULL;
static char **banned_ips = NULL;
static char **banned_at_names = NULL;
static char **banned_at_ips = NULL;
EXEC SQL END DECLARE SECTION;
static int banned_names_count = 0;
static int banned_ips_count = 0;
static int banned_at_count = 0;
/*
* Make sure they are not being stupid.
*/
int old_banned_name(char *name)
{
char ack[MAX_STRING_LENGTH] = "\0\0\0";
char *pfft = NULL;
if (DEBUG > 2)
log_info("called %s with %s", __PRETTY_FUNCTION__, VNULL(name));
strcpy(ack, old_banned_names);
if (!(pfft = (char *)strtok(ack, " \t\r\n")))
return FALSE;
if (!strcasecmp(pfft, name))
return TRUE;
while ((pfft = (char *)strtok(NULL, " \t\r\n"))) {
if (!strcasecmp(pfft, name))
return TRUE;
}
return FALSE;
}
int banned_name(char *name)
{
/*
EXEC SQL BEGIN DECLARE SECTION;
int is_banned = 0;
char check_name[MAX_STRING_LENGTH] = "\0\0\0";
EXEC SQL END DECLARE SECTION;
*/
int i;
if (DEBUG > 2)
log_info("called %s with %s", __PRETTY_FUNCTION__, VNULL(name));
if (banned_names_count < 1)
return FALSE;
for(i = 0; i < banned_names_count; i++) {
if (!str_cmp(banned_names[i], name))
return TRUE;
}
return FALSE;
/*
strcpy(check_name, name);
EXEC SQL SELECT 1
INTO :is_banned
FROM banned
WHERE lower(banned_name) = lower(:check_name)
AND banned_ip IS NULL;
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
}
return is_banned;
*/
}
int banned_ip(char *ip)
{
/*
EXEC SQL BEGIN DECLARE SECTION;
int is_banned = 0;
char check_ip[MAX_STRING_LENGTH] = "\0\0\0";
EXEC SQL END DECLARE SECTION;
*/
int i;
if (DEBUG > 2)
log_info("called %s with %s", __PRETTY_FUNCTION__, VNULL(ip));
if (banned_ips_count < 1)
return FALSE;
for(i = 0; i < banned_ips_count; i++) {
if (!str_cmp(banned_ips[i], ip))
return TRUE;
}
return FALSE;
/*
strcpy(check_ip, ip);
EXEC SQL SELECT 1
INTO :is_banned
FROM banned
WHERE host(banned_ip) = lower(:check_ip)
AND banned_name IS NULL;
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
}
return is_banned;
*/
}
int banned_at(char *name, char *ip)
{
/*
EXEC SQL BEGIN DECLARE SECTION;
int is_banned = 0;
char check_ip[MAX_STRING_LENGTH] = "\0\0\0";
char check_name[MAX_STRING_LENGTH] = "\0\0\0";
EXEC SQL END DECLARE SECTION;
*/
int i;
if (DEBUG > 2)
log_info("called %s with %s", __PRETTY_FUNCTION__, VNULL(ip));
if (banned_ips_count < 1)
return FALSE;
for(i = 0; i < banned_at_count; i++) {
if (!str_cmp(banned_at_names[i], name) && !str_cmp(banned_at_ips[i], ip))
return TRUE;
}
return FALSE;
/*
strcpy(check_ip, ip);
strcpy(check_name, name);
EXEC SQL SELECT 1
INTO :is_banned
FROM banned
WHERE host(banned_ip) = lower(:check_ip)
AND lower(banned_name) = lower(:check_name);
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
}
return is_banned;
*/
}
void load_bans(void)
{
/*
if( !db_connected ) {
log_boot("- Loading banned name list from file");
file_to_prompt(BANNED_NAME_FILE, old_banned_names);
return;
}
*/
/* Only load from the file if it's newer than our SQL data */
if( compare_dates_file_sql( BANNED_NAME_FILE, "banned", "banned_date" ) > 0 ) {
log_boot("- Loading banned name list from file");
file_to_prompt(BANNED_NAME_FILE, old_banned_names);
bans_to_sql();
}
log_boot("- Loading banned name list from SQL");
init_sql();
EXEC SQL SELECT banned_name
INTO :banned_names
FROM banned
WHERE banned_ip IS NULL
ORDER BY banned_name;
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
} else {
banned_names_count = sqlca.sqlerrd[2]; /* row count */
EXEC SQL COMMIT;
}
log_boot("- Loading banned ip list from SQL");
EXEC SQL SELECT host(banned_ip)
INTO :banned_ips
FROM banned
WHERE banned_name IS NULL
ORDER BY banned_ip;
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
} else {
banned_ips_count = sqlca.sqlerrd[2]; /* row count */
EXEC SQL COMMIT;
}
log_boot("- Loading banned name@ip list from SQL");
EXEC SQL SELECT banned_name, banned_ip
INTO :banned_at_names, :banned_at_ips
FROM banned
WHERE banned_name IS NOT NULL
AND banned_ip IS NOT NULL
ORDER BY banned_name, banned_ip;
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
} else {
banned_at_count = sqlca.sqlerrd[2]; /* row count */
EXEC SQL COMMIT;
}
close_sql();
save_bans();
}
void unload_bans(void)
{
if(banned_names) {
log_boot("- Unloading banned name list");
free(banned_names);
banned_names = NULL;
banned_names_count = 0;
}
if(banned_ips) {
log_boot("- Unloading banned ip list");
free(banned_ips);
banned_ips = NULL;
banned_ips_count = 0;
}
}
void bans_to_sql(void)
{
EXEC SQL BEGIN DECLARE SECTION;
char tmp[MAX_STRING_LENGTH];
EXEC SQL END DECLARE SECTION;
char ack[MAX_STRING_LENGTH] = "\0\0\0";
char *pfft = NULL;
init_sql();
strcpy(ack, old_banned_names);
pfft = (char *)strtok(ack, " \t\r\n");
while(pfft) {
strcpy(tmp, pfft);
EXEC SQL BEGIN WORK;
EXEC SQL INSERT INTO banned ( banned_name ) VALUES ( :tmp );
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
EXEC SQL ROLLBACK WORK;
if (sqlca.sqlcode == -400) {
init_sql();
}
} else {
EXEC SQL COMMIT WORK;
}
pfft = (char *)strtok(NULL, " \t\r\n");
}
close_sql();
}
void do_ban(struct char_data *ch, const char *argument, int cmd)
{
char ban_type[MAX_STRING_LENGTH] = "\0\0\0";
int i = 0;
EXEC SQL BEGIN DECLARE SECTION;
char buf[MAX_STRING_LENGTH] = "\0\0\0";
EXEC SQL END DECLARE SECTION;
if (DEBUG)
log_info("called %s with %s, %s, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(argument), cmd);
if (IS_NPC(ch)) {
cprintf(ch, "You're a mob, you can't ban anyone.\r\n");
return;
}
if (argument && *argument) {
argument = one_argument(argument, ban_type);
only_argument(argument, buf);
if (*ban_type) {
if (!str_cmp(ban_type, "name")) {
if (*buf) {
/* First, we need to make sure it isn't already a mob or player.
* then we can try adding it to the ban table.
*/
if(!acceptable_name(buf)) {
cprintf(ch, "%s is already an invalid choice.\r\n", buf);
return;
}
/* Now, we can actually do the ban. */
init_sql();
EXEC SQL BEGIN WORK;
EXEC SQL INSERT INTO banned ( banned_name ) VALUES ( :buf );
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
EXEC SQL ROLLBACK WORK;
} else {
EXEC SQL COMMIT WORK;
cprintf(ch, "%s is now banned!\r\n", buf);
log_auth(ch, "BAN %s has been banned by %s!", buf, GET_NAME(ch));
}
close_sql();
/* Now we need to refresh the ban lists */
unload_bans();
load_bans();
return;
} else {
cprintf(ch, "Banned names:\r\n");
for(i = 0; i < banned_names_count; i++) {
cprintf(ch, "%-20s\r\n", banned_names[i]);
}
return;
}
} else if (!str_cmp(ban_type, "ip") || !str_cmp(ban_type, "address") || !str_cmp(ban_type, "site")) {
if (*buf) {
/* No banning localhost! */
if(str_cmp("127.0.0.1", buf)) {
cprintf(ch, "You cannot ban localhost!\r\n");
return;
}
/* Now, we can actually do the ban. */
init_sql();
EXEC SQL BEGIN WORK;
EXEC SQL INSERT INTO banned ( banned_ip ) VALUES ( :buf );
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
EXEC SQL ROLLBACK WORK;
} else {
EXEC SQL COMMIT WORK;
cprintf(ch, "%s is now banned!\r\n", buf);
log_auth(ch, "BAN %s has been banned by %s!", buf, GET_NAME(ch));
}
close_sql();
/* Now we need to refresh the ban lists */
unload_bans();
load_bans();
return;
} else {
cprintf(ch, "Banned IP addresses:\r\n");
for(i = 0; i < banned_ips_count; i++) {
cprintf(ch, "%-20s\r\n", banned_ips[i]);
}
return;
}
}
}
}
cprintf(ch, "Usage: ban < name|ip > [ name|address ]\r\n");
}
void do_unban(struct char_data *ch, const char *argument, int cmd)
{
char ban_type[MAX_STRING_LENGTH] = "\0\0\0";
char tmp_page[MAX_STRING_LENGTH] = "\0\0\0";
int i = 0;
EXEC SQL BEGIN DECLARE SECTION;
char buf[MAX_STRING_LENGTH] = "\0\0\0";
EXEC SQL END DECLARE SECTION;
if (DEBUG)
log_info("called %s with %s, %s, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(argument), cmd);
if (IS_NPC(ch)) {
cprintf(ch, "You're a mob, you can't ban anyone.\r\n");
return;
}
if (argument && *argument) {
argument = one_argument(argument, ban_type);
only_argument(argument, buf);
if (*ban_type) {
if (!str_cmp(ban_type, "name")) {
if (*buf) {
/* Are they actually banned? */
if(!banned_name(buf)) {
cprintf(ch, "%s is not currently banned.\r\n", buf);
return;
}
/* OK, yank 'em. */
init_sql();
EXEC SQL BEGIN WORK;
EXEC SQL DELETE FROM banned WHERE lower(banned_name) = lower(:buf);
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
EXEC SQL ROLLBACK WORK;
} else {
EXEC SQL COMMIT WORK;
cprintf(ch, "%s is now unbanned.\r\n", buf);
log_auth(ch, "BAN %s has been unbanned by %s!", buf, GET_NAME(ch));
}
close_sql();
/* Now we need to refresh the ban lists */
unload_bans();
load_bans();
return;
} else {
sprintf(tmp_page, "Banned names:\r\n");
page_string(ch->desc, tmp_page, 1);
for(i = 0; i < banned_names_count; i++) {
sprintf(tmp_page, "%-20s\r\n", banned_names[i]);
page_string(ch->desc, tmp_page, 1);
}
return;
}
} else if (!str_cmp(ban_type, "ip") || !str_cmp(ban_type, "address") || !str_cmp(ban_type, "site")) {
if (*buf) {
/* Are they actually banned? */
if(!banned_ip(buf)) {
cprintf(ch, "%s is not currently banned.\r\n", buf);
return;
}
/* OK, yank 'em. */
init_sql();
EXEC SQL BEGIN WORK;
EXEC SQL DELETE FROM banned WHERE host(banned_ip) = lower(:buf);
if (sqlca.sqlcode < 0) {
fprintf(stderr, "error code %ld, message %s, rows %ld, warning %c\n",
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, sqlca.sqlerrd[2],
sqlca.sqlwarn[0]);
EXEC SQL ROLLBACK WORK;
} else {
EXEC SQL COMMIT WORK;
cprintf(ch, "%s is now unbanned.\r\n", buf);
log_auth(ch, "BAN %s has been unbanned by %s!", buf, GET_NAME(ch));
}
close_sql();
/* Now we need to refresh the ban lists */
unload_bans();
load_bans();
return;
} else {
sprintf(tmp_page, "Banned IP addresses:\r\n");
page_string(ch->desc, tmp_page, 1);
for(i = 0; i < banned_ips_count; i++) {
sprintf(tmp_page, "%-20s\r\n", banned_ips[i]);
page_string(ch->desc, tmp_page, 1);
}
return;
}
}
}
}
cprintf(ch, "Usage: unban < name|ip > [ name|address ]\r\n");
}
/* Returns TRUE if this character name would be acceptable for a
* new player.
* Returns FALSE if it fails any checks, including being an
* already existing character or mob, an illegal name, banned, etc.
*/
int acceptable_name( const char *name )
{
char tmp_name[20] = "\0\0\0";
struct char_file_u tmp_store;
struct char_data tmp_char;
if (!valid_parse_name(name, tmp_name))
return FALSE;
if (check_playing(NULL, tmp_name))
return FALSE;
/* We don't check ValidPlayer here */
if (fread_char(tmp_name, &tmp_store, &tmp_char) > -1)
return FALSE;
if (load_char(tmp_name, &tmp_store) > -1)
return FALSE;
if (already_mob_name(tmp_name))
return FALSE;
if (banned_name(tmp_name))
return FALSE;
return TRUE;
}
void save_bans(void)
{
FILE *fp = NULL;
int i;
if(!(fp = fopen(BAN_FILE, "w"))) {
log_error("Cannot open %s for writing!\n", BAN_FILE);
return;
}
log_boot("- Saving ban data to %s", BAN_FILE);
fprintf(fp, "%d\n", banned_names_count);
for (i = 0; i < banned_names_count; i++) {
fprintf(fp, "%s\n", banned_names[i]);
}
fprintf(fp, "%d\n", banned_ips_count);
for (i = 0; i < banned_ips_count; i++) {
fprintf(fp, "%s\n", banned_ips[i]);
}
fprintf(fp, "%d\n", banned_at_count);
for (i = 0; i < banned_at_count; i++) {
fprintf(fp, "%s\n%s\n", banned_at_names[i], banned_at_ips[i]);
}
fclose(fp);
}