Deleted Added
full compact
authpf.c (153722) authpf.c (171172)
1/* $OpenBSD: authpf.c,v 1.89 2005/02/10 04:24:15 joel Exp $ */
1/* $OpenBSD: authpf.c,v 1.104 2007/02/24 17:35:08 beck Exp $ */
2
3/*
2
3/*
4 * Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
4 * Copyright (C) 1998 - 2007 Bob Beck (beck@openbsd.org).
5 *
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.
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
14 *
9 *
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.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 */
27
28#include <sys/cdefs.h>
17 */
18
19#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/contrib/pf/authpf/authpf.c 153722 2005-12-25 22:57:08Z mlaier $");
20__FBSDID("$FreeBSD: head/contrib/pf/authpf/authpf.c 171172 2007-07-03 12:30:03Z 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
21
22#include <sys/param.h>
23#include <sys/file.h>
24#include <sys/ioctl.h>
25#include <sys/socket.h>
26#include <sys/stat.h>
27#include <sys/time.h>
28#include <sys/wait.h>

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

42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <syslog.h>
46#include <unistd.h>
47
48#include "pathnames.h"
49
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 *);
50static int read_config(FILE *);
51static void print_message(char *);
52static int allowed_luser(char *);
53static int check_luser(char *, char *);
54static int remove_stale_rulesets(void);
55static int change_filter(int, const char *, const char *);
67static int change_table(int, const char *, const char *);
56static int change_table(int, 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;
57static void authpf_kill_states(void);
58
59int dev; /* pf device */
60char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
61char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
62char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
63
64FILE *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;
65char luser[MAXLOGNAME]; /* username */
66char ipsrc[256]; /* ip as a string */
67char pidfile[MAXPATHLEN]; /* we save pid in this file. */
68
69struct timeval Tstart, Tend; /* start and end times of session */
70
71volatile sig_atomic_t want_death;
72static void need_death(int signo);

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

85int
86main(int argc, char *argv[])
87{
88 int lockcnt = 0, n, pidfd;
89 FILE *config;
90 struct in6_addr ina;
91 struct passwd *pw;
92 char *cp;
93 gid_t gid;
105 uid_t uid;
106 char *shell;
107 login_cap_t *lc;
108
109 config = fopen(PATH_CONFFILE, "r");
94 uid_t uid;
95 char *shell;
96 login_cap_t *lc;
97
98 config = fopen(PATH_CONFFILE, "r");
99 if (config == NULL) {
100 syslog(LOG_ERR, "can not open %s (%m)", PATH_CONFFILE);
101 exit(1);
102 }
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);
103
104 if ((cp = getenv("SSH_TTY")) == NULL) {
105 syslog(LOG_ERR, "non-interactive session connection for authpf");
106 exit(1);
107 }
108
109 if ((cp = getenv("SSH_CLIENT")) == NULL) {
110 syslog(LOG_ERR, "cannot determine connection source");

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

131 dev = open(PATH_DEVFILE, O_RDWR);
132 if (dev == -1) {
133 syslog(LOG_ERR, "cannot open packet filter device (%m)");
134 goto die;
135 }
136
137 uid = getuid();
138 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);
139 if (pw == NULL) {
140 syslog(LOG_ERR, "cannot find user for uid %u", uid);
141 goto die;
142 }
143
144 if ((lc = login_getclass(pw->pw_class)) != NULL)
145 shell = (char *)login_getcapstr(lc, "shell", pw->pw_shell,
146 pw->pw_shell);

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

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

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

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

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

646 char *pargv[13] = {
647 "pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
648 "-D", "user_ip=X", "-D", "user_id=X", "-f",
649 "file", NULL
650 };
651 char *fdpath = NULL, *userstr = NULL, *ipstr = NULL;
652 char *rsn = NULL, *fn = NULL;
653 pid_t pid;
654 gid_t gid;
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:
655 int s;
656
657 if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
658 syslog(LOG_ERR, "invalid luser/ipsrc");
659 goto error;
660 }
661
662 if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)

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

686 pargv[9] = ipstr;
687 if (!add)
688 pargv[11] = "/dev/null";
689 else
690 pargv[11] = fn;
691
692 switch (pid = fork()) {
693 case -1:
687 err(1, "fork failed");
694 syslog(LOG_ERR, "fork failed");
695 goto error;
688 case 0:
696 case 0:
697 /* revoke group privs before exec */
698 gid = getgid();
699 if (setregid(gid, gid) == -1) {
700 err(1, "setregid");
701 }
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) {
702 execvp(PATH_PFCTL, pargv);
703 warn("exec of %s failed", PATH_PFCTL);
704 _exit(1);
705 }
706
707 /* parent */
708 waitpid(pid, &s, 0);
709 if (s != 0) {
697 if (WIFEXITED(s)) {
698 syslog(LOG_ERR, "pfctl exited abnormally");
699 goto error;
700 }
710 syslog(LOG_ERR, "pfctl exited abnormally");
711 goto error;
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);
712 }
713
714 if (add) {
715 gettimeofday(&Tstart, NULL);
716 syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser);
717 } else {
718 gettimeofday(&Tend, NULL);
719#ifdef __FreeBSD__

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

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

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

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