Deleted Added
sdiff udiff text old ( 153722 ) new ( 171172 )
full compact
1/* $OpenBSD: authpf.c,v 1.89 2005/02/10 04:24:15 joel Exp $ */
2
3/*
4 * Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/contrib/pf/authpf/authpf.c 153722 2005-12-25 22:57:08Z mlaier $");
30
31#include <sys/param.h>
32#include <sys/file.h>
33#include <sys/ioctl.h>
34#include <sys/socket.h>
35#include <sys/stat.h>
36#include <sys/time.h>
37#include <sys/wait.h>

--- 13 unchanged lines hidden (view full) ---

51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <syslog.h>
55#include <unistd.h>
56
57#include "pathnames.h"
58
59extern int symset(const char *, const char *, int);
60
61static int read_config(FILE *);
62static void print_message(char *);
63static int allowed_luser(char *);
64static int check_luser(char *, char *);
65static int remove_stale_rulesets(void);
66static int change_filter(int, const char *, const char *);
67static int change_table(int, const char *, const char *);
68static void authpf_kill_states(void);
69
70int dev; /* pf device */
71char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
72char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
73char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
74
75FILE *pidfp;
76char *infile; /* file name printed by yyerror() in parse.y */
77char luser[MAXLOGNAME]; /* username */
78char ipsrc[256]; /* ip as a string */
79char pidfile[MAXPATHLEN]; /* we save pid in this file. */
80
81struct timeval Tstart, Tend; /* start and end times of session */
82
83volatile sig_atomic_t want_death;
84static void need_death(int signo);

--- 12 unchanged lines hidden (view full) ---

97int
98main(int argc, char *argv[])
99{
100 int lockcnt = 0, n, pidfd;
101 FILE *config;
102 struct in6_addr ina;
103 struct passwd *pw;
104 char *cp;
105 uid_t uid;
106 char *shell;
107 login_cap_t *lc;
108
109 config = fopen(PATH_CONFFILE, "r");
110
111 if ((cp = getenv("SSH_TTY")) == NULL) {
112 syslog(LOG_ERR, "non-interactive session connection for authpf");
113 exit(1);
114 }
115
116 if ((cp = getenv("SSH_CLIENT")) == NULL) {
117 syslog(LOG_ERR, "cannot determine connection source");

--- 20 unchanged lines hidden (view full) ---

138 dev = open(PATH_DEVFILE, O_RDWR);
139 if (dev == -1) {
140 syslog(LOG_ERR, "cannot open packet filter device (%m)");
141 goto die;
142 }
143
144 uid = getuid();
145 pw = getpwuid(uid);
146 endpwent();
147 if (pw == NULL) {
148 syslog(LOG_ERR, "cannot find user for uid %u", uid);
149 goto die;
150 }
151
152 if ((lc = login_getclass(pw->pw_class)) != NULL)
153 shell = (char *)login_getcapstr(lc, "shell", pw->pw_shell,
154 pw->pw_shell);

--- 96 unchanged lines hidden (view full) ---

251 /*
252 * we try to kill the previous process and acquire the lock
253 * for 10 seconds, trying once a second. if we can't after
254 * 10 attempts we log an error and give up
255 */
256 if (++lockcnt > 10) {
257 syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
258 otherpid);
259 goto dogdeath;
260 }
261 sleep(1);
262
263 /* re-open, and try again. The previous authpf process
264 * we killed above should unlink the file and release
265 * it's lock, giving us a chance to get it now
266 */
267 fclose(pidfp);
268 } while (1);
269
270 /* revoke privs */
271 seteuid(getuid());
272 setuid(getuid());
273
274 openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
275
276 if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
277 syslog(LOG_INFO, "user %s prohibited", luser);
278 do_death(0);
279 }
280
281 if (config == NULL || read_config(config)) {
282 syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE);
283 do_death(0);
284 }
285
286 if (remove_stale_rulesets()) {
287 syslog(LOG_INFO, "error removing stale rulesets");
288 do_death(0);
289 }
290
291 /* We appear to be making headway, so actually mark our pid */
292 rewind(pidfp);
293 fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser);
294 fflush(pidfp);
295 (void) ftruncate(fileno(pidfp), ftello(pidfp));
296
297 if (change_filter(1, luser, ipsrc) == -1) {
298 printf("Unable to modify filters\r\n");
299 do_death(0);
300 }
301 if (change_table(1, luser, ipsrc) == -1) {
302 printf("Unable to modify table\r\n");
303 change_filter(0, luser, ipsrc);
304 do_death(0);
305 }
306
307 signal(SIGTERM, need_death);
308 signal(SIGINT, need_death);
309 signal(SIGALRM, need_death);
310 signal(SIGPIPE, need_death);
311 signal(SIGHUP, need_death);
312 signal(SIGSTOP, need_death);
313 signal(SIGTSTP, need_death);
314 while (1) {
315 printf("\r\nHello %s. ", luser);
316 printf("You are authenticated from host \"%s\"\r\n", ipsrc);
317 setproctitle("%s@%s", luser, ipsrc);
318 print_message(PATH_MESSAGE);
319 while (1) {
320 sleep(10);

--- 233 unchanged lines hidden (view full) ---

554 luser, tmp);
555
556 /* reuse tmp */
557 strlcpy(tmp, "\n\n-**- Sorry, you have been banned! -**-\n\n",
558 sizeof(tmp));
559 while (fputs(tmp, stdout) != EOF && !feof(f)) {
560 if (fgets(tmp, sizeof(tmp), f) == NULL) {
561 fflush(stdout);
562 return (0);
563 }
564 }
565 }
566 fflush(stdout);
567 return (0);
568}
569
570/*
571 * Search for rulesets left by other authpf processes (either because they
572 * died ungracefully or were terminated) and remove them.

--- 67 unchanged lines hidden (view full) ---

640 char *pargv[13] = {
641 "pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
642 "-D", "user_ip=X", "-D", "user_id=X", "-f",
643 "file", NULL
644 };
645 char *fdpath = NULL, *userstr = NULL, *ipstr = NULL;
646 char *rsn = NULL, *fn = NULL;
647 pid_t pid;
648 int s;
649
650 if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
651 syslog(LOG_ERR, "invalid luser/ipsrc");
652 goto error;
653 }
654
655 if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)

--- 23 unchanged lines hidden (view full) ---

679 pargv[9] = ipstr;
680 if (!add)
681 pargv[11] = "/dev/null";
682 else
683 pargv[11] = fn;
684
685 switch (pid = fork()) {
686 case -1:
687 err(1, "fork failed");
688 case 0:
689 execvp(PATH_PFCTL, pargv);
690 warn("exec of %s failed", PATH_PFCTL);
691 _exit(1);
692 }
693
694 /* parent */
695 waitpid(pid, &s, 0);
696 if (s != 0) {
697 if (WIFEXITED(s)) {
698 syslog(LOG_ERR, "pfctl exited abnormally");
699 goto error;
700 }
701 }
702
703 if (add) {
704 gettimeofday(&Tstart, NULL);
705 syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser);
706 } else {
707 gettimeofday(&Tend, NULL);
708#ifdef __FreeBSD__

--- 4 unchanged lines hidden (view full) ---

713 ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
714#endif
715 }
716 return (0);
717no_mem:
718 syslog(LOG_ERR, "malloc failed");
719error:
720 free(fdpath);
721 fdpath = NULL;
722 free(rsn);
723 rsn = NULL;
724 free(userstr);
725 userstr = NULL;
726 free(ipstr);
727 ipstr = NULL;
728 free(fn);
729 fn = NULL;
730 infile = NULL;
731 return (-1);
732}
733
734/*
735 * Add/remove this IP from the "authpf_users" table.
736 */
737static int
738change_table(int add, const char *luser, const char *ipsrc)
739{
740 struct pfioc_table io;
741 struct pfr_addr addr;
742
743 bzero(&io, sizeof(io));
744 strlcpy(io.pfrio_table.pfrt_name, tablename, sizeof(io.pfrio_table));
745 io.pfrio_buffer = &addr;
746 io.pfrio_esize = sizeof(addr);
747 io.pfrio_size = 1;
748
749 bzero(&addr, sizeof(addr));
750 if (ipsrc == NULL || !ipsrc[0])
751 return (-1);
752 if (inet_pton(AF_INET, ipsrc, &addr.pfra_ip4addr) == 1) {

--- 76 unchanged lines hidden (view full) ---

829static __dead void
830#endif
831do_death(int active)
832{
833 int ret = 0;
834
835 if (active) {
836 change_filter(0, luser, ipsrc);
837 change_table(0, luser, ipsrc);
838 authpf_kill_states();
839 remove_stale_rulesets();
840 }
841 if (pidfp)
842 ftruncate(fileno(pidfp), 0);
843 if (pidfile[0])
844 if (unlink(pidfile) == -1)
845 syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
846 exit(ret);
847}