Blob Blame History Raw
diff -up initscripts-8.54.1/rwtab.olpc initscripts-8.54.1/rwtab
--- initscripts-8.54.1/rwtab.olpc	2007-04-13 18:44:55.000000000 -0400
+++ initscripts-8.54.1/rwtab	2007-09-11 18:23:52.000000000 -0400
@@ -24,10 +24,7 @@ empty	/var/tux
 empty	/media
 
 files	/etc/adjtime
-files	/etc/fstab
-files	/etc/mtab
 files	/etc/ntp.conf
-files	/etc/resolv.conf
 files	/etc/lvm/.cache
 files	/etc/lvm/archive
 files	/etc/lvm/backup
@@ -38,3 +35,4 @@ files	/var/lib/iscsi
 files	/var/lib/logrotate.status
 files	/var/lib/ntp
 files	/var/lib/xen
+files   /home/olpc/.Xauthority
diff -up initscripts-8.54.1/inittab.olpc initscripts-8.54.1/inittab
--- initscripts-8.54.1/inittab.olpc	2006-10-12 13:51:04.000000000 -0400
+++ initscripts-8.54.1/inittab	2007-09-11 18:23:52.000000000 -0400
@@ -15,7 +15,7 @@
 #   5 - X11
 #   6 - reboot (Do NOT set initdefault to this)
 # 
-id:3:initdefault:
+id:5:initdefault:
 
 # System initialization.
 si::sysinit:/etc/rc.d/rc.sysinit
@@ -44,10 +44,7 @@ pr:12345:powerokwait:/sbin/shutdown -c "
 # Run gettys in standard runlevels
 1:2345:respawn:/sbin/mingetty tty1
 2:2345:respawn:/sbin/mingetty tty2
-3:2345:respawn:/sbin/mingetty tty3
-4:2345:respawn:/sbin/mingetty tty4
-5:2345:respawn:/sbin/mingetty tty5
-6:2345:respawn:/sbin/mingetty tty6
+3:2345:respawn:/sbin/agetty ttyS0 115200 vt100
 
 # Run xdm in runlevel 5
-x:5:respawn:/etc/X11/prefdm -nodaemon
+x:5:respawn:/sbin/olpc-dm
diff -up /dev/null initscripts-8.54.1/src/olpc-dm.c
--- /dev/null	2007-09-11 11:59:20.755757520 -0400
+++ initscripts-8.54.1/src/olpc-dm.c	2007-09-11 18:29:19.000000000 -0400
@@ -0,0 +1,568 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <utmp.h>
+#include <termios.h>
+#include <setjmp.h>
+#include <ctype.h>
+#include <grp.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/syslog.h>
+#include <sys/sysmacros.h>
+#include <sys/param.h>
+
+#include <linux/major.h>
+
+#define OLPC_USER        "olpc"
+
+#define TTY_MODE         0620
+#define	TTYGRPNAME       "tty" 
+#define _PATH_HUSHLOGIN  ".hushlogin"
+
+#  include <security/pam_appl.h>
+#  include <security/pam_misc.h>
+#  define PAM_MAX_LOGIN_TRIES	3
+#  define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
+       fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \
+       syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \
+       pam_end(pamh, retcode); exit(1); \
+   }
+#  define PAM_END { \
+	pam_setcred(pamh, PAM_DELETE_CRED); \
+	retcode = pam_close_session(pamh,0); \
+	pam_end(pamh,retcode); \
+}
+
+int     timeout = 60;
+
+struct passwd *pwd;
+
+static struct passwd pwdcopy;
+char    hostaddress[16];	/* used in checktty.c */
+char	*hostname;		/* idem */
+static char	*username, *tty_name, *tty_number;
+static char	thishost[100];
+static pid_t	pid;
+
+static inline void xstrncpy(char *dest, const char *src, size_t n) {
+        strncpy(dest, src, n-1);
+        dest[n-1] = 0;
+}
+
+static int childPid = 0;
+static volatile int got_sig = 0;
+
+
+
+static void
+parent_sig_handler(int signal)
+{
+  if(childPid)
+    kill(-childPid, signal);
+  else
+    got_sig = 1;
+  if(signal == SIGTERM)
+    kill(-childPid, SIGHUP); /* because the shell often ignores SIGTERM */
+}
+
+/* Nice and simple code provided by Linus Torvalds 16-Feb-93 */
+/* Nonblocking stuff by Maciej W. Rozycki, macro@ds2.pg.gda.pl, 1999.
+   He writes: "Login performs open() on a tty in a blocking mode.
+   In some cases it may make login wait in open() for carrier infinitely,
+   for example if the line is a simplistic case of a three-wire serial
+   connection. I believe login should open the line in the non-blocking mode
+   leaving the decision to make a connection to getty (where it actually
+   belongs). */
+static void
+opentty(const char * tty) 
+{
+  int i, fd, flags;
+
+  fd = open(tty, O_RDWR | O_NONBLOCK);
+  if (fd == -1) 
+    {
+      syslog(LOG_ERR, "FATAL: can't reopen tty: %s",
+                     strerror(errno));
+      sleep(1);
+      exit(1);
+    }
+
+  flags = fcntl(fd, F_GETFL);
+  flags &= ~O_NONBLOCK;
+  fcntl(fd, F_SETFL, flags);
+    
+  for (i = 0; i < fd; i++)
+    close(i);
+  for (i = 0; i < 3; i++)
+    if (fd != i)
+      dup2(fd, i);
+  if (fd >= 3)
+    close(fd);
+}
+
+/* true if the filedescriptor fd is a console tty, very Linux specific */
+static int
+consoletty(int fd) 
+{
+  struct stat stb;
+
+  if ((fstat(fd, &stb) >= 0) 
+      && (major(stb.st_rdev) == TTY_MAJOR)
+      && (minor(stb.st_rdev) < 64))
+    {
+      return 1;
+    }
+
+  return 0;
+}
+
+/* strip comments and leading white space*/
+char *
+strip(char *src)
+{
+  int tpos=0;
+  int len;
+  int i;
+  int first_char_found=0;
+  char *result;
+ 
+  len = strlen(src);
+  result = (char *)malloc(len);
+  
+  for (i=0; i < len; i++)
+    {
+      if (!first_char_found && !isblank((int)src[i]))
+        first_char_found = 1;
+
+      if (first_char_found)
+        {
+          if (src[i] == (int)'#')
+            break;
+
+          result[tpos] = src[i];
+          tpos++;
+        }
+    }
+
+  if (tpos == 0)
+    {
+      /* blank line */
+      free(result);
+      result = NULL;
+    }
+  else
+    result[tpos]='\0';
+
+  return result;
+}
+
+void 
+source_i18n(void)
+{
+  FILE *f;
+  char *line;
+
+  f = fopen("/etc/sysconfig/i18n", "r");
+  while(fscanf(f, "%as", &line)==1)
+    {
+      char *sline;
+ 
+      sline = strip(line);
+      if (sline == NULL)
+        continue;
+
+      putenv(sline);
+
+      free(line);
+    }
+ 
+  fclose(f);
+}
+
+void
+olpc_login(void)
+{
+  extern int optind;
+  extern char *optarg, **environ;
+  struct group *gr;
+  int fflag, hflag, pflag, cnt;
+  int quietlog;
+  char *domain, *ttyn;
+  char tbuf[MAXPATHLEN + 2];
+  char *termenv;
+  int retcode;
+  pam_handle_t *pamh = NULL;
+  struct pam_conv conv = { misc_conv, NULL };
+  struct sigaction sa, oldsa_hup, oldsa_term;
+  char vcsn[20], vcsan[20];
+  pid = getpid();
+
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGINT, SIG_IGN);
+
+  setpriority(PRIO_PROCESS, 0, 0);
+  
+  gethostname(tbuf, sizeof(tbuf));
+  xstrncpy(thishost, tbuf, sizeof(thishost));
+  domain = index(tbuf, '.');
+  
+  username = tty_name = hostname = NULL;
+  fflag = hflag = pflag = 0;
+
+  for (cnt = getdtablesize(); cnt > 2; cnt--)
+    close(cnt);
+ 
+  /* TODO: This is not right, we should open the display :0 but we need
+   *     to start X first.  Flow should go like this once we get rid of startx
+   *     seteuid 0, setuid olpc -> start X -> start pam session -> fork ->
+   *     seteuid olpc -> start clients
+   */ 
+  ttyn = "/dev/tty2";
+  tty_number = "2";
+
+  /* set pgid to pid */
+  setpgrp();
+  /* this means that setsid() will fail */
+  
+  openlog("olpc-login", LOG_ODELAY, LOG_AUTHPRIV);
+
+  retcode = pam_start("olpc-login", OLPC_USER, &conv, &pamh);
+  if(retcode != PAM_SUCCESS) 
+    {
+      fprintf(stderr, "olpc-login: PAM Failure, aborting: %s\n",
+              pam_strerror(pamh, retcode));
+      syslog(LOG_ERR, "Couldn't initialize PAM: %s",
+             pam_strerror(pamh, retcode));
+      exit(99);
+    }
+  retcode = pam_set_item(pamh, PAM_TTY, tty_name);
+  PAM_FAIL_CHECK;
+
+  /*
+   * Authentication may be skipped (for example, during krlogin, rlogin, etc...), 
+   * but it doesn't mean that we can skip other account checks. The account 
+   * could be disabled or password expired (althought kerberos ticket is valid).
+   * -- kzak@redhat.com (22-Feb-2006)
+   */
+  retcode = pam_acct_mgmt(pamh, 0);
+
+  if(retcode == PAM_NEW_AUTHTOK_REQD) 
+    retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+
+  PAM_FAIL_CHECK;
+
+  /*
+   * Grab the user information out of the password file for future usage
+   * First get the username that we are actually using, though.
+   */
+  retcode = pam_get_item(pamh, PAM_USER, (const void **) &username);
+  PAM_FAIL_CHECK;
+
+  if (!username || !*username) 
+    {
+      fprintf(stderr, "\nSession setup problem, abort.\n");
+      syslog(LOG_ERR, "NULL user name in %s:%d. Abort.",
+             __FUNCTION__, __LINE__);
+      pam_end(pamh, PAM_SYSTEM_ERR);
+      exit(1);
+    }
+
+  if (!(pwd = getpwnam(username))) 
+    {
+      fprintf(stderr, "\nSession setup problem, abort.\n");
+      syslog(LOG_ERR, "Invalid user name \"%s\" in %s:%d. Abort.",
+             username, __FUNCTION__, __LINE__);
+      pam_end(pamh, PAM_SYSTEM_ERR);
+      exit(1);
+    }
+
+  /*
+   * Create a copy of the pwd struct - otherwise it may get
+   * clobbered by PAM
+   */
+  memcpy(&pwdcopy, pwd, sizeof(*pwd));
+  pwd = &pwdcopy;
+  pwd->pw_name   = strdup(pwd->pw_name);
+  pwd->pw_passwd = strdup(pwd->pw_passwd);
+  pwd->pw_gecos  = strdup(pwd->pw_gecos);
+  pwd->pw_dir  = strdup(pwd->pw_dir);
+  pwd->pw_shell  = strdup(pwd->pw_shell);
+  if (!pwd->pw_name || !pwd->pw_passwd || !pwd->pw_gecos ||
+	!pwd->pw_dir || !pwd->pw_shell) 
+    {
+      fprintf(stderr, "olpc-login: Out of memory\n");
+      syslog(LOG_ERR, "Out of memory");
+      pam_end(pamh, PAM_SYSTEM_ERR);
+      exit(1);
+    }
+  username = pwd->pw_name;
+
+  /*
+   * Initialize the supplementary group list.
+   * This should be done before pam_setcred because
+   * the PAM modules might add groups during pam_setcred.
+   */
+  if (initgroups(username, pwd->pw_gid) < 0) 
+    {
+      syslog(LOG_ERR, "initgroups: %m");
+      fprintf(stderr, "\nSession setup problem, abort.\n");
+      pam_end(pamh, PAM_SYSTEM_ERR);
+      exit(1);
+    }
+
+  retcode = pam_open_session(pamh, 0);
+  PAM_FAIL_CHECK;
+
+  retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+  if (retcode != PAM_SUCCESS)
+      pam_close_session(pamh, 0);
+  PAM_FAIL_CHECK;
+
+  /* committed to login -- turn off timeout */
+  alarm((unsigned int)0);
+  
+  endpwent();
+  
+  /* This requires some explanation: As root we may not be able to
+     read the directory of the user if it is on an NFS mounted
+     filesystem. We temporarily set our effective uid to the user-uid
+     making sure that we keep root privs. in the real uid. 
+     
+     A portable solution would require a fork(), but we rely on Linux
+     having the BSD setreuid() */
+  
+  {
+    char tmpstr[MAXPATHLEN];
+    uid_t ruid = getuid();
+    gid_t egid = getegid();
+
+    /* avoid snprintf - old systems do not have it, or worse,
+       have a libc in which snprintf is the same as sprintf */
+    if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 > MAXPATHLEN)
+      quietlog = 0;
+    else 
+      {
+        sprintf(tmpstr, "%s/%s", pwd->pw_dir, _PATH_HUSHLOGIN);
+                setregid(-1, pwd->pw_gid);
+                setreuid(0, pwd->pw_uid);
+                quietlog = (access(tmpstr, R_OK) == 0);
+                setuid(0); /* setreuid doesn't do it alone! */
+                setreuid(ruid, 0);
+                setregid(-1, egid);
+      }
+  }
+  
+  /* for linux, write entries in utmp and wtmp */
+  {
+    struct utmp ut;
+    struct utmp *utp;
+    struct timeval tv;
+	
+    utmpname(_PATH_UTMP);
+    setutent();
+
+    /* Find pid in utmp.
+       login sometimes overwrites the runlevel entry in /var/run/utmp,
+       confusing sysvinit. I added a test for the entry type, and the problem
+       was gone. (In a runlevel entry, st_pid is not really a pid but some number
+       calculated from the previous and current runlevel).
+       Michael Riepe <michael@stud.uni-hannover.de>
+     */
+    while ((utp = getutent()))
+      if (utp->ut_pid == pid
+          && utp->ut_type >= INIT_PROCESS
+          && utp->ut_type <= DEAD_PROCESS)
+        break;
+
+	/* If we can't find a pre-existing entry by pid, try by line.
+	   BSD network daemons may rely on this. (anonymous) */
+    if (utp == NULL)
+      {
+        setutent();
+        ut.ut_type = LOGIN_PROCESS;
+        strncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
+        utp = getutline(&ut);
+      }
+	
+    if (utp) 
+      {
+        memcpy(&ut, utp, sizeof(ut)); 
+      } 
+    else 
+      {
+        /* some gettys/telnetds don't initialize utmp... */
+        memset(&ut, 0, sizeof(ut));
+      }
+	
+    if (ut.ut_id[0] == 0)
+      strncpy(ut.ut_id, tty_number, sizeof(ut.ut_id));
+	
+    strncpy(ut.ut_user, username, sizeof(ut.ut_user));
+    xstrncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
+    gettimeofday(&tv, NULL);
+    ut.ut_tv.tv_sec = tv.tv_sec;
+    ut.ut_tv.tv_usec = tv.tv_usec;
+    ut.ut_type = USER_PROCESS;
+    ut.ut_pid = pid;
+    if (hostname) 
+      {
+        xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
+        if (hostaddress[0])
+          memcpy(&ut.ut_addr_v6, hostaddress, sizeof(ut.ut_addr_v6));
+      }
+	
+    pututline(&ut);
+    endutent();
+
+    updwtmp(_PATH_WTMP, &ut);
+  }
+
+  setgid(pwd->pw_gid);
+  
+  environ = (char**)malloc(sizeof(char*));
+  memset(environ, 0, sizeof(char*));
+ 
+  source_i18n();
+ 
+  setenv("HOME", pwd->pw_dir, 0);    /* legal to override */
+  setenv("PATH", _PATH_DEFPATH, 1);
+  
+  setenv("SHELL", pwd->pw_shell, 1);
+  /*setenv("TERM", termenv, 1);*/
+  
+  /* LOGNAME is not documented in login(1) but
+     HP-UX 6.5 does it. We'll not allow modifying it.
+     */
+  setenv("LOGNAME", pwd->pw_name, 1);
+
+  {
+    int i;
+    char ** env = pam_getenvlist(pamh);
+
+    if (env != NULL) 
+      {
+        for (i=0; env[i]; i++)
+          putenv(env[i]);
+      }
+  }
+
+  /* allow tracking of good logins.
+     -steve philp (sphilp@mail.alliance.net) */
+  
+  if (hostname) 
+    syslog(LOG_INFO, "LOGIN ON %s BY %s FROM %s", tty_name, 
+           pwd->pw_name, hostname);
+  else 
+    syslog(LOG_INFO, "LOGIN ON %s BY %s", tty_name,
+           pwd->pw_name); 
+  
+  signal(SIGALRM, SIG_DFL);
+  signal(SIGQUIT, SIG_DFL);
+  signal(SIGTSTP, SIG_IGN);
+
+  /*
+   * We must fork before setuid() because we need to call
+   * pam_close_session() as root.
+   */
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SIG_IGN;
+  sigaction(SIGINT, &sa, NULL);
+
+  sigaction(SIGHUP, &sa, &oldsa_hup); /* ignore while we detach from the tty */
+  ioctl(0, TIOCNOTTY, NULL);
+
+  sa.sa_handler = parent_sig_handler;
+  sigaction(SIGHUP, &sa, NULL);
+  sigaction(SIGTERM, &sa, &oldsa_term);
+  
+  closelog();
+  childPid = fork();
+  if (childPid < 0) 
+    {
+      int errsv = errno;
+      /* error in fork() */
+      fprintf(stderr, "olpc-login: failure forking: %s", strerror(errsv));
+      PAM_END;
+      exit(0);
+    }
+
+  if (childPid) 
+    {
+      close(0); close(1); close(2); 
+      sa.sa_handler = SIG_IGN;
+      sigaction(SIGQUIT, &sa, NULL);
+      sigaction(SIGINT, &sa, NULL);
+      while(wait(NULL) == -1 && errno == EINTR) /**/ ;
+      openlog("olpc-login", LOG_ODELAY, LOG_AUTHPRIV);
+      PAM_END;
+      exit(0);
+    }
+
+  sigaction(SIGHUP, &oldsa_hup, NULL);
+  sigaction(SIGTERM, &oldsa_term, NULL);
+  if(got_sig) exit(1);
+
+  /* child */
+  /*
+   * Problem: if the user's shell is a shell like ash that doesnt do
+   * setsid() or setpgrp(), then a ctrl-\, sending SIGQUIT to every
+   * process in the pgrp, will kill us.
+   */
+
+  /* start new session */
+  setsid();
+
+  /* make sure we have a controlling tty */
+  openlog("olpc-login", LOG_ODELAY, LOG_AUTHPRIV);	/* reopen */
+
+  /*
+   * TIOCSCTTY: steal tty from other process group.
+   */
+  if (ioctl(0, TIOCSCTTY, (char *)1)) 
+    {
+      syslog(LOG_ERR, "Couldn't set controlling terminal: %s", strerror(errno));
+      exit(1);
+    }
+
+  signal(SIGINT, SIG_DFL);
+  
+  /* discard permissions last so can't get killed and drop core */
+  if(setuid(pwd->pw_uid) < 0 && pwd->pw_uid) 
+    {
+      syslog(LOG_ALERT, "setuid() failed");
+      exit(1);
+    }
+  
+  /* wait until here to change directory! */
+  if (chdir(pwd->pw_dir) < 0) 
+    {
+      printf("No directory %s!\n", pwd->pw_dir);
+      if (chdir("/"))
+        exit(0);
+      pwd->pw_dir = "/";
+      printf("Logging in with home = \"/\".\n");
+    }
+  
+  /* fork and exec startx. wait on child to cleanup */ 
+  execl("/usr/bin/startx", "startx", "--", "-fp", "built-ins", "-wr", NULL);
+  exit(0);
+}
+
+int
+main (int argc, 
+      char **argv)
+{
+  /* Use PAM to login as user*/
+  olpc_login (); 
+
+  return 0;
+}
diff -up initscripts-8.54.1/src/Makefile.olpc initscripts-8.54.1/src/Makefile
--- initscripts-8.54.1/src/Makefile.olpc	2006-09-27 15:59:05.000000000 -0400
+++ initscripts-8.54.1/src/Makefile	2007-09-11 18:23:52.000000000 -0400
@@ -1,7 +1,8 @@
 CFLAGS+=$(RPM_OPT_FLAGS) -Wall -D_GNU_SOURCE
 
 PROGS=usernetctl doexec netreport testd usleep ipcalc initlog \
-	fstab-decode getkey ppp-watch consoletype genhostid rename_device
+	fstab-decode getkey ppp-watch consoletype genhostid rename_device \
+          olpc-dm
 PPPWATCH_OBJS=ppp-watch.o shvar.o
 INITLOG_OBJS=initlog.o process.o
 USLEEP_OBJS=usleep.o
@@ -28,6 +29,7 @@ install:
 	install -m 755 consoletype $(ROOT)/sbin/consoletype
 	install -m 755 rename_device $(ROOT)/lib/udev/rename_device
 	install -m 755 ccw_init $(ROOT)/lib/udev/ccw_init
+	install -m 755 olpc-dm $(ROOT)/sbin/olpc-dm
 	install -m 644 initlog.1 $(ROOT)$(mandir)/man1
 	install -m 644 genhostid.1 $(ROOT)$(mandir)/man1
 	install -m 644 doexec.1 $(ROOT)$(mandir)/man1
@@ -77,5 +79,8 @@ ppp-watch.o: ppp-watch.c
 rename_device: rename_device.c
 	$(CC) $(CFLAGS) `pkg-config glib-2.0 --cflags` -o $@ $< `pkg-config glib-2.0 --libs`
 
+olpc-dm: olpc-dm.c
+	$(CC) $(CFLAGS) olpc-dm.c -o $@ -I/usr/include -lpam -lpam_misc
+
 kmodule: kmodule.o
 	$(CC) $(LDFLAGS) -o $@ $< -Wl,-Bstatic -lpopt -Wl,-Bdynamic -lkudzu -lpci