diff -uNr authpf/authpf.8 authpf_new/authpf.8 --- authpf/authpf.8 Mon Mar 24 20:04:07 2003 +++ authpf_new/authpf.8 Tue May 27 23:33:27 2003 @@ -32,6 +32,7 @@ .Nd authenticating gateway user shell .Sh SYNOPSIS .Nm authpf +.Nm authpf_single .Sh DESCRIPTION .Nm is a user shell for authenticating gateways. @@ -74,6 +75,11 @@ (if any) to add. On session exit the same rules that were added at startup are removed. .Pp +When executed as +.Nm authpf_single +the number of authpf sessions (parallel logins), for the user running authpf, +is limited to one (1). The other session (belonging to the user) gets terminated. +.Pp Each .Nm process stores its rules in a separate ruleset inside a @@ -441,6 +447,8 @@ .It Pa /etc/authpf/authpf.rules .It Pa /etc/authpf/authpf.message .It Pa /etc/authpf/authpf.problem +.It Pa /var/authpf/ips/ +.It Pa /var/authpf/users/ .El .Sh SEE ALSO .Xr pf 4 , diff -uNr authpf/authpf.c authpf_new/authpf.c --- authpf/authpf.c Tue May 27 23:16:27 2003 +++ authpf_new/authpf.c Tue May 27 23:15:58 2003 @@ -52,8 +52,13 @@ #include "pathnames.h" +#define YES 1 +#define NO 0 + extern int symset(const char *, const char *, int); +extern char *__progname; + static int read_config(FILE *); static void print_message(char *); static int allowed_luser(char *); @@ -66,11 +71,18 @@ char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf"; char rulesetname[PF_RULESET_NAME_SIZE]; +/* disallow users to take more then one IP at the time + * 1 = YES, 0 = NO + */ +int users_once = 1; + FILE *pidfp; +FILE *pidfp2; char *infile; /* file name printed by yyerror() in parse.y */ char luser[MAXLOGNAME]; /* username */ char ipsrc[256]; /* ip as a string */ -char pidfile[MAXPATHLEN]; /* we save pid in this file. */ +char pidfile[MAXPATHLEN]; /* we save pid and username in this file. */ +char pidfile2[MAXPATHLEN]; /* we save pid and ip in this file. */ struct timeval Tstart, Tend; /* start and end times of session */ @@ -87,12 +99,26 @@ int main(int argc, char *argv[]) { - int lockcnt = 0, n, pidfd; + int lockcnt = 0, n, pidfd, pidfd2; FILE *config; struct in_addr ina; struct passwd *pw; char *cp; uid_t uid; + char *progname; + + + progname = __progname; + if (*progname == '-') + progname++; + + /* was authpf invoked as authpf_single to + * to indecate users_once (see above) + */ + if (!strcmp(progname, "authpf_single")) + users_once = YES; + else + users_once = NO; if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld", (long)getpid())) < 0 || n >= sizeof(rulesetname)) { @@ -141,7 +167,7 @@ syslog(LOG_ERR, "cannot find user for uid %u", uid); goto die; } - if (strcmp(pw->pw_shell, PATH_AUTHPF_SHELL)) { + if (strcmp(pw->pw_shell, PATH_AUTHPF_SHELL) && strcmp(pw->pw_shell, "/usr/sbin/authpf_single")) { syslog(LOG_ERR, "wrong shell for user %s, uid %u", pw->pw_name, pw->pw_uid); goto die; @@ -156,8 +182,8 @@ goto die; } - /* Make our entry in /var/authpf as /var/authpf/ipaddr */ - n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc); + /* Make our entry in /var/authpf/ips as /var/authpf/ips/ipaddr */ + n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE_IPS, ipsrc); if (n < 0 || (u_int)n >= sizeof(pidfile)) { syslog(LOG_ERR, "path to pidfile too long"); goto die; @@ -234,6 +260,71 @@ fclose(pidfp); } while (1); + /* Make our entry in /var/authpf/users/ as /var/authpf/users/user */ + n = snprintf(pidfile2, sizeof(pidfile2), "%s/%s", PATH_PIDFILE_USERS, luser); + if (n < 0 || (u_int)n >= sizeof(pidfile2)) { + syslog(LOG_ERR, "path to pidfile2 too long"); + goto die; + } + + if (users_once == YES) { + do { + int save_errno, otherpid = -1; + char otherluip[20]; + + if ((pidfd2 = open(pidfile2, O_RDWR|O_CREAT, 0644)) == -1 || + (pidfp2 = fdopen(pidfd2, "r+")) == NULL) { + if (pidfd2 != -1) + close(pidfd2); + syslog(LOG_ERR, "cannot open or create %s: %s", pidfile2, + strerror(errno)); + goto die; + } + + if (flock(fileno(pidfp2), LOCK_EX|LOCK_NB) == 0) + break; + save_errno = errno; + + /* Mark our pid, and username to our file. */ + + rewind(pidfp2); + /* 31 == MAXLOGNAME - 1 */ + if (fscanf(pidfp2, "%d\n%31s\n", &otherpid, otherluip) != 2) + otherpid = -1; + syslog(LOG_DEBUG, "tried to lock %s, in use by pid %d: %s", + pidfile2, otherpid, strerror(save_errno)); + + if (otherpid > 0) { + syslog(LOG_INFO, + "killing prior auth (pid %d) of user %s by %s", + otherpid, luser, otherluip); + if (kill((pid_t) otherpid, SIGTERM) == -1) { + syslog(LOG_INFO, + "could not kill process %d: (%m)", + otherpid); + } + } + + /* + * we try to kill the previous process and acquire the lock + * for 10 seconds, trying once a second. if we can't after + * 10 attempts we log an error and give up + */ + if (++lockcnt > 10) { + syslog(LOG_ERR, "cannot kill previous authpf (pid %d)", + otherpid); + goto dogdeath; + } + sleep(1); + + /* re-open, and try again. The previous authpf process + * we killed above should unlink the file and release + * it's lock, giving us a chance to get it now + */ + fclose(pidfp2); + } while (1); + } + /* revoke privs */ seteuid(getuid()); setuid(getuid()); @@ -254,6 +345,14 @@ fflush(pidfp); (void) ftruncate(fileno(pidfp), ftell(pidfp)); + /* write pid and src-ip to username file */ + if (users_once == YES) { + rewind(pidfp2); + fprintf(pidfp2, "%ld\n%s\n", (long)getpid(), ipsrc); + fflush(pidfp2); + (void) ftruncate(fileno(pidfp2), ftell(pidfp2)); + } + if (change_filter(1, luser, ipsrc) == -1) { printf("Unable to modify filters\r\n"); do_death(1); @@ -729,7 +828,21 @@ change_filter(0, luser, ipsrc); authpf_kill_states(); remove_stale_rulesets(); + + /* remove username pidfile */ + if (users_once == YES) { + if (pidfp2) + ftruncate(fileno(pidfp2), 0); + if (pidfile2[0]) + if (unlink(pidfile2) == -1) + syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile2); + } + } + else { + if (pidfp2 != 0) + fclose(pidfp2); } + if (pidfp) ftruncate(fileno(pidfp), 0); if (pidfile[0]) @@ -875,4 +988,4 @@ /* never called, no anchors inside anchors, but we need the stub */ fprintf(stderr, "load anchor not supported from authpf\n"); return (1); -} \ No newline at end of file +} diff -uNr authpf/pathnames.h authpf_new/pathnames.h --- authpf/pathnames.h Tue May 27 23:16:33 2003 +++ authpf_new/pathnames.h Tue May 27 23:15:58 2003 @@ -36,5 +36,6 @@ #define PATH_USER_DIR "/etc/authpf/users" #define PATH_BAN_DIR "/etc/authpf/banned" #define PATH_DEVFILE "/dev/pf" -#define PATH_PIDFILE "/var/authpf" +#define PATH_PIDFILE_USERS "/var/authpf/users" +#define PATH_PIDFILE_IPS "/var/authpf/ips" #define PATH_AUTHPF_SHELL "/usr/sbin/authpf"