File: ban.c

package info (click to toggle)
crossfire 1.11.0-2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 24,456 kB
  • ctags: 7,800
  • sloc: ansic: 80,483; sh: 11,825; perl: 2,327; lex: 1,946; makefile: 1,149
file content (157 lines) | stat: -rw-r--r-- 4,543 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 * static char *rcsid_ban_c =
 *   "$Id: ban.c 5894 2007-03-25 20:41:32Z ryo_saeba $";
 */

/*
 * Ban.c
 * Code was grabbed from the netrek source and modified to work with
 * crossfire. This function checks a file in the lib directory for any
 * banned players. If it finds one it returns a 1. Wildcards can be used.
 */

#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.
 *
 * @param login the player name to check; NULL to check only the host name
 *
 * @param host the 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) {
            sprintf(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) {
            sprintf(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);
}