00001
00002
00003
00004 #define nil 0
00005 #define ioctl _ioctl
00006 #define open _open
00007 #define write _write
00008 #define close _close
00009 #include <sys/types.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <errno.h>
00013 #include <string.h>
00014 #include <fcntl.h>
00015 #include <unistd.h>
00016 #include <time.h>
00017 #include <sys/ioctl.h>
00018 #include <net/hton.h>
00019 #include <net/gen/in.h>
00020 #include <net/gen/tcp.h>
00021 #include <net/gen/tcp_io.h>
00022 #include <net/gen/inet.h>
00023 #include <net/gen/socket.h>
00024 #include <net/gen/netdb.h>
00025
00026
00027 static const char *path_servacces = _PATH_SERVACCES;
00028
00029 #define WLEN 256
00030
00031 static int getword(FILE *fp, char *word)
00032
00033
00034
00035
00036 {
00037 int c;
00038 char *pw;
00039 int wc;
00040
00041 wc= 0;
00042 for (;;) {
00043 if ((c= getc(fp)) == EOF) return EOF;
00044 if (c == '#') { wc= 1; continue; }
00045 if (c == '\n') { wc= 0; continue; }
00046 if (wc) continue;
00047 if (c <= ' ') continue;
00048 break;
00049 }
00050
00051 pw= word;
00052 if (c == ':' || c == ';') {
00053 *pw++ = c;
00054 } else {
00055 do {
00056 if (pw < word + WLEN-1) *pw++ = c;
00057 c= getc(fp);
00058 } while (c != EOF && c > ' ' && c != ':' && c != ';');
00059 if (c != EOF) ungetc(c, fp);
00060 }
00061 *pw= 0;
00062 return word[0];
00063 }
00064
00065 static int netspec(char *word, ipaddr_t *addr, ipaddr_t *mask)
00066
00067 {
00068 char *slash;
00069 int r;
00070 static char S32[]= "/32";
00071
00072 if (*word == 0) return 0;
00073
00074 if ((slash= strchr(word, '/')) == NULL) slash= S32;
00075
00076 *slash= 0;
00077 r= inet_aton(word, addr);
00078 *slash++= '/';
00079 if (!r) return 0;
00080
00081 r= 0;
00082 while ((*slash - '0') < 10u) {
00083 r= 10*r + (*slash++ - '0');
00084 if (r > 32) return 0;
00085 }
00086 if (*slash != 0 || slash[-1] == '/') return 0;
00087 *mask= htonl(r == 0 ? 0L : (0xFFFFFFFFUL >> (32 - r)) << (32 - r));
00088 return 1;
00089 }
00090
00091 static int match(const char *word, const char *pattern)
00092
00093 {
00094 unsigned cw, cp;
00095 #define lc(c, d) ((((c)= (d)) - 'A') <= ('Z' - 'A') ? (c)+= ('a' - 'A') : 0)
00096
00097 for (;;) {
00098 lc(cw, *word);
00099 lc(cp, *pattern);
00100
00101 if (cp == '*') {
00102 do pattern++; while (*pattern == '*');
00103 lc(cp, *pattern);
00104 if (cp == 0) return 1;
00105
00106 while (cw != 0) {
00107 if (cw == cp && match(word+1, pattern+1)) return 1;
00108 word++;
00109 lc(cw, *word);
00110 }
00111 return 0;
00112 } else
00113 if (cw == 0 || cp == 0) {
00114 return cw == cp;
00115 } else
00116 if (cw == cp) {
00117 word++;
00118 pattern++;
00119 } else {
00120 return 0;
00121 }
00122 }
00123 #undef lc
00124 }
00125
00126 static int get_name(ipaddr_t addr, char *name)
00127
00128
00129
00130
00131 {
00132 struct hostent *he;
00133 int i;
00134
00135 he= gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
00136 if (he != NULL) {
00137 strcpy(name, he->h_name);
00138 he= gethostbyname(name);
00139
00140 if (he != NULL && he->h_addrtype == AF_INET) {
00141 for (i= 0; he->h_addr_list[i] != NULL; i++) {
00142 if (memcmp(he->h_addr_list[i], &addr, sizeof(addr)) == 0) {
00143 strcpy(name, he->h_name);
00144 return 1;
00145 }
00146 }
00147 }
00148 }
00149 strcpy(name, inet_ntoa(addr));
00150 return 0;
00151 }
00152
00153
00154 #define DEFFAIL 0x01
00155 #define FAIL (0x02 | DEFFAIL)
00156 #define PASS 0x04
00157
00158 int servxcheck(ipaddr_t peer, const char *service,
00159 void (*logf)(int pass, const char *name))
00160 {
00161 FILE *fp;
00162 char word[WLEN];
00163 char name[WLEN];
00164 int c;
00165 int got_name, slist, seen, explicit, state, log;
00166 ipaddr_t addr, mask;
00167
00168
00169 if ((peer & HTONL(0xFF000000)) == HTONL(0x7F000000)) return 1;
00170
00171 if ((fp= fopen(path_servacces, "r")) == nil) {
00172
00173 return (errno != ENOENT);
00174 }
00175
00176 slist= 1;
00177 seen= 0;
00178 explicit= 0;
00179 got_name= -1;
00180 log= FAIL;
00181 state= DEFFAIL;
00182
00183 while ((c= getword(fp, word)) != EOF) {
00184 if (c == ':') {
00185 slist= 0;
00186 } else
00187 if (c == ';') {
00188 slist= 1;
00189 seen= 0;
00190 } else
00191 if (slist) {
00192
00193
00194 if (match(service, word)) {
00195
00196 if (match(word, service)) {
00197
00198 seen= explicit= 1;
00199 } else {
00200
00201 if (!explicit) seen= 1;
00202 }
00203 }
00204 } else {
00205
00206
00207 if (c == 'l' && strcmp(word, "log") == 0) {
00208 if (seen) {
00209
00210 log= FAIL|PASS;
00211 }
00212 continue;
00213 }
00214
00215 if (c != '-' && c != '+') {
00216 if (logf == nil) {
00217 fprintf(stderr, "%s: strange check word '%s'\n",
00218 path_servacces, word);
00219 }
00220 continue;
00221 }
00222
00223 if (seen) {
00224 if (state == DEFFAIL) {
00225
00226 state= c == '+' ? FAIL : PASS;
00227 }
00228
00229 if ((state == PASS) == (c == '+')) {
00230
00231 } else
00232 if (word[1] == 0) {
00233
00234 state= c == '-' ? FAIL : PASS;
00235 } else
00236 if (netspec(word+1, &addr, &mask)) {
00237
00238 if (((peer ^ addr) & mask) == 0) {
00239 state= c == '-' ? FAIL : PASS;
00240 }
00241 } else {
00242
00243 if (got_name == -1) {
00244 got_name= get_name(peer, name);
00245 }
00246
00247
00248 if (!got_name) {
00249 state= FAIL;
00250 } else
00251 if (match(name, word+1)) {
00252 state= c == '-' ? FAIL : PASS;
00253 }
00254 }
00255 }
00256 }
00257 }
00258 fclose(fp);
00259
00260 if ((log & state) != 0) {
00261
00262 if (got_name == -1) (void) get_name(peer, name);
00263
00264 if (logf != nil) {
00265 (*logf)(state == PASS, name);
00266 } else {
00267 int lfd;
00268 char line[128+WLEN];
00269 time_t t;
00270 struct tm *tm;
00271 char month[][4]= {
00272 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00273 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
00274 };
00275
00276 if ((lfd= open("/usr/adm/log", O_WRONLY|O_APPEND)) != -1) {
00277 time(&t);
00278 tm= localtime(&t);
00279 sprintf(line, "%s %02d %02d:%02d:%02d service '%s' %s to %s\n",
00280 month[tm->tm_mon],
00281 tm->tm_mday,
00282 tm->tm_hour, tm->tm_min, tm->tm_sec,
00283 service,
00284 state == PASS ? "granted" : "denied",
00285 name);
00286 (void) write(lfd, line, strlen(line));
00287 close(lfd);
00288 }
00289 }
00290 }
00291 return state == PASS;
00292 }
00293
00294 char *servxfile(const char *file)
00295
00296
00297
00298 {
00299 const char *oldpath= path_servacces;
00300 path_servacces= file;
00301 return (char *) oldpath;
00302 }