Пример #1
0
/*
 * change the system date on the master
 */
static void
mchgdate(struct tsp *msg)
{
	char tname[MAXHOSTNAMELEN];
	char olddate[32];
	struct timeval otime, ntime;

	strlcpy(tname, msg->tsp_name, sizeof(tname));

	xmit(TSP_DATEACK, msg->tsp_seq, &from);

	strlcpy(olddate, date(), sizeof(olddate));

	/* adjust time for residence on the queue */
	gettimeofday(&otime, 0);
	adj_msg_time(msg,&otime);

	timevalsub(&ntime, &msg->tsp_time, &otime);
	if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
		/*
		 * do not change the clock if we can adjust it
		 */
		dictate = 3;
		synch(tvtomsround(ntime));
	} else {
		logwtmp("|", "date", "");
		settimeofday(&msg->tsp_time, 0);
		logwtmp("{", "date", "");
		spreadtime();
	}

	syslog(LOG_NOTICE, "date changed by %s from %s",
	       tname, olddate);
}
Пример #2
0
/*ARGSUSED*/
#endif /* !defined TSP_SETDATE */
static void
reset(const time_t newt, const int nflag)
{
	register const char *	username;
	static struct timeval	tv;	/* static so tv_usec is 0 */

#ifdef EBUG
	return;
#endif /* defined EBUG */
	username = getlogin();
	if (username == NULL || *username == '\0') /* single-user or no tty */
		username = "******";
	tv.tv_sec = newt;
#ifdef TSP_SETDATE
	if (nflag || !netsettime(tv))
#endif /* defined TSP_SETDATE */
	{
		/*
		** "old" entry is always written, for compatibility.
		*/
		logwtmp("|", TIME_NAME, "");
		if (settimeofday(&tv, NULL) == 0) {
			logwtmp("{", TIME_NAME, "");	/* } */
			syslog(LOG_AUTH | LOG_NOTICE, _("date set by %s"),
				username);
		} else	oops("settimeofday");
	}
}
/* ARGSUSED */
void
cleanup(int sig)
{
	char *p, c;

	p = line + sizeof(_PATH_DEV) - 1;
#ifdef SUPPORT_UTMP
	if (logout(p))
		logwtmp(p, "", "");
#endif
#ifdef SUPPORT_UTMPX
	if (logoutx(p, 0, DEAD_PROCESS))
		logwtmpx(p, "", "", 0, DEAD_PROCESS);
#endif
	(void)chmod(line, 0666);
	(void)chown(line, 0, 0);
	c = *p; *p = 'p';
	(void)chmod(line, 0666);
	(void)chown(line, 0, 0);
	*p = c;
	if (ttyaction(line, "telnetd", "root"))
		syslog(LOG_ERR, "%s: ttyaction failed", line);
	(void) shutdown(net, 2);
	exit(1);
}
Пример #4
0
void
cleanup(int sig)
{
#if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP)
    rmut();
#ifdef HAVE_VHANGUP
#ifndef __sgi
    vhangup(); /* XXX */
#endif
#endif
#else
    char *p;

    p = line + sizeof("/dev/") - 1;
    if (logout(p))
	logwtmp(p, "", "");
    chmod(line, 0666);
    chown(line, 0, 0);
    *p = 'p';
    chmod(line, 0666);
    chown(line, 0, 0);
#endif
    shutdown(net, 2);
    exit(1);
}
Пример #5
0
/*
 * plogout - Logout the user.
 */
static void
plogout(void)
{
#ifdef USE_PAM
    struct pam_conv pam_conversation;
    pam_handle_t *pamh;
    int pam_error;
/*
 * Fill the pam_conversion structure. The PAM specification states that the
 * session must be able to be closed by a totally different handle from which
 * it was created. Hold the PAM group to their own specification!
 */
    memset (&pam_conversation, '\0', sizeof (struct pam_conv));
    pam_conversation.conv = &pam_conv;

    pam_error = pam_start ("ppp", user, &pam_conversation, &pamh);
    if (pam_error == PAM_SUCCESS) {
        pam_set_item (pamh, PAM_TTY, devnam);
        pam_close_session (pamh, PAM_SILENT);
	pam_end (pamh, PAM_SUCCESS);
    }

#else
    char *tty;

    tty = devnam;
    if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
	tty += 5;
    logwtmp(tty, "", "");		/* Wipe out wtmp logout entry */
    logout(tty);			/* Wipe out utmp */
#endif

    logged_in = FALSE;
}
Пример #6
0
/* Records that the user has logged out. */
void
record_logout(pid_t pid, const char *tty)
{
	const char *line = tty + 5;	/* /dev/ttyq8 -> ttyq8 */
	if (logout(line))
		logwtmp(line, "", "");
}
Пример #7
0
/*
 * Record login in wtmp file.
 */
void
dologin(struct passwd *pw, struct sockaddr_in *sin)
{
	char line[32];
	char remotehost[32];
	int wtmp, f;
	struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr,
		sizeof (struct in_addr), AF_INET);

	if (hp) {
		strncpy(remotehost, hp->h_name, sizeof (remotehost));
		endhostent();
	} else
		strncpy(remotehost, inet_ntoa(sin->sin_addr),
		    sizeof (remotehost));

	sprintf(line, "uucp%.4d", getpid());

	logwtmp (line, pw->pw_name, remotehost);

#if defined (PATH_LASTLOG) && defined (HAVE_STRUCT_LASTLOG)
#define	SCPYN(a, b)	strncpy(a, b, sizeof (a))
	if ((f = open(PATH_LASTLOG, O_RDWR)) >= 0) {
		struct lastlog ll;

		time(&ll.ll_time);
		lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
		strcpy(line, remotehost);
		SCPYN(ll.ll_line, line);
		SCPYN(ll.ll_host, remotehost);
		(void) write(f, (char *) &ll, sizeof ll);
		(void) close(f);
	}
#endif
}
static void ip_up(void *opaque, int arg)
{
  char *user = reduce(peer_authname);
  if (debug)
    notice("pptpd-logwtmp.so ip-up %s %s %s", ifname, user, 
	   pptpd_original_ip);
  logwtmp(ifname, user, pptpd_original_ip);
}
Пример #9
0
/*
 * Close out the accounting files for a login session.
 * NB: should send a message to the session logger to avoid blocking.
 */
void
clear_session_logs(session_t *sp)
{
	char *line = sp->se_device + sizeof(_PATH_DEV) - 1;

	if (logout(line))
		logwtmp(line, "", "");
}
Пример #10
0
/*
 * Run the system startup script.
 */
state_func_t
runcom(void)
{
	state_func_t next_transition;

	if ((next_transition = run_script(_PATH_RUNCOM)) != 0)
		return next_transition;

	runcom_mode = AUTOBOOT;		/* the default */
	/* NB: should send a message to the session logger to avoid blocking. */
	logwtmp("~", "reboot", "");
	return (state_func_t) read_ttys;
}
Пример #11
0
static void ip_up(void *opaque, int arg)
{
  char *user = peer_authname;
  if (pptpd_logwtmp_strip_domain) {
    char *sep = strstr(user, "//");
    if (sep != NULL)
      user = sep + 2;
  }
  if (debug)
    notice("pptpd-logwtmp.so ip-up %s %s %s", ifname, user, 
	   pptpd_original_ip);
  logwtmp(ifname, user, pptpd_original_ip);
}
Пример #12
0
long
pty_logwtmp(const char *tty, const char *user, const char *host)
{
#ifndef HAVE_LOGWTMP
    PTY_STRUCT_UTMPX utx;
    int loggingin;
    size_t len;
    const char *cp;
    char utmp_id[5];
#endif

#ifdef HAVE_LOGWTMP
    logwtmp(tty,user,host);
    return 0;
#else

    loggingin = (user[0] != '\0');

    memset(&utx, 0, sizeof(utx));
    strncpy(utx.ut_line, tty, sizeof(utx.ut_line));
    strncpy(utx.ut_user, user, sizeof(utx.ut_user));
#if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_HOST))	   \
	|| (!defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_HOST))
    strncpy(utx.ut_host, host, sizeof(utx.ut_host));
    utx.ut_host[sizeof(utx.ut_host) - 1] = '\0';
#endif
#ifdef HAVE_SETUTXENT
    gettimeofday(&utx.ut_tv, NULL);
#else
    (void)time(&utx.ut_time);
#endif
    utx.ut_pid = (loggingin ? getpid() : 0);
    utx.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);

    len = strlen(tty);
    if (len >= 2)
	cp = tty + len - 2;
    else
	cp = tty;
    snprintf(utmp_id, sizeof(utmp_id), "kr%s", cp);
    strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id));

#ifdef HAVE_SETUTXENT
    return ptyint_update_wtmpx(&utx);
#else
    return ptyint_update_wtmp(&utx);
#endif

#endif /* !HAVE_LOGWTMP */
}
Пример #13
0
/* Records that the user has logged out. */
void
record_logout(pid_t pid, const char *tty)
{
#if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
	const char *line = tty + 5;	/* /dev/ttyq8 -> ttyq8 */
#endif
#ifdef SUPPORT_UTMP
	if (logout(line))
		logwtmp(line, "", "");
#endif
#ifdef SUPPORT_UTMPX
	/* XXX: no exit info yet */
	if (logoutx(line, 0, DEAD_PROCESS))
		logwtmpx(line, "", "", 0, DEAD_PROCESS);
#endif
}
Пример #14
0
PAM_EXTERN int
pam_sm_close_session (pam_handle_t *pamh, int flags,
		      int argc, const char **argv)
{
    const char *terminal_line;

    if (!(_pam_parse(pamh, flags, argc, argv) & LASTLOG_WTMP))
	return PAM_SUCCESS;

    terminal_line = get_tty(pamh);

    /* Wipe out utmp logout entry */
    logwtmp(terminal_line, "", "");

    return PAM_SUCCESS;
}
Пример #15
0
/* Update umtp & wtmp as necessary, and change tty & pty permissions back to
   what they should be.  */
void
cleanup_session (char *tty, int pty_fd)
{
  char *line;

# ifdef PATH_TTY_PFX
  if (strncmp (tty, PATH_TTY_PFX, sizeof PATH_TTY_PFX - 1) == 0)
    line = tty + sizeof PATH_TTY_PFX - 1;
  else
# endif /* PATH_TTY_PFX */
    line = tty;

  if (logout (line))
    logwtmp (line, "", "");

  chmod (tty, 0666);
  chown (tty, 0, 0);
  fchmod (pty_fd, 0666);
  fchown (pty_fd, 0, 0);
}
Пример #16
0
void
dologout (void)
{
  int pid;

#ifdef HAVE_WAITPID
  while ((pid = waitpid (-1, 0, WNOHANG)) > 0)
#else
# ifdef HAVE_WAIT3
  while ((pid = wait3 (0, WNOHANG, 0)) > 0)
# else
  while ((pid = wait (0)) > 0)
# endif	/* HAVE_WAIT3 */
#endif /* HAVE_WAITPID */
    {
      char line[100];
      sprintf (line, "uucp%.4d", pid);
      logwtmp (line, "", "");
    }
}
Пример #17
0
static int
syslogin_perform_logout(struct logininfo *li)
{
# ifdef HAVE_LOGOUT
	char line[UT_LINESIZE];

	(void)line_stripname(line, li->line, sizeof(line));

	if (!logout(line))
		logit("%s: logout() returned an error", __func__);
#  ifdef HAVE_LOGWTMP
	else
		logwtmp(line, "", "");
#  endif
	/* FIXME: (ATL - if the need arises) What to do if we have
	 * login, but no logout?  what if logout but no logwtmp? All
	 * routines are in libutil so they should all be there,
	 * but... */
# endif
	return (1);
}
Пример #18
0
long
pty_logwtmp(const char *tty, const char *user, const char *host)
{
    struct utmp ut;

#ifdef HAVE_LOGWTMP
    logwtmp(tty,user,host);
    return 0;
#else

    memset(&ut, 0, sizeof(ut));
#ifdef HAVE_STRUCT_UTMP_UT_HOST
    strncpy(ut.ut_host, host, sizeof(ut.ut_host));
    ut.ut_host[sizeof(ut.ut_host) - 1] = '\0';
#endif
    strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
    strncpy(ut.ut_name, user, sizeof(ut.ut_name));
    return ptyint_update_wtmp(&ut);

#endif /* !HAVE_LOGWTMP */
}
Пример #19
0
RETSIGTYPE
cleanup (int signo ARG_UNUSED)
{
  char *p;

  p = line + sizeof (PATH_DEV) - 1;
#ifdef UTMPX
  utmp_logout (p);
  chmod (line, 0644);
  chown (line, 0, 0);
#else
  if (logout (p))
    logwtmp (p, "", "");
  chmod (line, 0666);
  chown (line, 0, 0);
  *p = 'p';
  chmod (line, 0666);
  chown (line, 0, 0);
#endif
  shutdown (netf, 2);
  exit (1);
}
Пример #20
0
static int
syslogin_perform_logout(struct logininfo *li)
{
# ifdef HAVE_LOGOUT
	char line[8];

	(void)line_stripname(line, li->line, sizeof(line));

	if (!logout(line)) {
		dropbear_log(LOG_WARNING, "syslogin_perform_logout: logout(%s) returned an error: %s", line, strerror(errno));
#  ifdef HAVE_LOGWTMP
	} else {
		logwtmp(line, "", "");
#  endif
	}
	/* FIXME: (ATL - if the need arises) What to do if we have
	 * login, but no logout?  what if logout but no logwtmp? All
	 * routines are in libutil so they should all be there,
	 * but... */
# endif
	return 1;
}
Пример #21
0
/*
 * Record login in wtmp file.
 */
void dologin(struct passwd *pw, struct sockaddr *sin)
{
#if __FreeBSD_version >= 900007
	struct utmpx ut;

	memset(&ut, 0, sizeof ut);
	ut.ut_type = USER_PROCESS;
	gettimeofday(&ut.ut_tv, NULL);
	ut.ut_pid = getpid();
	snprintf(ut.ut_id, sizeof ut.ut_id, "%xuucp", ut.ut_pid);
	SCPYN(ut.ut_user, pw->pw_name);
	realhostname_sa(ut.ut_host, sizeof ut.ut_host, sin, sin->sa_len);
	pututxline(&ut);
#else
	char line[32];
	char remotehost[UT_HOSTSIZE + 1];
	int f;
	time_t cur_time;

	realhostname_sa(remotehost, sizeof(remotehost) - 1, sin, sin->sa_len);
	remotehost[sizeof remotehost - 1] = '\0';

	/* hack, but must be unique and no tty line */
	sprintf(line, "uucp%ld", (long)getpid());
	time(&cur_time);
	if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
		struct lastlog ll;

		ll.ll_time = cur_time;
		lseek(f, (off_t)pw->pw_uid * sizeof(struct lastlog), L_SET);
		SCPYN(ll.ll_line, line);
		SCPYN(ll.ll_host, remotehost);
		(void) write(f, (char *) &ll, sizeof ll);
		(void) close(f);
	}
	logwtmp(line, pw->pw_name, remotehost);
#endif
}
Пример #22
0
/*
 * cleanup()
 *
 * This is the routine to call when we are all through, to
 * clean up anything that needs to be cleaned up.
 */
void cleanup(int sig) {
    char *p;
    (void)sig;

    p = line + sizeof("/dev/") - 1;
    if (logout(p)) logwtmp(p, "", "");
#ifdef PARANOID_TTYS
    /*
     * dholland 16-Aug-96 chmod the tty when not in use
     * This will make it harder to attach unwanted stuff to it
     * (which is a security risk) but will break some programs.
     */
    chmod(line, 0600);
#else
    chmod(line, 0666);
#endif
    chown(line, 0, 0);
    *p = 'p';
    chmod(line, 0666);
    chown(line, 0, 0);
    shutdown(net, 2);
    exit(0);
}
Пример #23
0
void dologout(void)
{
	int status;
	pid_t pid;
#if __FreeBSD_version >= 900007
	struct utmpx ut;
#else
	char line[32];
#endif

	while ((pid=wait((int *)&status)) > 0) {
#if __FreeBSD_version >= 900007
		memset(&ut, 0, sizeof ut);
		ut.ut_type = DEAD_PROCESS;
		gettimeofday(&ut.ut_tv, NULL);
		ut.ut_pid = pid;
		snprintf(ut.ut_id, sizeof ut.ut_id, "%xuucp", pid);
		pututxline(&ut);
#else
		sprintf(line, "uucp%ld", (long)pid);
		logwtmp(line, "", "");
#endif
	}
}
Пример #24
0
slave()
{
	int length;
	int senddateack;
	long electiontime, refusetime, looktime;
	u_short seq;
	char candidate[MAXHOSTNAMELEN];
	struct tsp *msg, to, *readmsg();
	struct sockaddr_in saveaddr, msaveaddr;
	struct timeval wait;
	struct timeval time, otime;
	struct tsp *answer, *acksend();
	int timeout();
	char *date();
	long casual();
	int bytenetorder();
	char olddate[32];
	struct sockaddr_in server;
	register struct netinfo *ntp;
	int ind;
	struct tsp resp;
	extern int Mflag;
	extern int justquit;
#ifdef MEASURE
	extern FILE *fp;
#endif
	if (slavenet) {
		resp.tsp_type = TSP_SLAVEUP;
		resp.tsp_vers = TSPVERSION;
		(void)strcpy(resp.tsp_name, hostname);
		bytenetorder(&resp);
		if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
		    &slavenet->dest_addr, sizeof(struct sockaddr_in)) < 0) {
			syslog(LOG_ERR, "sendto: %m");
			exit(1);
		}
	}

	if (status & MASTER) {
#ifdef MEASURE
		if (fp == NULL) {
			fp = fopen("/usr/adm/timed.masterlog", "w");
			setlinebuf(fp);
		}
#endif
		syslog(LOG_INFO, "THIS MACHINE IS A SUBMASTER");
		if (trace) {
			fprintf(fd, "THIS MACHINE IS A SUBMASTER\n");
		}
		for (ntp = nettab; ntp != NULL; ntp = ntp->next)
			if (ntp->status == MASTER)
				masterup(ntp);

	} else {
		syslog(LOG_INFO, "THIS MACHINE IS A SLAVE");
		if (trace) {
			fprintf(fd, "THIS MACHINE IS A SLAVE\n");
		}
	}

	seq = 0;
	senddateack = OFF;
	refusetime = 0;

	(void)gettimeofday(&time, (struct timezone *)0);
	electiontime = time.tv_sec + delay2;
	if (Mflag)
		if (justquit)
			looktime = time.tv_sec + delay2;
		else 
			looktime = 1;
	else
		looktime = 0;

loop:
	length = sizeof(struct sockaddr_in);
	(void)gettimeofday(&time, (struct timezone *)0);
	if (time.tv_sec > electiontime) {
		if (trace) 
			fprintf(fd, "election timer expired\n");
		longjmp(jmpenv, 1);
	}
	if (looktime && time.tv_sec > looktime) {
		if (trace) 
			fprintf(fd, "Looking for nets to master and loops\n");
		
		if (nignorednets > 0) {
			for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
				if (ntp->status == IGNORE) {
					lookformaster(ntp);
					if (ntp->status == MASTER)
						masterup(ntp);
					else
						ntp->status = IGNORE;
				}
			}
			setstatus();
#ifdef MEASURE
			/*
			 * Check to see if we just became master
			 * (file not open)
			 */
			if (fp == NULL) {
				fp = fopen("/usr/adm/timed.masterlog", "w");
				setlinebuf(fp);
			}
#endif
		}

		for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
		    if (ntp->status == MASTER) {
			to.tsp_type = TSP_LOOP;
			to.tsp_vers = TSPVERSION;
			to.tsp_seq = sequence++;
			to.tsp_hopcnt = 10;
			(void)strcpy(to.tsp_name, hostname);
			bytenetorder(&to);
			if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
			    &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) {
				syslog(LOG_ERR, "sendto: %m");
				exit(1);
			}
		    }
		}
		(void)gettimeofday(&time, (struct timezone *)0);
		looktime = time.tv_sec + delay2;
	}
	wait.tv_sec = electiontime - time.tv_sec + 10;
	wait.tv_usec = 0;
	msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL);
	if (msg != NULL) {
		switch (msg->tsp_type) {
		case TSP_SETDATE:
#ifdef TESTING
		case TSP_TEST:
#endif
		case TSP_MSITE:
		case TSP_TRACEOFF:
		case TSP_TRACEON:
			break;
		case TSP_MASTERUP:
			if (fromnet == NULL) {
				if (trace) {
					fprintf(fd, "slave ignored: ");
					print(msg, &from);
				}
				goto loop;
			}
			break;
		default:
			if (fromnet == NULL || fromnet->status == IGNORE) {
				if (trace) {
					fprintf(fd, "slave ignored: ");
					print(msg, &from);
				}
				goto loop;
			}
			break;
		}

		switch (msg->tsp_type) {

		case TSP_ADJTIME:
			if (fromnet->status != SLAVE)
				break;
			(void)gettimeofday(&time, (struct timezone *)0);
			electiontime = time.tv_sec + delay2;
			if (seq != msg->tsp_seq) {
				seq = msg->tsp_seq;
				if ((status & SUBMASTER) == SUBMASTER) {
					synch((msg->tsp_time.tv_sec * 1000) + 
					    (msg->tsp_time.tv_usec / 1000));
				} else {
					adjclock(&(msg->tsp_time));
				}
			}
			break;
		case TSP_SETTIME:
			if (fromnet->status != SLAVE)
				break;
			if (seq == msg->tsp_seq)
				break;

			seq = msg->tsp_seq;

			(void)strcpy(olddate, date());
			(void)gettimeofday(&otime, (struct timezone *)0);
			(void)settimeofday(&msg->tsp_time,
				(struct timezone *)0);
			syslog(LOG_NOTICE, "date changed by %s from: %s",
				msg->tsp_name, olddate);
			logwtmp(otime, msg->tsp_time);
			if ((status & SUBMASTER) == SUBMASTER)
				spreadtime();
			(void)gettimeofday(&time, (struct timezone *)0);
			electiontime = time.tv_sec + delay2;

			if (senddateack == ON) {
				senddateack = OFF;
				msg->tsp_type = TSP_DATEACK;
				(void)strcpy(msg->tsp_name, hostname);
				bytenetorder(msg);
				length = sizeof(struct sockaddr_in);
				if (sendto(sock, (char *)msg, 
						sizeof(struct tsp), 0,
						&saveaddr, length) < 0) {
					syslog(LOG_ERR, "sendto: %m");
					exit(1);
				}
			}
			break;
		case TSP_MASTERUP:
			if (slavenet && fromnet != slavenet)
				break;
			makeslave(fromnet);
			setstatus();
			msg->tsp_type = TSP_SLAVEUP;
			msg->tsp_vers = TSPVERSION;
			(void)strcpy(msg->tsp_name, hostname);
			bytenetorder(msg);
			answerdelay();
			length = sizeof(struct sockaddr_in);
			if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, 
						&from, length) < 0) {
				syslog(LOG_ERR, "sendto: %m");
				exit(1);
			}
			backoff = 1;
			delay2 = casual((long)MINTOUT, (long)MAXTOUT);
			(void)gettimeofday(&time, (struct timezone *)0);
			electiontime = time.tv_sec + delay2;
			refusetime = 0;
			break;
		case TSP_MASTERREQ:
			if (fromnet->status != SLAVE)
				break;
			(void)gettimeofday(&time, (struct timezone *)0);
			electiontime = time.tv_sec + delay2;
			break;
		case TSP_SETDATE:
			saveaddr = from;
			msg->tsp_type = TSP_SETDATEREQ;
			msg->tsp_vers = TSPVERSION;
			(void)strcpy(msg->tsp_name, hostname);
			for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
				if (ntp->status == SLAVE)
					break;
			}
			if (ntp == NULL)
				break;
			answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR,
			    TSP_DATEACK, ntp);
			if (answer != NULL) {
				msg->tsp_type = TSP_ACK;
				bytenetorder(msg);
				length = sizeof(struct sockaddr_in);
				if (sendto(sock, (char *)msg,
				    sizeof(struct tsp), 0, &saveaddr,
				    length) < 0) {
					syslog(LOG_ERR, "sendto: %m");
					exit(1);
				}
				senddateack = ON;
			}
			break;
		case TSP_SETDATEREQ:
			saveaddr = from;
			if (status != SUBMASTER || fromnet->status != MASTER)
				break;
			for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
				if (ntp->status == SLAVE)
					break;
			}
			ind = findhost(msg->tsp_name);
			if (ind < 0) {
			    syslog(LOG_WARNING,
				"DATEREQ from uncontrolled machine");
			    break;
			}
			syslog(LOG_DEBUG,
			    "forwarding date change request for %s",
			    msg->tsp_name);
			(void)strcpy(msg->tsp_name, hostname);
			answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR,
			    TSP_DATEACK, ntp);
			if (answer != NULL) {
				msg->tsp_type = TSP_DATEACK;
				bytenetorder(msg);
				length = sizeof(struct sockaddr_in);
				if (sendto(sock, (char *)msg,
				    sizeof(struct tsp), 0, &saveaddr,
				    length) < 0) {
					syslog(LOG_ERR, "sendto: %m");
					exit(1);
				}
			}
			break;
		case TSP_TRACEON:
			if (!(trace)) {
				fd = fopen(tracefile, "w");
				setlinebuf(fd);
				fprintf(fd, "Tracing started on: %s\n\n", 
								date());
			}
			trace = ON;
			break;
		case TSP_TRACEOFF:
			if (trace) {
				fprintf(fd, "Tracing ended on: %s\n", date());
				(void)fclose(fd);
			}
#ifdef GPROF
			moncontrol(0);
			_mcleanup();
			moncontrol(1);
#endif
			trace = OFF;
			break;
		case TSP_SLAVEUP:
			if ((status & MASTER) && fromnet->status == MASTER) {
				ind = addmach(msg->tsp_name, &from);
				newslave(ind, msg->tsp_seq);
			}
			break;
		case TSP_ELECTION:
			if (fromnet->status == SLAVE) {
				(void)gettimeofday(&time, (struct timezone *)0);
				electiontime = time.tv_sec + delay2;
				seq = 0;            /* reset sequence number */
				if (time.tv_sec < refusetime)
					msg->tsp_type = TSP_REFUSE;
				else {
					msg->tsp_type = TSP_ACCEPT;
					refusetime = time.tv_sec + 30;
				}
				(void)strcpy(candidate, msg->tsp_name);
				(void)strcpy(msg->tsp_name, hostname);
				answerdelay();
				server = from;
				answer = acksend(msg, &server, candidate, TSP_ACK,
				    (struct netinfo *)NULL);
				if (answer == NULL)
					syslog(LOG_WARNING,
					   "no answer from master candidate\n");
			} else {	/* fromnet->status == MASTER */
				to.tsp_type = TSP_QUIT;
				(void)strcpy(to.tsp_name, hostname);
				server = from;
				answer = acksend(&to, &server, msg->tsp_name,
				    TSP_ACK, (struct netinfo *)NULL);
				if (answer == NULL) {
					syslog(LOG_WARNING,
					    "election error: no reply to QUIT");
				} else {
					(void) addmach(msg->tsp_name, &from);
				}
			}
			break;
                case TSP_CONFLICT:
			if (fromnet->status != MASTER)
				break;
                        /*
                         * After a network partition, there can be
                         * more than one master: the first slave to
                         * come up will notify here the situation.
                         */
                        (void)strcpy(to.tsp_name, hostname);

                        if (fromnet == NULL)
                                break;
                        for(;;) {
                                to.tsp_type = TSP_RESOLVE;
                                answer = acksend(&to, &fromnet->dest_addr,
                                    (char *)ANYADDR, TSP_MASTERACK, fromnet);
                                if (answer == NULL)
                                        break;
                                to.tsp_type = TSP_QUIT;
                                server = from;
                                msg = acksend(&to, &server, answer->tsp_name,
                                    TSP_ACK, (struct netinfo *)NULL);
                                if (msg == NULL) {
                                        syslog(LOG_WARNING,
					    "conflict error: no reply to QUIT");
				} else {
                                        (void) addmach(answer->tsp_name, &from);
				}
                        }
                        masterup(fromnet);
                        break;
		case TSP_MSITE:
			if (!slavenet)
				break;
			msaveaddr = from;
			msg->tsp_type = TSP_MSITEREQ;
			msg->tsp_vers = TSPVERSION;
			(void)strcpy(msg->tsp_name, hostname);
			answer = acksend(msg, &slavenet->dest_addr,
					 (char *)ANYADDR, TSP_ACK, slavenet);
			if (answer != NULL) {
				msg->tsp_type = TSP_ACK;
				length = sizeof(struct sockaddr_in);
				bytenetorder(msg);
				if (sendto(sock, (char *)msg, 
						sizeof(struct tsp), 0,
						&msaveaddr, length) < 0) {
					syslog(LOG_ERR, "sendto: %m");
					exit(1);
				}
			}
			break;
		case TSP_ACCEPT:
		case TSP_REFUSE:
			break;
		case TSP_RESOLVE:
			break;
		case TSP_QUIT:
			/* become slave */
#ifdef MEASURE
			if (fp != NULL) {
				(void)fclose(fp);
				fp = NULL;
			}
#endif
			longjmp(jmpenv, 2);
			break;
#ifdef TESTING
		case TSP_TEST:
			electiontime = 0;
			break;
#endif
		case TSP_MSITEREQ:
			if (status & MASTER)
				break;
			if (trace) {
				fprintf(fd, "garbage: ");
				print(msg, &from);
			}
			break;

		case TSP_LOOP:
			/* looking for loops of masters */
			if ( !(status & MASTER))
				break;
			if (fromnet->status == SLAVE) {
			    if ( !strcmp(msg->tsp_name, hostname)) {
				  for(;;) {
				    to.tsp_type = TSP_RESOLVE;
				    answer = acksend(&to, &fromnet->dest_addr,
					(char *)ANYADDR, TSP_MASTERACK,
					fromnet);
				    if (answer == NULL)
					    break;
				    to.tsp_type = TSP_QUIT;
				    (void)strcpy(to.tsp_name, hostname);
				    server = from;
				    answer = acksend(&to, &server,
					answer->tsp_name, TSP_ACK,
					(struct netinfo *)NULL);
				    if (answer == NULL) {
					syslog(LOG_ERR, "loop kill error");
				    } else {
					electiontime = 0;
				    }
				  }
			    } else {
				if (msg->tsp_hopcnt-- <= 0)
				    break;
				bytenetorder(msg);
				ntp = nettab;
				for (; ntp != NULL; ntp = ntp->next)
				    if (ntp->status == MASTER)
					if (sendto(sock, (char *)msg, 
					    sizeof(struct tsp), 0,
					    &ntp->dest_addr, length) < 0) {
						syslog(LOG_ERR, "sendto: %m");
						exit(1);
					}
			    }
			} else {
			    /*
			     * We should not have received this from a net
			     * we are master on.  There must be two masters
			     * in this case.
			     */
			    if (fromnet->my_addr.s_addr == from.sin_addr.s_addr)
				break;
			    for (;;) {
				to.tsp_type = TSP_RESOLVE;
				answer = acksend(&to, &fromnet->dest_addr,
				    (char *)ANYADDR, TSP_MASTERACK,
				    fromnet);
				if (answer == NULL)
					break;
				to.tsp_type = TSP_QUIT;
				(void)strcpy(to.tsp_name, hostname);
				server = from;
				answer = acksend(&to, &server, answer->tsp_name,
				    TSP_ACK, (struct netinfo *)NULL);
				if (answer == NULL) {
					syslog(LOG_ERR, "loop kill error2");
				} else {
					(void)addmach(msg->tsp_name, &from);
				}
			    }
			}
			break;
		default:
			if (trace) {
				fprintf(fd, "garbage: ");
				print(msg, &from);
			}
			break;
		}
	}
	goto loop;
}
Пример #25
0
static void ip_down(void *opaque, int arg)
{
  if (debug) 
    notice("pptpd-logwtmp.so ip-down %s", ifname);
  logwtmp(ifname, "", "");
}
Пример #26
0
void
setthetime(char *p)
{
	struct tm *lt;
	struct timeval tv;
	char *dot, *t;
	int yearset = 0;

	for (t = p, dot = NULL; *t; ++t) {
		if (isdigit((unsigned char)*t))
			continue;
		if (*t == '.' && dot == NULL) {
			dot = t;
			continue;
		}
		badformat();
	}

	lt = localtime(&tval);

	lt->tm_isdst = -1;			/* correct for DST */

	if (dot != NULL) {			/* .SS */
		*dot++ = '\0';
		if (strlen(dot) != 2)
			badformat();
		lt->tm_sec = ATOI2(dot);
		if (lt->tm_sec > 61)
			badformat();
	} else
		lt->tm_sec = 0;

	switch (strlen(p)) {
	case 12:				/* cc */
		lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
		yearset = 1;
		/* FALLTHROUGH */
	case 10:				/* yy */
		if (!yearset) {
			/* mask out current year, leaving only century */
			lt->tm_year = ((lt->tm_year / 100) * 100);
		}
		lt->tm_year += ATOI2(p);
		/* FALLTHROUGH */
	case 8:					/* mm */
		lt->tm_mon = ATOI2(p);
		if ((lt->tm_mon > 12) || !lt->tm_mon)
			badformat();
		--lt->tm_mon;			/* time struct is 0 - 11 */
		/* FALLTHROUGH */
	case 6:					/* dd */
		lt->tm_mday = ATOI2(p);
		if ((lt->tm_mday > 31) || !lt->tm_mday)
			badformat();
		/* FALLTHROUGH */
	case 4:					/* HH */
		lt->tm_hour = ATOI2(p);
		if (lt->tm_hour > 23)
			badformat();
		/* FALLTHROUGH */
	case 2:					/* MM */
		lt->tm_min = ATOI2(p);
		if (lt->tm_min > 59)
			badformat();
		break;
	default:
		badformat();
	}

	/* convert broken-down time to UTC clock time */
	if ((tval = mktime(lt)) < 0)
		errx(1, "specified date is outside allowed range");

	if (jflag)
		return;

	/* set the time */
	if (slidetime) {
		struct timeval tv_current;

		if (gettimeofday(&tv_current, NULL) == -1)
			err(1, "Could not get local time of day");

		tv.tv_sec = tval - tv_current.tv_sec;
		tv.tv_usec = 0;
		if (adjtime(&tv, NULL) == -1)
			errx(1, "adjtime");
	} else {
#ifndef SMALL
		logwtmp("|", "date", "");
#endif
		tv.tv_sec = tval;
		tv.tv_usec = 0;
		if (settimeofday(&tv, NULL))
			err(1, "settimeofday");
#ifndef SMALL
		logwtmp("{", "date", "");
#endif
	}

	if ((p = getlogin()) == NULL)
		p = "???";
	syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
}
Пример #27
0
void
exec_shell(struct conf *cfp, int fd, int parentfd)
{
	int master, slave;
	pid_t pid;
	char line[MAXPATHLEN];	
	char *tty;
#ifdef HAVE_UTMP_H
	struct utmp ut;
#elif HAVE_UTMPX_H
	struct utmpx ut;
	struct timeval tv;
#endif

#if defined(HAVE_UTMP_H) || defined(HAVE_UTMPX_H)
	memset(&ut, 0, sizeof(ut));
#endif

	if (pipe(pipechld) < 0) {
		syslog(LOG_ERR, "exec_shell() pipe %m");
		_exit(1);
	}

	(void)non_blocking(pipechld[0]);
	(void)non_blocking(pipechld[1]);

	if (openpty(&master, &slave, line, NULL, NULL) == -1) {
		syslog(LOG_ERR, "openpty %m");
		_exit(1) ;
	}

	/*
	 * pts/x compatible
	 */
	if ((tty = strstr(line, "/dev/"))) 
        	tty += 5;
       	else
       		tty = line;
#if defined(HAVE_UTMP_H) || defined(HAVE_UTMPX_H)
	if (cfp->utmp) {
		if (cfp->utname) {
#ifdef HAVE_UTMP_H
                	(void)strncpy(ut.ut_name, cfp->utname, 
				sizeof(ut.ut_name)-1);
			ut.ut_name[sizeof(ut.ut_name)-1] = '\0';
#elif HAVE_UTMPX_H
			(void)strncpy(ut.ut_user, cfp->utname,
				sizeof(ut.ut_user)-1);
			ut.ut_user[sizeof(ut.ut_user)-1] = '\0';
#endif
		} else {
			struct passwd *pw;
			pw = get_pwentry(cfp->havesetuser ? cfp->setuser : \
				0);
#ifdef HAVE_UTMP_H
			(void)strncpy(ut.ut_name, pw->pw_name, 
				sizeof(ut.ut_name)-1); 

			ut.ut_name[sizeof(ut.ut_name)-1] = '\0';
#elif HAVE_UTMPX_H
			(void)strncpy(ut.ut_user, pw->pw_name,
				sizeof(ut.ut_user)-1);

			ut.ut_user[sizeof(ut.ut_user)-1] = '\0';
#endif
		}
    
		(void)strncpy(ut.ut_line, tty, sizeof(ut.ut_line)-1);
		ut.ut_line[sizeof(ut.ut_line)-1] = '\0';

		if (cfp->uthost) {
			(void)strncpy(ut.ut_host, cfp->uthost, 
				sizeof(ut.ut_host)-1);
			ut.ut_host[sizeof(ut.ut_host)-1] = '\0';
		}
#ifdef HAVE_UTMP_H	
		(void)time(&ut.ut_time);	
#elif HAVE_UTMPX_H 
		(void)gettimeofday(&tv, NULL);
		ut.ut_tv.tv_sec = tv.tv_sec;
		ut.ut_tv.tv_usec = tv.tv_usec;

		(void)strncpy(ut.ut_id, ut.ut_line, sizeof(ut.ut_id)-1);
		ut.ut_line[sizeof(ut.ut_line)-1] = '\0';

		ut.ut_pid = getpid();
		ut.ut_type = USER_PROCESS;
#endif
	}
#endif

        /*
         * overwriting signal disposition
         */
        (void)signal(SIGCHLD, sig_chld);

	switch (pid = fork()) {
	case -1:
		syslog(LOG_ERR, "forkpty: %m");
		_exit(1);	
	case 0:
		(void)close(parentfd);
		(void)close(pipechld[0]);
		(void)close(pipechld[1]);
		(void)close(master);
               	(void)close(fd);	
		(void)login_tty(slave);
#ifdef HAVE_UTMP_H
		login(&ut);
#elif HAVE_UTMPX_H
		setutxent();
		(void)pututxline(&ut);
#endif

		set_privileges(cfp);		

		/*
		 * SUIP PROGRAM HERE
		 */
#ifdef __NetBSD__
		(void)execl(_PATH_BSHELL,"sh", "-c",cfp->suipfile,(char *)NULL);
#else
		(void)execl(_PATH_BSHELL, "sh", "-p", "-c", cfp->suipfile, 
			(char *)NULL);
#endif
		_exit(127);
	default:
	{
		int ctrls;	
		int exit_status = 0;
	
		(void)close(slave);
	
		/*
		 * trying to open a control channel
		 * control_create() returns the number of bytes which were 
		 * written
		 * select_fd() returns -1 if errors exist you can check errno
		 */
		if (control_create(&ctrls, fd) == 1) { 
			if (select_fd(cfp, fd, master, ctrls, parentfd) < 0)
				exit_status = 1; 
		} else {
			syslog(LOG_ERR, "can't open ctrl chan");
			exit_status = 1;
		}
#if defined(HAVE_UTMP_H) || defined(HAVE_UTMPX_H)
		if (cfp->utmp) {
#ifdef HAVE_UTMP_H
			if (!logout(tty)) { 
				syslog(LOG_ERR, "unable to logout on %s", tty);
				exit_status = 1;
			} else
				logwtmp(tty, "", "");
#elif HAVE_UTMPX_H
			ut.ut_type = DEAD_PROCESS;
			(void)gettimeofday(&tv, NULL);
			ut.ut_tv.tv_sec = tv.tv_sec;
			ut.ut_tv.tv_usec = tv.tv_usec;

			(void)memset(&ut.ut_user, 0, sizeof(ut.ut_user));	
			setutxent();
			if (pututxline(&ut) == NULL) {
				syslog(LOG_ERR, 
					"unable to logout on %s (utmpx)",
					tty);
				exit_status = 1;
			}	
			endutxent();
#endif
		}
#endif

		cleanup(line);
		_exit(exit_status);
	}}	

	/*
	 * never reached
	 */
	_exit(1);
}
Пример #28
0
int
main(int argc, char *argv[])
{
	struct passwd *pw;
	int ch, howto, i, fd, kflag, lflag, nflag, qflag, pflag, sverrno;
	u_int pageins;
	char *kernel = NULL, *p;
	const char *user;

	if (strstr((p = strrchr(*argv, '/')) ? p + 1 : *argv, "halt")) {
		dohalt = 1;
		howto = RB_HALT;
	} else
		howto = 0;
	kflag = lflag = nflag = qflag = 0;
	while ((ch = getopt(argc, argv, "dk:lnpq")) != -1)
		switch(ch) {
		case 'd':
			howto |= RB_DUMP;
			break;
		case 'k':
			kflag = 1;
			kernel = optarg;
			break;
		case 'l':
			lflag = 1;
			break;
		case 'n':
			nflag = 1;
			howto |= RB_NOSYNC;
			break;
		case 'p':
			pflag = 1;
			howto |= (RB_POWEROFF | RB_HALT);
			break;
		case 'q':
			qflag = 1;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
		errx(1, "cannot dump (-d) when halting; must reboot instead");
	if (geteuid()) {
		errno = EPERM;
		err(1, NULL);
	}

	if (qflag) {
		reboot(howto);
		err(1, NULL);
	}

	if (kflag) {
		fd = open("/boot/nextboot.conf",
			  O_WRONLY | O_CREAT | O_TRUNC, 0444);
		if (fd != -1) {
			write(fd, "kernel=\"", 8L);
			write(fd, kernel, strlen(kernel));
			write(fd, "\"\n", 2);
			close(fd);
		}
	}

	/* Log the reboot. */
	if (!lflag)  {
		if ((user = getlogin()) == NULL)
			user = (pw = getpwuid(getuid())) ?
			    pw->pw_name : "???";
		if (dohalt) {
			openlog("halt", 0, LOG_AUTH | LOG_CONS);
			syslog(LOG_CRIT, "halted by %s", user);
		} else {
			openlog("reboot", 0, LOG_AUTH | LOG_CONS);
			syslog(LOG_CRIT, "rebooted by %s", user);
		}
	}
	logwtmp("~", "shutdown", "");

	/*
	 * Do a sync early on, so disks start transfers while we're off
	 * killing processes.  Don't worry about writes done before the
	 * processes die, the reboot system call syncs the disks.
	 */
	if (!nflag)
		sync();

	/* Just stop init -- if we fail, we'll restart it. */
	if (kill(1, SIGTSTP) == -1)
		err(1, "SIGTSTP init");

	/* Ignore the SIGHUP we get when our parent shell dies. */
	signal(SIGHUP, SIG_IGN);

	/* Send a SIGTERM first, a chance to save the buffers. */
	if (kill(-1, SIGTERM) == -1)
		err(1, "SIGTERM processes");

	/*
	 * After the processes receive the signal, start the rest of the
	 * buffers on their way.  Wait 5 seconds between the SIGTERM and
	 * the SIGKILL to give everybody a chance. If there is a lot of
	 * paging activity then wait longer, up to a maximum of approx
	 * 60 seconds.
	 */
	sleep(2);
	for (i = 0; i < 20; i++) {
		pageins = get_pageins();
		if (!nflag)
			sync();
		sleep(3);
		if (get_pageins() == pageins)
			break;
	}

	for (i = 1;; ++i) {
		if (kill(-1, SIGKILL) == -1) {
			if (errno == ESRCH)
				break;
			goto restart;
		}
		if (i > 5) {
			fprintf(stderr,
			    "WARNING: some process(es) wouldn't die\n");
			break;
		}
		sleep(2 * i);
	}

	reboot(howto);
	/* FALLTHROUGH */

restart:
	sverrno = errno;
	errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
	    strerror(sverrno));
	/* NOTREACHED */
}
Пример #29
0
static void
setthetime(const char *fmt, const char *p, int jflag, int nflag)
{
	struct tm *lt;
	struct timeval tv;
	const char *dot, *t;
	int century;

	if (fmt != NULL) {
		lt = localtime(&tval);
		t = strptime(p, fmt, lt);
		if (t == NULL) {
			fprintf(stderr, "Failed conversion of ``%s''"
				" using format ``%s''\n", p, fmt);
			badformat();
		} else if (*t != '\0')
			fprintf(stderr, "Warning: Ignoring %ld extraneous"
				" characters in date string (%s)\n",
				(long) strlen(t), t);
	} else {
		for (t = p, dot = NULL; *t; ++t) {
			if (isdigit(*t))
				continue;
			if (*t == '.' && dot == NULL) {
				dot = t;
				continue;
			}
			badformat();
		}

		lt = localtime(&tval);

		if (dot != NULL) {			/* .ss */
			dot++; /* *dot++ = '\0'; */
			if (strlen(dot) != 2)
				badformat();
			lt->tm_sec = ATOI2(dot);
			if (lt->tm_sec > 61)
				badformat();
		} else
			lt->tm_sec = 0;

		century = 0;
		/* if p has a ".ss" field then let's pretend it's not there */
		switch (strlen(p) - ((dot != NULL) ? 3 : 0)) {
		case 12:				/* cc */
			lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
			century = 1;
			/* FALLTHROUGH */
		case 10:				/* yy */
			if (century)
				lt->tm_year += ATOI2(p);
			else {				/* hack for 2000 ;-} */
				lt->tm_year = ATOI2(p);
				if (lt->tm_year < 69)
					lt->tm_year += 2000 - TM_YEAR_BASE;
				else
					lt->tm_year += 1900 - TM_YEAR_BASE;
			}
			/* FALLTHROUGH */
		case 8:					/* mm */
			lt->tm_mon = ATOI2(p);
			if (lt->tm_mon > 12)
				badformat();
			--lt->tm_mon;		/* time struct is 0 - 11 */
			/* FALLTHROUGH */
		case 6:					/* dd */
			lt->tm_mday = ATOI2(p);
			if (lt->tm_mday > 31)
				badformat();
			/* FALLTHROUGH */
		case 4:					/* HH */
			lt->tm_hour = ATOI2(p);
			if (lt->tm_hour > 23)
				badformat();
			/* FALLTHROUGH */
		case 2:					/* MM */
			lt->tm_min = ATOI2(p);
			if (lt->tm_min > 59)
				badformat();
			break;
		default:
			badformat();
		}
	}

	/* Let mktime() decide whether summer time is in effect. */
	lt->tm_isdst = -1;

	/* convert broken-down time to GMT clock time */
	if ((tval = mktime(lt)) == -1)
		errx(1, "nonexistent time");

	if (!jflag) {
		/* set the time */
		if (nflag || netsettime(tval)) {
			logwtmp("|", "date", "");
			tv.tv_sec = tval;
			tv.tv_usec = 0;
			if (settimeofday(&tv, NULL))
				err(1, "settimeofday (timeval)");
			logwtmp("{", "date", "");
		}

		if ((p = getlogin()) == NULL)
			p = "???";
		syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
	}
}
Пример #30
0
static int
plogin(char *user, char *passwd, char **msg, int *msglen)
{

#ifdef USE_PAM

    struct pam_conv pam_conversation;
    pam_handle_t *pamh;
    int pam_error;
/*
 * Fill the pam_conversion structure
 */
    memset (&pam_conversation, '\0', sizeof (struct pam_conv));
    pam_conversation.conv = &pam_conv;

    pam_error = pam_start ("ppp", user, &pam_conversation, &pamh);

    if (pam_error != PAM_SUCCESS) {
        *msg = MY_PAM_STRERROR (pam_error);
	return UPAP_AUTHNAK;
    }
/*
 * Define the fields for the credintial validation
 */
    pam_set_item (pamh, PAM_TTY, devnam);
    PAM_username = user;
    PAM_password = passwd;
/*
 * Validate the user
 */
    pam_error = pam_authenticate (pamh, PAM_SILENT);
    if (pam_error == PAM_SUCCESS) {
        pam_error = pam_acct_mgmt (pamh, PAM_SILENT);

	/* start a session for this user. Session closed when link ends. */
	if (pam_error == PAM_SUCCESS)
	   pam_open_session (pamh, PAM_SILENT);
    }

    *msg = MY_PAM_STRERROR (pam_error);

    PAM_username =
    PAM_password = "";
/*
 * Clean up the mess
 */
    pam_end (pamh, pam_error);

    if (pam_error != PAM_SUCCESS)
        return UPAP_AUTHNAK;
/*
 * Use the non-PAM methods directly
 */
#else /* #ifdef USE_PAM */

    struct passwd *pw;
    struct utmp utmp;
    struct timeval tp;
    char *tty;

#ifdef HAS_SHADOW
    struct spwd *spwd;
    struct spwd *getspnam();
#endif

    pw = getpwnam(user);
    endpwent();
    if (pw == NULL) {
	return (UPAP_AUTHNAK);
    }
/*
 * Check that the user is not listed in /etc/ppp/ppp.deny
 * and that the user's shell is listed in /etc/ppp/ppp.shells
 * if /etc/ppp/ppp.shells exists.
 */

    if (checkfile(_PATH_PPPDENY, user) == 1) {
	    	syslog(LOG_WARNING, "upap user %s: login denied in %s",
			user, _PATH_PPPDENY);
		return (UPAP_AUTHNAK);
    }

    if (checkfile(_PATH_PPPSHELLS, pw->pw_shell) == 0) {
	    	syslog(LOG_WARNING, "upap user %s: shell %s not in %s",
			user, pw->pw_shell, _PATH_PPPSHELLS);
		return (UPAP_AUTHNAK);
    }

#ifdef HAS_SHADOW
    spwd = getspnam(user);
    endspent();
    if (spwd) {
	/* check the age of the password entry */
	long now = time(NULL) / 86400L;

	if ((spwd->sp_expire > 0 && now >= spwd->sp_expire)
	    || ((spwd->sp_max >= 0 && spwd->sp_max < 10000)
		&& spwd->sp_lstchg >= 0
		&& now >= spwd->sp_lstchg + spwd->sp_max)) {
	    syslog(LOG_WARNING, "Password for %s has expired", user);
	    return (UPAP_AUTHNAK);
	}
	pw->pw_passwd = spwd->sp_pwdp;
    }
#endif

    /*
     * If no passwd, don't let them login.
     */
    if (pw->pw_passwd == NULL || *pw->pw_passwd == '\0'
	|| strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0)
	return (UPAP_AUTHNAK);

    if (pw->pw_expire) {
	gettimeofday(&tp, NULL);
	if (tp.tv_sec >= pw->pw_expire) {
	    syslog(LOG_INFO, "pap user %s account expired", user);
	    return (UPAP_AUTHNAK);
	}
    }

    /* These functions are not enabled for PAM. The reason for this is that */
    /* there is not necessarily a "passwd" entry for this user. That is     */
    /* real purpose of 'PAM' -- to virtualize the account data from the     */
    /* application. If you want to do the same thing, write the entry in    */
    /* the 'session' hook.                                                  */

    /* Log in wtmp and utmp using login() */

    tty = devnam;
    if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
	tty += 5;

    if (logout(tty))		/* Already entered (by login?) */
        logwtmp(tty, "", "");

#if defined(_PATH_LASTLOG)
    {
	    struct lastlog ll;
	    int fd;

	    if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
		lseek(fd, (off_t)(pw->pw_uid * sizeof(ll)), SEEK_SET);
		memset((void *)&ll, 0, sizeof(ll));
		time(&ll.ll_time);
		strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
		write(fd, (char *)&ll, sizeof(ll));
		close(fd);
	    }
    }
#endif

    memset((void *)&utmp, 0, sizeof(utmp));
    time(&utmp.ut_time);
    strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
    strncpy(utmp.ut_host, ":PPP", sizeof(utmp.ut_host));
    strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
    login(&utmp);		/* This logs us in wtmp too */

#endif /* #ifdef USE_PAM */

    syslog(LOG_INFO, "user %s logged in", user);
    logged_in = TRUE;

    return (UPAP_AUTHACK);
}