215 lines
3.8 KiB
C
215 lines
3.8 KiB
C
/*
|
|
* CGI to add stuff to a pf table on successful entry of a username and password
|
|
* I hope it's secure; must run suid root
|
|
* (C)2005-2010, Dan Ponte <amigan@gmail.com>
|
|
* 2-clause BSD license
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <pwd.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <net/if.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <errno.h>
|
|
|
|
#include <net/pfvar.h>
|
|
|
|
#ifndef TMPTAB
|
|
#define TMPTAB "webtable"
|
|
#endif
|
|
|
|
void add_addr(fd, add)
|
|
int fd;
|
|
int add;
|
|
{
|
|
struct pfioc_table pftb;
|
|
struct pfr_table ttb;
|
|
struct pfr_addr addr;
|
|
struct in_addr tad;
|
|
int i;
|
|
char *raddr;
|
|
|
|
#define NTABS 20
|
|
|
|
raddr = getenv("REMOTE_ADDR");
|
|
if(raddr == NULL) {
|
|
printf("No remote_addr!\n");
|
|
exit(-23);
|
|
}
|
|
|
|
bzero(&ttb, sizeof(ttb));
|
|
bzero(&pftb, sizeof pftb);
|
|
bzero(&addr, sizeof addr);
|
|
|
|
strncpy(ttb.pfrt_name, TMPTAB, sizeof(ttb.pfrt_name));
|
|
|
|
pftb.pfrio_table = ttb;
|
|
pftb.pfrio_buffer = &addr;
|
|
pftb.pfrio_size = 1;
|
|
pftb.pfrio_esize = sizeof(struct pfr_addr);
|
|
|
|
inet_aton(raddr, &tad);
|
|
bcopy(&tad, &addr.pfra_ip4addr, 4);
|
|
addr.pfra_af = AF_INET;
|
|
addr.pfra_net = 32;
|
|
|
|
if(add) {
|
|
i = ioctl(fd, DIOCRADDADDRS, &pftb);
|
|
if(i == -1) {
|
|
perror("ioctl DIOCRADDADDRS");
|
|
exit(-23);
|
|
}
|
|
} else {
|
|
i = ioctl(fd, DIOCRDELADDRS, &pftb);
|
|
if(i == -1) {
|
|
perror("ioctl DIOCRDELADDRS");
|
|
exit(-23);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
int check_crendentials(void)
|
|
{
|
|
char bfr[512];
|
|
char *loginname, *pass;
|
|
char *tok, *ntok;
|
|
size_t len;
|
|
char *encpass;
|
|
struct passwd *pd;
|
|
|
|
fgets(bfr, 511, stdin);
|
|
|
|
tok = strstr(bfr, "login=");
|
|
if(tok == NULL) {
|
|
printf("no login=\n");
|
|
return 0;
|
|
}
|
|
|
|
tok += strlen("login=");
|
|
|
|
ntok = strchr(tok, '&');
|
|
if(ntok == NULL) {
|
|
printf("no ampersand\n");
|
|
return 0;
|
|
}
|
|
|
|
len = (size_t)(ntok - tok) + 1;
|
|
|
|
loginname = malloc(len);
|
|
if(loginname == NULL) {
|
|
printf("malloc error for loginname\n");
|
|
return 0;
|
|
}
|
|
bzero(loginname, len);
|
|
|
|
strncpy(loginname, tok, len - 1);
|
|
|
|
tok = strstr(bfr, "passwd=");
|
|
if(tok == NULL) {
|
|
printf("no passwd=\n");
|
|
return 0;
|
|
}
|
|
|
|
tok += strlen("passwd=");
|
|
|
|
ntok = strchr(tok, '&');
|
|
if(ntok == NULL)
|
|
if((ntok = strchr(tok, '\0')) == NULL) {
|
|
printf("dbl no amp\n");
|
|
return 0;
|
|
}
|
|
|
|
len = (size_t)(ntok - tok) + 1;
|
|
|
|
pass = malloc(len);
|
|
if(pass == NULL) {
|
|
printf("malloc error for passwd\n");
|
|
return 0;
|
|
}
|
|
|
|
bzero(pass, len);
|
|
|
|
strncpy(pass, tok, len - 1);
|
|
|
|
errno = 0;
|
|
pd = getpwnam(loginname);
|
|
if(pd == NULL) {
|
|
if(errno != 0) {
|
|
printf("getpwnam error: %s\n", strerror(errno));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
encpass = crypt(pass, pd->pw_passwd);
|
|
if(encpass == NULL) {
|
|
printf("null encpass\n");
|
|
return 0;
|
|
}
|
|
|
|
free(loginname);
|
|
free(pass);
|
|
|
|
if(strcmp(encpass, pd->pw_passwd) == 0)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
int main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
char *req_method;
|
|
int pffd;
|
|
|
|
if(getenv("GATEWAY_INTERFACE") == NULL) {
|
|
fprintf(stderr, "Must be run as a CGI! Aborting.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
printf("Content-Type: text/html\n\n<!DOCTYPE html\n"
|
|
"PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n"
|
|
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd\">\n"
|
|
"<html xmlns=\"http://www.w3.org/1999.xhtml\">\n"
|
|
"<head><title>webpftable</title></head>\n<body>\n"
|
|
);
|
|
|
|
if((req_method = getenv("REQUEST_METHOD")) == NULL) {
|
|
fprintf(stderr, "CGI!\n");
|
|
exit(-2);
|
|
}
|
|
|
|
if(strcmp(req_method, "POST") != 0) {
|
|
printf("Must be POST!\n");
|
|
exit(-3);
|
|
}
|
|
|
|
if((pffd = open("/dev/pf", O_RDWR)) < 0 ) {
|
|
perror("open pf");
|
|
exit(-4);
|
|
}
|
|
|
|
if(check_crendentials()) {
|
|
add_addr(pffd, 1);
|
|
printf("<p>Added! Have fun!</p>\n");
|
|
}else {
|
|
add_addr(pffd, 0);
|
|
printf("<p>Incorrect login and/or password. Try again.</p>\n");
|
|
printf("<p>Your IP has been removed from table if it was there.</p>\n");
|
|
}
|
|
|
|
close(pffd);
|
|
|
|
printf("</body></html>\n");
|
|
|
|
return 0;
|
|
}
|