static int doUtdbrlonly (xmlNode * node, int action) { xmlNode *child; if (node == NULL) return 0; if (ud->top == 0) action = 1; if (action != 0) push_sem_stack (node); switch (ud->stack[ud->top]) { case utdnewpage: doUtdnewpage (node); if (action != 0) pop_sem_stack (); return 1; case utdnewline: doUtdnewline (node); if (action != 0) pop_sem_stack (); return 1; case utddispimg: transcribe_graphic (node, 0); if (action != 0) pop_sem_stack (); return 1; case changetable: change_table (node); return 1; default: break; } child = node->children; while (child) { switch (child->type) { case XML_ELEMENT_NODE: doUtdbrlonly (child, 1); break; case XML_TEXT_NODE: doDotsText (child); break; default: break; } child = child->next; } if (action != 0) pop_sem_stack (); return 1; }
/* * function that removes our stuff when we go away. */ static __dead void do_death(int active) { int ret = 0; if (active) { change_filter(0, luser, ipsrc); change_table(0, ipsrc); authpf_kill_states(); remove_stale_rulesets(); } if (pidfile[0] && (pidfp != NULL)) if (unlink(pidfile) == -1) syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile); exit(ret); }
/* * function that removes our stuff when we go away. */ static __dead void do_death(int active) { int ret = 0; if (active) { change_filter(0, luser, ipsrc); if (user_ip) { change_table(0, ipsrc); authpf_kill_states(); } } if (pidfile[0] && pidfd != -1) if (unlink(pidfile) == -1) syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile); exit(ret); }
/* * User shell for authenticating gateways. Sole purpose is to allow * a user to ssh to a gateway, and have the gateway modify packet * filters to allow access, then remove access when the user finishes * up. Meant to be used only from ssh(1) connections. */ int main(void) { int lockcnt = 0, n; FILE *config; struct in6_addr ina; struct passwd *pw; char *cp; gid_t gid; uid_t uid; const char *shell; login_cap_t *lc; if (strcmp(__progname, "-authpf-noip") == 0) user_ip = 0; config = fopen(PATH_CONFFILE, "r"); if (config == NULL) { syslog(LOG_ERR, "cannot open %s (%m)", PATH_CONFFILE); exit(1); } if ((cp = getenv("SSH_TTY")) == NULL) { syslog(LOG_ERR, "non-interactive session connection for authpf"); exit(1); } if ((cp = getenv("SSH_CLIENT")) == NULL) { syslog(LOG_ERR, "cannot determine connection source"); exit(1); } if (strlcpy(ipsrc, cp, sizeof(ipsrc)) >= sizeof(ipsrc)) { syslog(LOG_ERR, "SSH_CLIENT variable too long"); exit(1); } cp = strchr(ipsrc, ' '); if (!cp) { syslog(LOG_ERR, "corrupt SSH_CLIENT variable %s", ipsrc); exit(1); } *cp = '\0'; if (inet_pton(AF_INET, ipsrc, &ina) != 1 && inet_pton(AF_INET6, ipsrc, &ina) != 1) { syslog(LOG_ERR, "cannot determine IP from SSH_CLIENT %s", ipsrc); exit(1); } /* open the pf device */ dev = open(PATH_DEVFILE, O_RDWR); if (dev == -1) { syslog(LOG_ERR, "cannot open packet filter device (%m)"); goto die; } uid = getuid(); pw = getpwuid(uid); if (pw == NULL) { syslog(LOG_ERR, "cannot find user for uid %u", uid); goto die; } if ((lc = login_getclass(pw->pw_class)) != NULL) shell = login_getcapstr(lc, "shell", pw->pw_shell, pw->pw_shell); else shell = pw->pw_shell; #ifndef __FreeBSD__ login_close(lc); #endif if (strcmp(shell, PATH_AUTHPF_SHELL) && strcmp(shell, PATH_AUTHPF_SHELL_NOIP)) { syslog(LOG_ERR, "wrong shell for user %s, uid %u", pw->pw_name, pw->pw_uid); #ifdef __FreeBSD__ login_close(lc); #else if (shell != pw->pw_shell) free(shell); #endif goto die; } #ifdef __FreeBSD__ login_close(lc); #else if (shell != pw->pw_shell) free(shell); #endif /* * Paranoia, but this data _does_ come from outside authpf, and * truncation would be bad. */ if (strlcpy(luser, pw->pw_name, sizeof(luser)) >= sizeof(luser)) { syslog(LOG_ERR, "username too long: %s", pw->pw_name); goto die; } if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)", luser, (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) { syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld", luser, (long)getpid(), (long)getpid()); if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld", (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) { syslog(LOG_ERR, "pid too large for ruleset name"); goto die; } } /* Make our entry in /var/authpf as ipaddr or username */ n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, user_ip ? ipsrc : luser); if (n < 0 || (u_int)n >= sizeof(pidfile)) { syslog(LOG_ERR, "path to pidfile too long"); goto die; } signal(SIGTERM, need_death); signal(SIGINT, need_death); signal(SIGALRM, need_death); signal(SIGPIPE, need_death); signal(SIGHUP, need_death); signal(SIGQUIT, need_death); signal(SIGTSTP, need_death); /* * If someone else is already using this ip, then this person * wants to switch users - so kill the old process and exit * as well. * * Note, we could print a message and tell them to log out, but the * usual case of this is that someone has left themselves logged in, * with the authenticated connection iconized and someone else walks * up to use and automatically logs in before using. If this just * gets rid of the old one silently, the new user never knows they * could have used someone else's old authentication. If we * tell them to log out before switching users it is an invitation * for abuse. */ do { int save_errno, otherpid = -1; char otherluser[MAXLOGNAME]; if ((pidfd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 || (pidfp = fdopen(pidfd, "r+")) == NULL) { if (pidfd != -1) close(pidfd); syslog(LOG_ERR, "cannot open or create %s: %s", pidfile, strerror(errno)); goto die; } if (flock(fileno(pidfp), LOCK_EX|LOCK_NB) == 0) break; save_errno = errno; /* Mark our pid, and username to our file. */ rewind(pidfp); /* 31 == MAXLOGNAME - 1 */ if (fscanf(pidfp, "%d\n%31s\n", &otherpid, otherluser) != 2) otherpid = -1; syslog(LOG_DEBUG, "tried to lock %s, in use by pid %d: %s", pidfile, otherpid, strerror(save_errno)); if (otherpid > 0) { syslog(LOG_INFO, "killing prior auth (pid %d) of %s by user %s", otherpid, ipsrc, otherluser); 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 (want_death || ++lockcnt > 10) { if (!want_death) syslog(LOG_ERR, "cannot kill previous authpf (pid %d)", otherpid); fclose(pidfp); pidfp = NULL; pidfd = -1; 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(pidfp); pidfp = NULL; pidfd = -1; } while (1); /* whack the group list */ gid = getegid(); if (setgroups(1, &gid) == -1) { syslog(LOG_INFO, "setgroups: %s", strerror(errno)); do_death(0); } /* revoke privs */ uid = getuid(); if (setresuid(uid, uid, uid) == -1) { syslog(LOG_INFO, "setresuid: %s", strerror(errno)); do_death(0); } openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON); if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(pw)) { syslog(LOG_INFO, "user %s prohibited", luser); do_death(0); } if (read_config(config)) { syslog(LOG_ERR, "invalid config file %s", PATH_CONFFILE); do_death(0); } if (remove_stale_rulesets()) { syslog(LOG_INFO, "error removing stale rulesets"); do_death(0); } /* We appear to be making headway, so actually mark our pid */ rewind(pidfp); fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser); fflush(pidfp); (void) ftruncate(fileno(pidfp), ftello(pidfp)); if (change_filter(1, luser, ipsrc) == -1) { printf("Unable to modify filters\r\n"); do_death(0); } if (user_ip && change_table(1, ipsrc) == -1) { printf("Unable to modify table\r\n"); change_filter(0, luser, ipsrc); do_death(0); } while (1) { printf("\r\nHello %s. ", luser); printf("You are authenticated from host \"%s\"\r\n", ipsrc); setproctitle("%s@%s", luser, ipsrc); print_message(PATH_MESSAGE); while (1) { sleep(10); if (want_death) do_death(1); } } /* NOTREACHED */ dogdeath: printf("\r\n\r\nSorry, this service is currently unavailable due to "); printf("technical difficulties\r\n\r\n"); print_message(PATH_PROBLEM); printf("\r\nYour authentication process (pid %ld) was unable to run\n", (long)getpid()); sleep(180); /* them lusers read reaaaaal slow */ die: do_death(0); }
int volumesDoBrlNode (xmlNode * node, int action) { xmlNode *child; if (node == NULL) return 0; if (action == 0) ud->outbuf1_len_so_far = 0; else push_sem_stack (node); switch (ud->stack[ud->top]) { case markhead: if (ud->head_node == NULL) ud->head_node = node; pop_sem_stack (); break; case utdbrlonly: doUtdbrlonly (node, 0); if (action != 0) pop_sem_stack (); return 1; case utdnewpage: doUtdnewpage (node); if (action != 0) pop_sem_stack (); return 1; case utdnewline: doUtdnewline (node); if (action != 0) pop_sem_stack (); return 1; case utddispimg: transcribe_graphic (node, 0); if (action != 0) pop_sem_stack (); return 1; case changetable: change_table (node); return 1; default: break; } child = node->children; while (child) { switch (child->type) { case XML_ELEMENT_NODE: volumesDoBrlNode (child, 1); break; case XML_TEXT_NODE: doDotsText (child); break; default: break; } child = child->next; } if (action != 0) { pop_sem_stack (); return 1; } finishBrlNode (); return 1; }