summaryrefslogtreecommitdiff
path: root/utils/login.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/login.c')
-rw-r--r--utils/login.c101
1 files changed, 52 insertions, 49 deletions
diff --git a/utils/login.c b/utils/login.c
index c22a379a..cad3b1ed 100644
--- a/utils/login.c
+++ b/utils/login.c
@@ -1,8 +1,8 @@
/* Hurdish login
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995,96,97,98,99,2002 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Written by Miles Bader <miles@gnu.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -32,6 +32,7 @@
#include <time.h>
#include <assert.h>
#include <version.h>
+#include <sys/mman.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -139,7 +140,7 @@ cat (mach_port_t node, char *str)
{
write (0, data, data_len);
if (data != buf)
- vm_deallocate (mach_task_self (), (vm_address_t)data, data_len);
+ munmap (data, data_len);
}
}
if (err)
@@ -187,7 +188,9 @@ add_utmp_entry (char *args, unsigned args_len, int inherit_host)
{
struct utmp *old_utmp;
strncpy (utmp.ut_line, basename (tty), sizeof (utmp.ut_line));
+ setutent ();
old_utmp = getutline (&utmp);
+ endutent ();
if (old_utmp)
{
if (! host)
@@ -207,7 +210,7 @@ add_utmp_entry (char *args, unsigned args_len, int inherit_host)
/* Lookup the host HOST, and add entries for VIA (the host name), and
VIA_ADDR (the dotted decimal address) to ARGS & ARGS_LEN. */
static error_t
-add_canonical_host (char **args, unsigned *args_len, char *host)
+add_canonical_host (char **args, size_t *args_len, char *host)
{
struct hostent *he = gethostbyname (host);
@@ -244,7 +247,7 @@ add_canonical_host (char **args, unsigned *args_len, char *host)
/* Add the `=' separated environment entry ENTRY to ENV & ENV_LEN, exiting
with an error message if we can't. */
static void
-add_entry (char **env, unsigned *env_len, char *entry)
+add_entry (char **env, size_t *env_len, char *entry)
{
char *name = strsep (&entry, "=");
error_t err = envz_add (env, env_len, name, entry);
@@ -269,7 +272,7 @@ check_owned (process_t proc_server, pid_t pid, int *owned)
{
*owned = !(pi->state & PI_NOTOWNED);
if (pi != &_pi)
- vm_deallocate (mach_task_self (), (vm_address_t)pi, pi_size);
+ munmap (pi, pi_size);
}
return err;
@@ -294,7 +297,7 @@ kill_login (process_t proc_server, pid_t pid, int sig)
if (pids[i] != self)
kill (pids[i], sig);
if (pids != _pids)
- vm_deallocate (mach_task_self (), (vm_address_t)pids, num_pids);
+ munmap (pids, num_pids);
}
}
while (!err && num_pids > 0);
@@ -365,7 +368,7 @@ dog (time_t timeout, pid_t pid, char **argv)
}
}
-void
+int
main(int argc, char *argv[])
{
int i;
@@ -374,15 +377,15 @@ main(int argc, char *argv[])
char *path;
error_t err = 0;
char *args = 0; /* The login parameters */
- unsigned args_len = 0;
+ size_t args_len = 0;
char *args_defs = 0; /* Defaults for login parameters. */
- unsigned args_defs_len = 0;
+ size_t args_defs_len = 0;
char *env = 0; /* The new environment. */
- unsigned env_len = 0;
+ size_t env_len = 0;
char *env_defs = 0; /* Defaults for the environment. */
- unsigned env_defs_len = 0;
+ size_t env_defs_len = 0;
char *parent_env = 0; /* The environment we got from our parent */
- unsigned parent_env_len = 0;
+ size_t parent_env_len = 0;
int no_environ = 0; /* If false, use the env as default params. */
int no_args = 0; /* If false, put login params in the env. */
int inherit_environ = 0; /* True if we shouldn't clear our env. */
@@ -391,11 +394,11 @@ main(int argc, char *argv[])
int paranoid = 0; /* Admit no knowledge. */
int retry = 0; /* For some failures, exec a login shell. */
char *retry_args = 0; /* Args passed when retrying. */
- unsigned retry_args_len = 0;
+ size_t retry_args_len = 0;
char *shell = 0; /* The shell program to run. */
char *sh_arg0 = 0; /* The shell's argv[0]. */
char *sh_args = 0; /* The args to the shell. */
- unsigned sh_args_len = 0;
+ size_t sh_args_len = 0;
int shell_arg = 0; /* If there are shell args, use the first as
the shell name. */
struct ugids ugids = UGIDS_INIT; /* Authorization of the new shell. */
@@ -403,7 +406,6 @@ main(int argc, char *argv[])
struct idvec parent_uids = IDVEC_INIT; /* Parent uids, -SETUID. */
struct idvec parent_gids = IDVEC_INIT; /* Parent gids, -SETGID. */
mach_port_t exec; /* The shell executable. */
- mach_port_t cwd; /* The child's CWD. */
mach_port_t root; /* The child's root directory. */
mach_port_t ports[INIT_PORT_MAX]; /* Init ports for the new process. */
int ints[INIT_INT_MAX]; /* Init ints for it. */
@@ -438,7 +440,6 @@ main(int argc, char *argv[])
int retry_argc;
char **retry_argv;
char *via = envz_get (args, args_len, "VIA");
- extern void _argp_unlock_xxx (); /* Secret unknown function. */
if (fmt)
error (retry ? 0 : code, err, fmt, str); /* May exit... */
@@ -454,7 +455,6 @@ main(int argc, char *argv[])
argz_extract (retry_args, retry_args_len, retry_argv);
/* Reinvoke ourselves with no userids or anything; shouldn't return. */
- _argp_unlock_xxx (); /* Hack to get around problems with getopt. */
main (retry_argc, retry_argv);
exit (code); /* But if it does... */
}
@@ -580,12 +580,17 @@ main(int argc, char *argv[])
/* Parse our options. */
argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
- /* Check passwords where necessary. */
- err = ugids_verify (&ugids, &parent_uids, &parent_gids, 0);
- if (err == EINVAL)
+ /* Check passwords where necessary. If no_passwd is set, then our parent
+ guarantees identity itself (where it is allowed), but otherwise
+ we want every UID fully checked. */
+ err = ugids_verify_make_auth (&ugids,
+ no_passwd ? &parent_uids : 0,
+ no_passwd ? &parent_gids : 0,
+ 0, 0, 0, 0, &auth);
+ if (err == EACCES)
fail (5, 0, "Invalid password", 0);
else if (err)
- error (5, err, "Checking passwords");
+ error (5, err, "Authentication failure");
/* Now that we've parsed the command line, put together all these
environments we've gotten from various places. There are two targets:
@@ -608,13 +613,13 @@ main(int argc, char *argv[])
{
struct passwd *pw;
char *passwd = 0; /* Login parameters from /etc/passwd */
- unsigned passwd_len = 0;
+ size_t passwd_len = 0;
/* Decide which password entry to get parameters from. */
if (ugids.eff_uids.num > 0)
pw = getpwuid (ugids.eff_uids.ids[0]); /* Effective uid */
else if (ugids.avail_uids.num > 0)
- pw = getpwuid (ugids.eff_uids.ids[0]); /* Auxiliary uid */
+ pw = getpwuid (ugids.avail_uids.ids[0]); /* Auxiliary uid */
else
/* No user! Try to used the `not-logged-in' user to set various
parameters. */
@@ -642,14 +647,12 @@ main(int argc, char *argv[])
free (passwd);
}
- err = ugids_make_auth (&ugids, MACH_PORT_NULL, &auth);
- if (err)
- fail (3, err, "Authentication failure", 0);
-
err = proc_getsid (proc_server, pid, &sid);
assert_perror (err); /* This should never fail. */
- if (!no_login && parent_uids.num != 0)
+ if (!no_login
+ && (parent_uids.num != 0
+ || ugids.eff_uids.num + ugids.avail_uids.num > 0))
/* Make a new login collection (but only for real users). */
{
char *user = envz_get (args, args_len, "USER");
@@ -660,7 +663,7 @@ main(int argc, char *argv[])
if (ugids.eff_uids.num + ugids.avail_uids.num == 0)
/* We're transiting from having some uids to having none, which means
this is probably a new login session. Unless specified otherwise,
- set a timer to kill this session if it hasn't aquired any ids by
+ set a timer to kill this session if it hasn't acquired any ids by
then. Note that we fork off the timer process before clearing the
process owner: because we're interested in killing unowned
processes, proc's in-same-login-session rule should apply to us
@@ -690,6 +693,7 @@ main(int argc, char *argv[])
for (i = 0; i < INIT_PORT_MAX; i++)
ports[i] = MACH_PORT_NULL;
ports[INIT_PORT_PROC] = getproc ();
+ ports[INIT_PORT_CTTYID] = getcttyid ();
ports[INIT_PORT_CRDIR] = getcrdir (); /* May be replaced below. */
ports[INIT_PORT_CWDIR] = getcwdir (); /* " */
@@ -698,11 +702,10 @@ main(int argc, char *argv[])
if (err)
error (40, err, "Port reauth failure");
- /* These are the default values for the child's root/cwd. We don't want to
+ /* These are the default values for the child's root. We don't want to
modify PORTS just yet, because we use it to do child-authenticated
lookups. */
root = ports[INIT_PORT_CRDIR];
- cwd = ports[INIT_PORT_CWDIR];
/* Find the shell executable (we copy the name, as ARGS may be changed). */
if (shell_arg && sh_args && *sh_args)
@@ -757,13 +760,15 @@ main(int argc, char *argv[])
arg = envz_get (args, args_len, "HOME");
if (arg && *arg)
{
- cwd = child_lookup (arg, 0, O_RDONLY);
+ mach_port_t cwd = child_lookup (arg, 0, O_RDONLY);
if (cwd == MACH_PORT_NULL)
{
error (0, errno, "%s", arg);
error (0, 0, "Using HOME=/");
envz_add (&args, &args_len, "HOME", "/");
}
+ else
+ ports[INIT_PORT_CWDIR] = cwd;
}
arg = envz_get (args, args_len, "ROOT");
@@ -813,25 +818,24 @@ main(int argc, char *argv[])
if (no_login)
sh_arg0 = shell_base;
+ else if (ugids.eff_uids.num + ugids.avail_uids.num == 0)
+ /* Use a special format for the argv[0] of a login prompt shell,
+ so that `ps' shows something informative in the COMMAND field.
+ This string must begin with a `-', the convention to tell the
+ shell to be a login shell (i.e. run .profile and the like). */
+ err = (asprintf (&sh_arg0, "-login prompt (%s)", shell_base) == -1
+ ? ENOMEM : 0);
else
- {
- sh_arg0 = malloc (strlen (shell_base) + 2);
- if (! sh_arg0)
- err = ENOMEM;
- else
- /* Prepend the name with a `-', as is the odd custom. */
- {
- sh_arg0[0] = '-';
- strcpy (sh_arg0 + 1, shell_base);
- }
- }
+ /* Prepend a `-' to the name, which is the ancient canonical
+ way to tell the shell that it's a login shell. */
+ err = asprintf (&sh_arg0, "-%s", shell_base) == -1 ? ENOMEM : 0;
}
if (! err)
err = argz_insert (&sh_args, &sh_args_len, sh_args, sh_arg0);
if (err)
error (21, err, "Error building shell args");
- /* Maybe output the message of the day. Note that we we the child's
+ /* Maybe output the message of the day. Note that we use the child's
authentication to do it, so that this program can't be used to read
arbitrary files! */
arg = envz_get (args, args_len, "MOTD");
@@ -851,16 +855,15 @@ main(int argc, char *argv[])
}
/* Now that we don't need to use PORTS for lookups anymore, put the correct
- ROOT and CWD in. */
+ ROOT in. */
ports[INIT_PORT_CRDIR] = root;
- ports[INIT_PORT_CWDIR] = cwd;
/* Get rid of any accumulated null entries in env. */
envz_strip (&env, &env_len);
/* No more authentications to fail, so cross our fingers and add our utmp
entry. */
-
+
if (pid == sid)
/* Only add utmp entries for the session leader. */
add_utmp_entry (args, args_len, !idvec_contains (&parent_uids, 0));
@@ -888,5 +891,5 @@ main(int argc, char *argv[])
if (err)
error(5, err, "%s", shell);
- exit(0);
+ return 0;
}