* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define RCSID "$Id: auth.c,v 1.99 2004/11/04 10:02:26 paulus Exp $"
+#define RCSID "$Id: auth.c,v 1.112 2006/06/18 11:26:00 paulus Exp $"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
+#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
{
FILE *ufile;
int l;
+ uid_t euid;
char u[MAXNAMELEN], p[MAXSECRETLEN];
char *fname;
fname = strdup(*argv);
if (fname == NULL)
novm("+ua file name");
- seteuid(getuid());
+ euid = geteuid();
+ if (seteuid(getuid()) == -1) {
+ option_error("unable to reset uid before opening %s: %m", fname);
+ return 0;
+ }
ufile = fopen(fname, "r");
- seteuid(0);
+ if (seteuid(euid) == -1)
+ fatal("unable to regain privileges: %m");
if (ufile == NULL) {
option_error("unable to open user login data file %s", fname);
return 0;
/*
* An Open on LCP has requested a change from Dead to Establish phase.
- * Do what's necessary to bring the physical layer up.
*/
void
link_required(unit)
{
}
+/*
+ * Bring the link up to the point of being able to do ppp.
+ */
+void start_link(unit)
+ int unit;
+{
+ char *msg;
+
+ new_phase(PHASE_SERIALCONN);
+
+ devfd = the_channel->connect();
+ msg = "Connect script failed";
+ if (devfd < 0)
+ goto fail;
+
+ /* set up the serial device as a ppp interface */
+ /*
+ * N.B. we used to do tdb_writelock/tdb_writeunlock around this
+ * (from establish_ppp to set_ifunit). However, we won't be
+ * doing the set_ifunit in multilink mode, which is the only time
+ * we need the atomicity that the tdb_writelock/tdb_writeunlock
+ * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock.
+ */
+ fd_ppp = the_channel->establish_ppp(devfd);
+ msg = "ppp establishment failed";
+ if (fd_ppp < 0) {
+ status = EXIT_FATAL_ERROR;
+ goto disconnect;
+ }
+
+ if (!demand && ifunit >= 0)
+ set_ifunit(1);
+
+ /*
+ * Start opening the connection and wait for
+ * incoming events (reply, timeout, etc.).
+ */
+ if (ifunit >= 0)
+ notice("Connect: %s <--> %s", ifname, ppp_devnam);
+ else
+ notice("Starting negotiation on %s", ppp_devnam);
+ add_fd(fd_ppp);
+
+ status = EXIT_NEGOTIATION_FAILED;
+ new_phase(PHASE_ESTABLISH);
+
+ lcp_lowerup(0);
+ return;
+
+ disconnect:
+ new_phase(PHASE_DISCONNECT);
+ if (the_channel->disconnect)
+ the_channel->disconnect();
+
+ fail:
+ new_phase(PHASE_DEAD);
+ if (the_channel->cleanup)
+ (*the_channel->cleanup)();
+}
+
/*
* LCP has terminated the link; go to the Dead phase and take the
* physical layer down.
link_terminated(unit)
int unit;
{
- if (phase == PHASE_DEAD)
+ if (phase == PHASE_DEAD || phase == PHASE_MASTER)
return;
+ new_phase(PHASE_DISCONNECT);
+
if (pap_logout_hook) {
pap_logout_hook();
} else {
if (logged_in)
plogout();
}
- new_phase(PHASE_DEAD);
- notice("Connection terminated.");
+
+ if (!doing_multilink) {
+ notice("Connection terminated.");
+ print_link_stats();
+ } else
+ notice("Link terminated.");
+
+ /*
+ * Delete pid files before disestablishing ppp. Otherwise it
+ * can happen that another pppd gets the same unit and then
+ * we delete its pid file.
+ */
+ if (!doing_multilink && !demand)
+ remove_pidfiles();
+
+ /*
+ * If we may want to bring the link up again, transfer
+ * the ppp unit back to the loopback. Set the
+ * real serial device back to its normal mode of operation.
+ */
+ if (fd_ppp >= 0) {
+ remove_fd(fd_ppp);
+ clean_check();
+ the_channel->disestablish_ppp(devfd);
+ if (doing_multilink)
+ mp_exit_bundle();
+ fd_ppp = -1;
+ }
+ if (!hungup)
+ lcp_lowerdown(0);
+ if (!doing_multilink && !demand)
+ script_unsetenv("IFNAME");
+
+ /*
+ * Run disconnector script, if requested.
+ * XXX we may not be able to do this if the line has hung up!
+ */
+ if (devfd >= 0 && the_channel->disconnect) {
+ the_channel->disconnect();
+ devfd = -1;
+ }
+ if (the_channel->cleanup)
+ (*the_channel->cleanup)();
+
+ if (doing_multilink && multilink_master) {
+ if (!bundle_terminating)
+ new_phase(PHASE_MASTER);
+ else
+ mp_bundle_terminated();
+ } else
+ new_phase(PHASE_DEAD);
}
/*
void
link_down(unit)
int unit;
+{
+ if (auth_state != s_down) {
+ notify(link_down_notifier, 0);
+ auth_state = s_down;
+ if (auth_script_state == s_up && auth_script_pid == 0) {
+ update_link_stats(unit);
+ auth_script_state = s_down;
+ auth_script(_PATH_AUTHDOWN);
+ }
+ }
+ if (!doing_multilink) {
+ upper_layers_down(unit);
+ if (phase != PHASE_DEAD && phase != PHASE_MASTER)
+ new_phase(PHASE_ESTABLISH);
+ }
+ /* XXX if doing_multilink, should do something to stop
+ network-layer traffic on the link */
+}
+
+void upper_layers_down(int unit)
{
int i;
struct protent *protp;
- notify(link_down_notifier, 0);
- auth_state = s_down;
- if (auth_script_state == s_up && auth_script_pid == 0) {
- update_link_stats(unit);
- auth_script_state = s_down;
- auth_script(_PATH_AUTHDOWN);
- }
for (i = 0; (protp = protocols[i]) != NULL; ++i) {
if (!protp->enabled_flag)
continue;
}
num_np_open = 0;
num_np_up = 0;
- if (phase != PHASE_DEAD)
- new_phase(PHASE_ESTABLISH);
}
/*
/*
* Tell higher-level protocols that LCP is up.
*/
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->protocol != PPP_LCP && protp->enabled_flag
- && protp->lowerup != NULL)
- (*protp->lowerup)(unit);
+ if (!doing_multilink) {
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->protocol != PPP_LCP && protp->enabled_flag
+ && protp->lowerup != NULL)
+ (*protp->lowerup)(unit);
+ }
if (!auth_required && noauth_addrs != NULL)
set_allowed_addrs(unit, NULL, NULL);
set_allowed_addrs(unit, NULL, NULL);
} else if (!wo->neg_upap || uselogin || !null_login(unit)) {
warn("peer refused to authenticate: terminating link");
- lcp_close(unit, "peer refused to authenticate");
status = EXIT_PEER_AUTH_FAILED;
+ lcp_close(unit, "peer refused to authenticate");
return;
}
}
/*
* Authentication failure: take the link down
*/
- lcp_close(unit, "Authentication failed");
status = EXIT_PEER_AUTH_FAILED;
+ lcp_close(unit, "Authentication failed");
}
/*
* is no point in persisting without any way to get updated
* authentication secrets.
*/
- lcp_close(unit, "Failed to authenticate ourselves to peer");
status = EXIT_AUTH_TOPEER_FAILED;
+ lcp_close(unit, "Failed to authenticate ourselves to peer");
}
/*
int unit, protocol, prot_flavor;
{
int bit;
+ const char *prot = "";
switch (protocol) {
case PPP_CHAP:
bit = CHAP_WITHPEER;
+ prot = "CHAP";
switch (prot_flavor) {
case CHAP_MD5:
bit |= CHAP_MD5_WITHPEER;
if (passwd_from_file)
BZERO(passwd, MAXSECRETLEN);
bit = PAP_WITHPEER;
+ prot = "PAP";
break;
case PPP_EAP:
bit = EAP_WITHPEER;
+ prot = "EAP";
break;
default:
warn("auth_withpeer_success: unknown protocol %x", protocol);
bit = 0;
}
+ notice("%s authentication succeeded", prot);
+
/* Save the authentication method for later. */
auth_done[unit] |= bit;
diff = maxoctets - used;
if(diff < 0) {
notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used);
+ status = EXIT_TRAFFIC_LIMIT;
lcp_close(0, "Traffic limit");
need_holdoff = 0;
- status = EXIT_TRAFFIC_LIMIT;
} else {
TIMEOUT(check_maxoctets, NULL, maxoctets_timeout);
}
if (tlim <= 0) {
/* link is idle: shut it down. */
notice("Terminating connection due to lack of activity.");
+ status = EXIT_IDLE_TIMEOUT;
lcp_close(0, "Link inactive");
need_holdoff = 0;
- status = EXIT_IDLE_TIMEOUT;
} else {
TIMEOUT(check_idle, NULL, tlim);
}
if (auth_required) {
allow_any_ip = 0;
if (!wo->neg_chap && !wo->neg_upap && !wo->neg_eap) {
- wo->neg_chap = 1;
+ wo->neg_chap = chap_mdtype_all != MDTYPE_NONE;
wo->chap_mdtype = chap_mdtype_all;
wo->neg_upap = 1;
wo->neg_eap = 1;
static void
plogout()
{
+ char *tty;
#ifdef USE_PAM
int pam_error;
}
/* Apparently the pam stuff does closelog(). */
reopen_log();
-#else /* ! USE_PAM */
- char *tty;
+#endif /* USE_PAM */
tty = devnam;
if (strncmp(tty, "/dev/", 5) == 0)
tty += 5;
logwtmp(tty, "", ""); /* Wipe out utmp logout entry */
-#endif /* ! USE_PAM */
logged_in = 0;
}
argv[5] = strspeed;
argv[6] = NULL;
- auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL);
+ auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0);
}