Cosmetic change: use sizeof(destination) in memcpy.
[become] / src / become.c
index d94e3c2..c5df906 100644 (file)
@@ -1,10 +1,10 @@
 /* -*-c-*-
  *
- * $Id: become.c,v 1.10 1997/09/17 10:14:10 mdw Exp $
+ * $Id: become.c,v 1.18 1998/06/26 10:32:54 mdw Exp $
  *
  * Main code for `become'
  *
- * (c) 1997 EBI
+ * (c) 1998 EBI
  */
 
 /*----- Licensing notice --------------------------------------------------*
 /*----- Revision history --------------------------------------------------*
  *
  * $Log: become.c,v $
- * Revision 1.10  1997/09/17 10:14:10  mdw
+ * Revision 1.18  1998/06/26 10:32:54  mdw
+ * Cosmetic change: use sizeof(destination) in memcpy.
+ *
+ * Revision 1.17  1998/06/18 15:06:59  mdw
+ * Close log before execing program to avoid leaving a socket open.
+ *
+ * Revision 1.16  1998/04/23 13:21:04  mdw
+ * Small tweaks.  Support no-network configuration option, and rearrange
+ * the help text a little.
+ *
+ * Revision 1.15  1998/01/13 11:10:44  mdw
+ * Add `TZ' to the list of variables to be preserved.
+ *
+ * Revision 1.14  1998/01/12 16:45:39  mdw
+ * Fix copyright date.
+ *
+ * Revision 1.13  1997/09/26 09:14:57  mdw
+ * Merged blowfish branch into trunk.
+ *
+ * Revision 1.12  1997/09/25 16:04:48  mdw
+ * Change directory after becoming someone else, instead of before.  This
+ * avoids problems with root-squashed NFS mounts.
+ *
+ * Revision 1.11.2.1  1997/09/26 09:07:58  mdw
+ * Use the Blowfish encryption algorithm instead of IDEA.  This is partly
+ * because I prefer Blowfish (without any particularly strong evidence) but
+ * mainly because IDEA is patented and Blowfish isn't.
+ *
+ * Revision 1.11  1997/09/24  09:48:45  mdw
+ * Fix (scary) overrun bug in group allocation stuff.
+ *
+ * Revision 1.10  1997/09/17  10:14:10  mdw
  * Fix a typo.  Support service names in `--port' option.
  *
  * Revision 1.9  1997/09/10 10:28:05  mdw
@@ -131,11 +162,9 @@ enum {
 
 /* --- Login behaviour types --- */
 
-enum {
-  l_preserve,                          /* Preserve the environment */
-  l_setuser,                           /* Update who I am */
-  l_login                              /* Do a full login */
-};
+#define l_preserve 0                   /* Preserve the environment */
+#define l_setuser 1                    /* Update who I am */
+#define l_login        2                       /* Do a full login */
 
 /* --- Group behaviour types --- *
  *
@@ -304,8 +333,8 @@ static int bc__addGroups(gid_t *g, int *png, const gid_t *a, int na)
 
     /* --- See if there's room for more --- */
 
-    if (ng > NGROUPS_MAX) {
-      moan("too many groups (system limit exceeded -- some have been lost");
+    if (ng >= NGROUPS_MAX) {
+      moan("too many groups (system limit exceeded) -- some have been lost");
       *png = ng;
       return (-1);
     }
@@ -349,7 +378,10 @@ static void bc__usage(FILE *fp)
            "Usage: \n"
            "   $ -c <shell-command> <user>\n"
            "   $ [<env-var>] <user> [<command> [<arguments>]...]\n"
-           "   $ -d [-p <port>] [-f <config-file>]\n");
+#ifndef NONETWORK
+           "   $ -d [-p <port>] [-f <config-file>]\n"
+#endif
+    );
 }
 
 /* --- @bc__help@ --- *
@@ -389,7 +421,17 @@ static void bc__help(FILE *fp, int suid)
 "-e, --preserve-environment    Try to preserve the current environment\n"
 "-s, --su, --set-user          Set environment variables to reflect USER\n"
 "-l, --login                   Really log in as USER\n"
-"\n"
+"                              [Default is "
+#if DEFAULT_LOGIN_STYLE == l_preserve
+  "preserve-environment"
+#elif DEFAULT_LOGIN_STYLE == l_setuser
+  "set-user"
+#elif DEFAULT_LOGIN_STYLE == l_login
+  "login"
+#else
+  "poorly configured"
+#endif
+"]\n\n"
 "-g GROUP, --group=GROUP       Set primary group-id to be GROUP\n"
 #ifdef HAVE_SETGROUPS
 "-k, --keep-groups             Keep your current set of groups\n"
@@ -398,10 +440,13 @@ static void bc__help(FILE *fp, int suid)
 #endif
 "\n"
 "-c CMD, --command=CMD         Run the (Bourne) shell command CMD\n"
+#ifndef NONETWORK
 "\n"
 "-d, --daemon                  Start a daemon\n"
 "-p PORT, --port=PORT          In daemon mode, listen on PORT\n"
-"-f FILE, --config-file=FILE   In daemon mode, read config from FILE\n");
+"-f FILE, --config-file=FILE   In daemon mode, read config from FILE\n"
+#endif
+    );
 #ifdef TRACING
   bc__write(fp, "\n");
   if (!suid) {
@@ -439,8 +484,10 @@ int main(int argc, char *argv[])
 
   /* --- Become server setup parameters --- */
 
+#ifndef NONETWORK
   char *conffile = file_RULES;         /* Default config file for daemon */
   int port = 0;                                /* Default port for daemon */
+#endif
 
   /* --- Miscellanous shared variables --- */
 
@@ -468,7 +515,7 @@ int main(int argc, char *argv[])
   enum {
     f_daemon = 1,                      /* Start up in daemon mode */
     f_duff = 2,                                /* Fault in arguments */
-    f_login = 4,                       /* Execute as a login shell */
+    f_shell = 4,                       /* Run a default shell */
     f_dummy = 8,                       /* Don't actually do anything */
     f_setuid = 16,                     /* We're running setuid */
     f_havegroup = 32                   /* Set a default group */
@@ -525,9 +572,11 @@ int main(int argc, char *argv[])
 
       /* --- Server options --- */
 
+#ifndef NONETWORK
       { "daemon",      0,              0,      'd' },
       { "port",                gFlag_argReq,   0,      'p' },
       { "config-file", gFlag_argReq,   0,      'f' },
+#endif
 
       /* --- Tracing options --- */
 
@@ -550,7 +599,9 @@ int main(int argc, char *argv[])
               "g:"                     /* Group (without @setgroups@) */
 #endif
               "c:"                     /* Command to run options */
+#ifndef NONETWORK
               "dp:f:"                  /* Server options */
+#endif
 #ifdef TRACING
               "I:T::L::"               /* Tracing options */
 #endif
@@ -620,6 +671,7 @@ int main(int argc, char *argv[])
 
       /* --- Server options --- */
 
+#ifndef NONETWORK
       case 'p':
        if (isdigit((unsigned char)optarg[0]))
          port = htons(atoi(optarg));
@@ -636,6 +688,7 @@ int main(int argc, char *argv[])
       case 'f':
        conffile = optarg;
        break;
+#endif
 
       /* --- Pretend to be a different user --- *
        *
@@ -728,12 +781,14 @@ int main(int argc, char *argv[])
        static tr lvltbl[] = {
          { 'm', TRACE_MISC,    "miscellaneous messages" },
          { 's', TRACE_SETUP,   "building the request block" },
-         { 'd', TRACE_DAEMON,  "server process" },
          { 'r', TRACE_RULE,    "ruleset scanning" },
          { 'c', TRACE_CHECK,   "request checking" },
+#ifndef NONETWORK
+         { 'd', TRACE_DAEMON,  "server process" },
          { 'l', TRACE_CLIENT,  "client process" },
          { 'R', TRACE_RAND,    "random number generator" },
          { 'C', TRACE_CRYPTO,  "cryptographic processing of requests" },
+#endif
          { 'y', TRACE_YACC,    "parsing configuration file" },
          { 'D', TRACE_DFL,     "default tracing options" },
          { 'A', TRACE_ALL,     "all tracing options" },
@@ -851,11 +906,13 @@ done_options:
 
   /* --- Switch to daemon mode if requested --- */
 
+#ifndef NONETWORK
   if (flags & f_daemon) {
     T( trace(TRACE_MISC, "become: daemon mode requested"); )
     daemon_init(conffile, port);
     exit(0);
   }
+#endif
 
   /* --- Open a syslog --- */
 
@@ -901,7 +958,7 @@ done_options:
     uname(&u);
     if ((he = gethostbyname(u.nodename)) == 0)
       die("who am I? (can't resolve `%s')", u.nodename);
-    memcpy(&rq.host, he->h_addr, sizeof(struct in_addr));
+    memcpy(&rq.host, he->h_addr, sizeof(rq.host));
   }
 
   /* --- Fiddle with group ownerships a bit --- */
@@ -1008,7 +1065,7 @@ done_options:
       ngroups = 0;
       (void)(bc__addGroups(groups, &ngroups, ga, i) ||
             ((gstyle & g_keep) &&
-             bc__addGroups(groups, &ngroups, from_gr,n_fgr)) ||
+             bc__addGroups(groups, &ngroups, from_gr, n_fgr)) ||
             ((gstyle & g_replace) &&
              bc__addGroups(groups, &ngroups, to_gr, n_tgr)));
     }
@@ -1043,45 +1100,48 @@ done_options:
     binary = todo[0];
   }
 
-  else switch (style) {
+  else {
+    flags |= f_shell;
+
+    switch (style) {
 
-    /* --- An unadorned becoming requires little work --- */
+      /* --- An unadorned becoming requires little work --- */
 
-    case l_preserve:
-      shell[0] = getenv("SHELL");
-      if (!shell[0])
-       shell[0] = from_pw->pw_shell;
-      shell[1] = 0;
-      todo = shell;
-      binary = todo[0];
-      break;
+      case l_preserve:
+       shell[0] = getenv("SHELL");
+       if (!shell[0])
+         shell[0] = from_pw->pw_shell;
+       shell[1] = 0;
+       todo = shell;
+       binary = todo[0];
+       break;
 
-    /* --- An su-like login needs slightly less effort --- */
+      /* --- An su-like login needs slightly less effort --- */
 
-    case l_setuser:
-      shell[0] = to_pw->pw_shell;
-      shell[1] = 0;
-      todo = shell;
-      binary = todo[0];
-      break;
+      case l_setuser:
+       shell[0] = to_pw->pw_shell;
+       shell[1] = 0;
+       todo = shell;
+       binary = todo[0];
+       break;
+
+      /* --- A login request needs a little bit of work --- */
 
-    /* --- A login request needs a little bit of work --- */
-
-    case l_login: {
-      const char *p = strrchr(to_pw->pw_shell, '/');
-
-      if (p)
-       p++;
-      else
-       p = to_pw->pw_shell;
-      shell[0] = xmalloc(strlen(p) + 2);
-      shell[0][0] = '-';
-      strcpy(shell[0] + 1, p);
-      shell[1] = 0;
-      todo = shell;
-      binary = to_pw->pw_shell;
-      chdir(to_pw->pw_dir);
-    } break;
+      case l_login: {
+       const char *p = strrchr(to_pw->pw_shell, '/');
+
+       if (p)
+         p++;
+       else
+         p = to_pw->pw_shell;
+       shell[0] = xmalloc(strlen(p) + 2);
+       shell[0][0] = '-';
+       strcpy(shell[0] + 1, p);
+       shell[1] = 0;
+       todo = shell;
+       binary = to_pw->pw_shell;
+      } break;
+    }
   }
 
   /* --- Mangle the environment --- *
@@ -1118,7 +1178,7 @@ done_options:
      */
 
     static char *preserve[] = {
-      "TERM", "DISPLAY", 0
+      "TERM", "DISPLAY", "TZ", 0
     };
 
     /* --- Variables to be expunged --- *
@@ -1420,7 +1480,7 @@ done_options:
 
   if (rq.from == rq.to) {
     moan("you already are `%s'!", to_pw->pw_name);
-    if (!cmd && todo == shell) {
+    if (flags & f_shell) {
       moan("(to prevent confusion, I'm not spawning a shell)");
       exit(0);
     }
@@ -1455,9 +1515,19 @@ done_options:
   if (setuid(rq.to) < 0)
     die("couldn't set uid: %s", strerror(errno));
 
+  /* --- If this was a login, change current directory --- */
+
+  if ((flags & f_shell) &&
+      style == l_login &&
+      chdir(to_pw->pw_dir) < 0) {
+    moan("couldn't change directory to `%s': %s",
+        to_pw->pw_dir, strerror(errno));
+  }
+
   /* --- Finally, call the program --- */
 
   fflush(0);
+  closelog();
   execve(rq.cmd, todo, env);
   die("couldn't exec `%s': %s", rq.cmd, strerror(errno));
   return (127);