server-1.12/server/ban.c

156 lines
4.3 KiB
C

/*
* static char *rcsid_ban_c =
* "$Id: ban.c 11578 2009-02-23 22:02:27Z lalo $";
*/
/**
* @file
* This code was grabbed from the Netrek source and modified to work with
* Crossfire.
*/
#include <global.h>
#include <sproto.h>
#ifndef WIN32 /* ---win32 : remove unix headers */
#include <sys/ioctl.h>
#endif /* win32 */
#ifdef hpux
#include <sys/ptyio.h>
#endif
#ifndef WIN32 /* ---win32 : remove unix headers */
#include <errno.h>
#include <stdio.h>
#include <sys/file.h>
#endif /* win32 */
/**
* Check if a player and/or host is banned. Wildcards can be used.
*
* @param login
* player name to check; NULL to check only the host name.
* @param host
* host name to check.
*
* @return
* 1=player/host is banned; 0=player/host is not banned
*/
int checkbanned(const char *login, const char *host) {
FILE *bannedfile;
char buf[MAX_BUF];
char log_buf0[160], host_buf[64], line_buf[160];
char *indexpos;
int num1;
int hits = 0; /* Hits==2 means we're banned */
int loop;
/* Inverse ban feature: if a line is prefixed by a ~, then we will
* immediately return "check passed" if it matches. This allow to ban a
* network, but let a part of it still connect.
*/
int inverse_ban = 0;
for (loop = 0; loop < 2; loop++) { /* have to check both ban files now */
/* First time through look for BANFILE */
if (loop == 0) {
snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, BANFILE);
bannedfile = fopen(buf, "r");
if (bannedfile == NULL) {
LOG(llevDebug, "Could not find file Banned file\n");
continue;
}
}
/* Second time through look for BANISHFILE */
if (loop == 1) {
snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, BANISHFILE);
bannedfile = fopen(buf, "r");
if (bannedfile == NULL) {
LOG(llevDebug, "Could not find file Banish file\n");
return(0);
}
}
/* Do the actual work here checking for banned IPs */
while (fgets(line_buf, 160, bannedfile) != NULL) {
char *log_buf = log_buf0;
inverse_ban = 0;
hits = 0;
/* Split line up */
if (*line_buf == '#' || *line_buf == '\n')
continue;
indexpos = strrchr(line_buf, '@');
if (indexpos == NULL) {
LOG(llevDebug, "Bad line in banned file\n");
continue;
}
/* copy login name into log_buf */
num1 = indexpos-line_buf;
strncpy(log_buf, line_buf, num1);
log_buf[num1] = '\0';
/* copy host name into host_buf */
strncpy(host_buf, indexpos+1, sizeof(host_buf)-1);
host_buf[sizeof(host_buf)-1] = '\0';
/* Cut off any extra spaces on the host buffer */
indexpos = host_buf;
while (!isspace(*indexpos)) {
indexpos++;
}
*indexpos = '\0';
if (*log_buf == '~') {
log_buf++;
inverse_ban = 1;
}
/*
LOG(llevDebug, "Login: <%s>; host: <%s>\n", login, host);
LOG(llevDebug, " Checking Banned <%s> and <%s>.\n", log_buf, host_buf);
*/
if (*log_buf == '*')
hits = 1;
else if (login != NULL && strcmp(login, log_buf) == 0)
hits = 1;
if (hits == 1) {
if (*host_buf == '*') { /* Lock out any host */
hits++;
/* break out now. otherwise hits will get reset to one */
break;
} else if (strstr(host, host_buf) != NULL) { /* Lock out subdomains (eg, "*@usc.edu" */
hits++;
/* break out now. otherwise hits will get reset to one */
break;
} else if (strcmp(host, host_buf) == 0) { /* Lock out specific host */
hits++;
/* break out now. otherwise hits will get reset to one */
break;
}
}
} /* loop for one file */
fclose(bannedfile);
if (hits >= 2) {
return(!inverse_ban);
}
}
return(0);
}