aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2002-06-23 04:24:25 +0000
committerandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2002-06-23 04:24:25 +0000
commita99f567fcd02370d96d496993ec01f3ae57eec1b (patch)
tree632fbb26b13ad67f6efa335c33a22551b2707930
parent7266ca05a5470f5998adf16f30a34e490461ac44 (diff)
downloadbusybox-w32-a99f567fcd02370d96d496993ec01f3ae57eec1b.tar.gz
busybox-w32-a99f567fcd02370d96d496993ec01f3ae57eec1b.tar.bz2
busybox-w32-a99f567fcd02370d96d496993ec01f3ae57eec1b.zip
Port over the last of the tinylogin applets
-Erik git-svn-id: svn://busybox.net/trunk/busybox@4961 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--include/applets.h9
-rw-r--r--include/libbb.h30
-rw-r--r--include/shadow_.h82
-rw-r--r--include/usage.h34
-rw-r--r--libbb/Makefile.in10
-rw-r--r--libbb/change_identity.c54
-rw-r--r--libbb/correct_password.c78
-rw-r--r--libbb/libc5.c18
-rw-r--r--libbb/messages.c36
-rw-r--r--libbb/obscure.c246
-rw-r--r--libbb/pw_encrypt.c48
-rw-r--r--libbb/pwd2spwd.c73
-rw-r--r--libbb/restricted_shell.c57
-rw-r--r--libbb/run_shell.c81
-rw-r--r--libbb/setup_environment.c (renamed from loginutils/tinylogin.c)122
-rw-r--r--loginutils/Makefile.in9
-rw-r--r--loginutils/addgroup.c9
-rw-r--r--loginutils/adduser.c56
-rw-r--r--loginutils/config.in17
-rw-r--r--loginutils/deluser.c28
-rw-r--r--loginutils/login.c43
-rw-r--r--loginutils/passwd.c408
-rw-r--r--loginutils/su.c9
-rw-r--r--loginutils/sulogin.c184
-rw-r--r--loginutils/tinylogin.h10
-rw-r--r--loginutils/vlock.c229
26 files changed, 1722 insertions, 258 deletions
diff --git a/include/applets.h b/include/applets.h
index 3a8c731a5..c2d7acf4b 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -335,6 +335,9 @@
335#ifdef CONFIG_OD 335#ifdef CONFIG_OD
336 APPLET(od, od_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) 336 APPLET(od, od_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER)
337#endif 337#endif
338#ifdef CONFIG_PASSWD
339 APPLET(passwd, passwd_main, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS)
340#endif
338#ifdef CONFIG_PIDOF 341#ifdef CONFIG_PIDOF
339 APPLET(pidof, pidof_main, _BB_DIR_BIN, _BB_SUID_NEVER) 342 APPLET(pidof, pidof_main, _BB_DIR_BIN, _BB_SUID_NEVER)
340#endif 343#endif
@@ -419,6 +422,9 @@
419#ifdef CONFIG_SU 422#ifdef CONFIG_SU
420 APPLET(su, su_main, _BB_DIR_BIN, _BB_SUID_ALWAYS) 423 APPLET(su, su_main, _BB_DIR_BIN, _BB_SUID_ALWAYS)
421#endif 424#endif
425#ifdef CONFIG_SULOGIN
426 APPLET(sulogin, sulogin_main, _BB_DIR_SBIN, _BB_SUID_NEVER)
427#endif
422#ifdef CONFIG_SWAPONOFF 428#ifdef CONFIG_SWAPONOFF
423 APPLET(swapoff, swap_on_off_main, _BB_DIR_SBIN, _BB_SUID_NEVER) 429 APPLET(swapoff, swap_on_off_main, _BB_DIR_SBIN, _BB_SUID_NEVER)
424#endif 430#endif
@@ -505,6 +511,9 @@
505#ifdef CONFIG_VI 511#ifdef CONFIG_VI
506 APPLET(vi, vi_main, _BB_DIR_BIN, _BB_SUID_NEVER) 512 APPLET(vi, vi_main, _BB_DIR_BIN, _BB_SUID_NEVER)
507#endif 513#endif
514#ifdef CONFIG_VLOCK
515 APPLET(vlock, vlock_main, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS)
516#endif
508#ifdef CONFIG_WATCHDOG 517#ifdef CONFIG_WATCHDOG
509 APPLET(watchdog, watchdog_main, _BB_DIR_SBIN, _BB_SUID_NEVER) 518 APPLET(watchdog, watchdog_main, _BB_DIR_SBIN, _BB_SUID_NEVER)
510#endif 519#endif
diff --git a/include/libbb.h b/include/libbb.h
index 0b2411fcd..2b9fd5fd6 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -39,6 +39,16 @@
39 39
40#include "config.h" 40#include "config.h"
41 41
42#include "pwd.h"
43#include "grp.h"
44#ifdef CONFIG_FEATURE_SHADOWPASSWDS
45#include "shadow_.h"
46#endif
47#ifdef CONFIG_FEATURE_SHA1_PASSWORDS
48# include "sha1.h"
49#endif
50
51
42#if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__) 52#if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__)
43/* libc5 doesn't define socklen_t */ 53/* libc5 doesn't define socklen_t */
44typedef unsigned int socklen_t; 54typedef unsigned int socklen_t;
@@ -260,6 +270,15 @@ extern const char * const too_few_args;
260extern const char * const name_longer_than_foo; 270extern const char * const name_longer_than_foo;
261extern const char * const unknown; 271extern const char * const unknown;
262extern const char * const can_not_create_raw_socket; 272extern const char * const can_not_create_raw_socket;
273extern const char * const nologin_file;
274extern const char * const passwd_file;
275extern const char * const shadow_file;
276extern const char * const gshadow_file;
277extern const char * const group_file;
278extern const char * const securetty_file;
279extern const char * const motd_file;
280extern const char * const issue_file;
281extern const char * const _path_login;
263 282
264#ifdef CONFIG_FEATURE_DEVFS 283#ifdef CONFIG_FEATURE_DEVFS
265# define CURRENT_VC "/dev/vc/0" 284# define CURRENT_VC "/dev/vc/0"
@@ -299,4 +318,15 @@ void reset_ino_dev_hashtable(void);
299extern size_t xstrlen(const char *string); 318extern size_t xstrlen(const char *string);
300#define strlen(x) xstrlen(x) 319#define strlen(x) xstrlen(x)
301 320
321
322#define FAIL_DELAY 3
323extern void change_identity ( const struct passwd *pw );
324extern void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args );
325extern int restricted_shell ( const char *shell );
326extern void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw );
327extern int correct_password ( const struct passwd *pw );
328extern char *pw_encrypt(const char *clear, const char *salt);
329extern struct spwd *pwd_to_spwd(const struct passwd *pw);
330extern int obscure(const char *old, const char *newval, const struct passwd *pwdp);
331
302#endif /* __LIBCONFIG_H__ */ 332#endif /* __LIBCONFIG_H__ */
diff --git a/include/shadow_.h b/include/shadow_.h
new file mode 100644
index 000000000..a677d5262
--- /dev/null
+++ b/include/shadow_.h
@@ -0,0 +1,82 @@
1/*
2 * Copyright 1988 - 1994, Julianne Frances Haugh <jockgrrl@austin.rr.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef _H_SHADOW
31#define _H_SHADOW
32
33
34#ifdef USE_SYSTEM_SHADOW
35#include <shadow.h>
36#else
37
38/*
39 * This information is not derived from AT&T licensed sources. Posted
40 * to the USENET 11/88, and updated 11/90 with information from SVR4.
41 *
42 * $Id: shadow_.h,v 1.1 2002/06/23 04:24:20 andersen Exp $
43 */
44
45typedef long sptime;
46
47/*
48 * Shadow password security file structure.
49 */
50
51struct spwd {
52 char *sp_namp; /* login name */
53 char *sp_pwdp; /* encrypted password */
54 sptime sp_lstchg; /* date of last change */
55 sptime sp_min; /* minimum number of days between changes */
56 sptime sp_max; /* maximum number of days between changes */
57 sptime sp_warn; /* number of days of warning before password
58 expires */
59 sptime sp_inact; /* number of days after password expires
60 until the account becomes unusable. */
61 sptime sp_expire; /* days since 1/1/70 until account expires */
62 unsigned long sp_flag; /* reserved for future use */
63};
64
65/*
66 * Shadow password security file functions.
67 */
68
69#include <stdio.h> /* for FILE */
70
71extern struct spwd *getspent(void);
72extern struct spwd *sgetspent(const char *);
73extern struct spwd *fgetspent(FILE *);
74extern void setspent(void);
75extern void endspent(void);
76extern int putspent(const struct spwd *, FILE *);
77extern struct spwd *getspnam(const char *name);
78extern struct spwd *pwd_to_spwd(const struct passwd *pw);
79
80#endif /* USE_LOCAL_SHADOW */
81
82#endif /* _H_SHADOW */
diff --git a/include/usage.h b/include/usage.h
index 08ee00d77..18593fb1d 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -1321,6 +1321,24 @@
1321 "Write an unambiguous representation, octal bytes by default, of FILE\n"\ 1321 "Write an unambiguous representation, octal bytes by default, of FILE\n"\
1322 "to standard output. With no FILE, or when FILE is -, read standard input." 1322 "to standard output. With no FILE, or when FILE is -, read standard input."
1323 1323
1324#ifdef CONFIG_FEATURE_SHA1_PASSWORDS
1325 #define PASSWORD_ALG_TYPES(a) a
1326#else
1327 #define PASSWORD_ALG_TYPES(a)
1328#endif
1329#define passwd_trivial_usage \
1330 "[OPTION] [name]"
1331#define passwd_full_usage \
1332 "CChange a user password. If no name is specified,\n" \
1333 "changes the password for the current user.\n" \
1334 "Options:\n" \
1335 "\t-a\tDefine which algorithm shall be used for the password.\n" \
1336 "\t\t\t(Choices: des, md5" \
1337 CONFIG_FEATURE_SHA1_PASSWORDS(", sha1") \
1338 ")\n\t-d\tDelete the password for the specified user account.\n" \
1339 "\t-l\tLocks (disables) the specified user account.\n" \
1340 "\t-u\tUnlocks (re-enables) the specified user account.";
1341
1324#define pidof_trivial_usage \ 1342#define pidof_trivial_usage \
1325 "process-name [process-name ...]" 1343 "process-name [process-name ...]"
1326#define pidof_full_usage \ 1344#define pidof_full_usage \
@@ -1586,6 +1604,15 @@
1586 "Options:\n" \ 1604 "Options:\n" \
1587 "\t-p\tPreserve environment" 1605 "\t-p\tPreserve environment"
1588 1606
1607#define sulogin_trivial_usage \
1608 "[OPTION]... [tty-device]"
1609#define sulogin_full_usage \
1610 "Single user login\n" \
1611 "Options:\n" \
1612 "\t-f\tDo not authenticate (user already authenticated)\n" \
1613 "\t-h\tName of the remote host for this login.\n" \
1614 "\t-p\tPreserve environment."
1615
1589#define swapoff_trivial_usage \ 1616#define swapoff_trivial_usage \
1590 "[OPTION] [DEVICE]" 1617 "[OPTION] [DEVICE]"
1591#define swapoff_full_usage \ 1618#define swapoff_full_usage \
@@ -1956,6 +1983,13 @@
1956 "Options:\n" \ 1983 "Options:\n" \
1957 "\t-R\tRead-only- do not write to the file." 1984 "\t-R\tRead-only- do not write to the file."
1958 1985
1986#define vlock_trivial_usage \
1987 "[OPTIONS]"
1988#define vlock_full_usage \
1989 "Lock a virtual terminal. A password is required to unlock\n" \
1990 "Options:\n" \
1991 "\t-a\tLock all VTs"
1992
1959#define watchdog_trivial_usage \ 1993#define watchdog_trivial_usage \
1960 "DEV" 1994 "DEV"
1961#define watchdog_full_usage \ 1995#define watchdog_full_usage \
diff --git a/libbb/Makefile.in b/libbb/Makefile.in
index c6493bfa6..2af70f8c7 100644
--- a/libbb/Makefile.in
+++ b/libbb/Makefile.in
@@ -34,17 +34,21 @@ LIBBB_SRC:= \
34 my_getpwuid.c parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c \ 34 my_getpwuid.c parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c \
35 print_file.c process_escape_sequence.c read_package_field.c recursive_action.c \ 35 print_file.c process_escape_sequence.c read_package_field.c recursive_action.c \
36 safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \ 36 safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \
37 trim.c unzip.c uncompress.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \ 37 trim.c unzip.c uncompress.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c \
38 xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \ 38 xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \
39 copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \ 39 copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \
40 dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \ 40 dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \
41 simplify_path.c inet_common.c inode_hash.c 41 simplify_path.c inet_common.c inode_hash.c obscure.c pwd2spwd.c xfuncs.c \
42 correct_password.c change_identity.c setup_environment.c run_shell.c \
43 pw_encrypt.c restricted_shell.c
42LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) 44LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC))
43 45
44LIBBB_MSRC:=$(LIBBB_DIR)messages.c 46LIBBB_MSRC:=$(LIBBB_DIR)messages.c
45LIBBB_MOBJ:=full_version.o name_too_long.o omitting_directory.o not_a_directory.o \ 47LIBBB_MOBJ:=full_version.o name_too_long.o omitting_directory.o not_a_directory.o \
46 memory_exhausted.o invalid_date.o invalid_option.o io_error.o dash_dash_help.o \ 48 memory_exhausted.o invalid_date.o invalid_option.o io_error.o dash_dash_help.o \
47 write_error.o too_few_args.o name_longer_than_foo.o unknown.o can_not_create_raw_socket.o 49 write_error.o too_few_args.o name_longer_than_foo.o unknown.o can_not_create_raw_socket.o \
50 shadow_file.o passwd_file.o group_file.o gshadow_file.o nologin_file.o securetty_file.o \
51 motd_file.o
48LIBBB_MOBJS=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ)) 52LIBBB_MOBJS=$(patsubst %,$(LIBBB_DIR)%, $(LIBBB_MOBJ))
49 53
50libraries-y+=$(LIBBB_DIR)$(LIBBB_AR) 54libraries-y+=$(LIBBB_DIR)$(LIBBB_AR)
diff --git a/libbb/change_identity.c b/libbb/change_identity.c
new file mode 100644
index 000000000..819b216e0
--- /dev/null
+++ b/libbb/change_identity.c
@@ -0,0 +1,54 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdio.h>
32#include <errno.h>
33#include <unistd.h>
34#include <string.h>
35#include <stdlib.h>
36#include <syslog.h>
37#include <ctype.h>
38
39#include "libbb.h"
40
41
42/* Become the user and group(s) specified by PW. */
43void change_identity ( const struct passwd *pw )
44{
45 if ( initgroups ( pw-> pw_name, pw-> pw_gid ) == -1 )
46 perror_msg_and_die ( "cannot set groups" );
47 endgrent ( );
48
49 if ( setgid ( pw-> pw_gid ))
50 perror_msg_and_die ( "cannot set group id" );
51 if ( setuid ( pw->pw_uid ))
52 perror_msg_and_die ( "cannot set user id" );
53}
54
diff --git a/libbb/correct_password.c b/libbb/correct_password.c
new file mode 100644
index 000000000..758b89eed
--- /dev/null
+++ b/libbb/correct_password.c
@@ -0,0 +1,78 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdio.h>
32#include <errno.h>
33#include <unistd.h>
34#include <string.h>
35#include <stdlib.h>
36#include <syslog.h>
37#include <ctype.h>
38#include <crypt.h>
39
40#include "libbb.h"
41
42
43
44/* Ask the user for a password.
45 Return 1 if the user gives the correct password for entry PW,
46 0 if not. Return 1 without asking for a password if run by UID 0
47 or if PW has an empty password. */
48
49int correct_password ( const struct passwd *pw )
50{
51 char *unencrypted, *encrypted, *correct;
52
53#ifdef CONFIG_FEATURE_SHADOWPASSWDS
54 if (( strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
55 struct spwd *sp = getspnam ( pw-> pw_name );
56
57 if ( !sp )
58 error_msg_and_die ( "no valid shadow password" );
59
60 correct = sp-> sp_pwdp;
61 }
62 else
63#endif
64 correct = pw-> pw_passwd;
65
66 if ( correct == 0 || correct[0] == '\0' )
67 return 1;
68
69 unencrypted = getpass ( "Password: " );
70 if ( !unencrypted )
71 {
72 fputs ( "getpass: cannot open /dev/tty\n", stderr );
73 return 0;
74 }
75 encrypted = crypt ( unencrypted, correct );
76 memset ( unencrypted, 0, xstrlen ( unencrypted ));
77 return ( strcmp ( encrypted, correct ) == 0 ) ? 1 : 0;
78}
diff --git a/libbb/libc5.c b/libbb/libc5.c
index df622f65b..af15d1ac7 100644
--- a/libbb/libc5.c
+++ b/libbb/libc5.c
@@ -11,6 +11,24 @@
11 11
12#if __GNU_LIBRARY__ < 5 12#if __GNU_LIBRARY__ < 5
13 13
14/*
15 * Some systems already have updwtmp(). Some don't... This is
16 * the updwtmp() implementation from uClibc, Copyright 2002 by
17 * Erik Andersen <andersee@debian.org>
18 */
19extern void updwtmp(const char *wtmp_file, const struct utmp *lutmp)
20{
21 int fd;
22
23 fd = open(wtmp_file, O_APPEND | O_WRONLY, 0);
24 if (fd >= 0) {
25 if (lockf(fd, F_LOCK, 0)==0) {
26 write(fd, (const char *) lutmp, sizeof(struct utmp));
27 lockf(fd, F_ULOCK, 0);
28 close(fd);
29 }
30 }
31}
14 32
15/* Copyright (C) 1991 Free Software Foundation, Inc. 33/* Copyright (C) 1991 Free Software Foundation, Inc.
16This file is part of the GNU C Library. 34This file is part of the GNU C Library.
diff --git a/libbb/messages.c b/libbb/messages.c
index 895cfdc2b..185c1ee91 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -66,3 +66,39 @@
66#ifdef L_can_not_create_raw_socket 66#ifdef L_can_not_create_raw_socket
67 const char * const can_not_create_raw_socket = "can`t create raw socket"; 67 const char * const can_not_create_raw_socket = "can`t create raw socket";
68#endif 68#endif
69
70#ifdef L_passwd_file
71#define PASSWD_FILE "/etc/passwd"
72const char * const passwd_file = PASSWD_FILE;
73#endif
74
75#ifdef L_shadow_file
76#define SHADOW_FILE "/etc/shadow"
77const char * const shadow_file = SHADOW_FILE;
78#endif
79
80#ifdef L_group_file
81#define GROUP_FILE "/etc/group"
82const char * const group_file = GROUP_FILE;
83#endif
84
85#ifdef L_gshadow_file
86#define GSHADOW_FILE "/etc/gshadow"
87const char * const gshadow_file = GSHADOW_FILE;
88#endif
89
90#ifdef L_nologin_file
91#define NOLOGIN_FILE "/etc/nologin"
92const char * const nologin_file = NOLOGIN_FILE;
93#endif
94
95#ifdef L_securetty_file
96#define SECURETTY_FILE "/etc/securetty"
97const char * const securetty_file = SECURETTY_FILE;
98#endif
99
100#ifdef L_motd_file
101#define MOTD_FILE "/etc/motd"
102const char * const motd_file = MOTD_FILE;
103#endif
104
diff --git a/libbb/obscure.c b/libbb/obscure.c
new file mode 100644
index 000000000..dc7de751d
--- /dev/null
+++ b/libbb/obscure.c
@@ -0,0 +1,246 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright 1989 - 1994, Julianne Frances Haugh <jockgrrl@austin.rr.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/*
32 * This version of obscure.c contains modifications to support "cracklib"
33 * by Alec Muffet (alec.muffett@uk.sun.com). You must obtain the Cracklib
34 * library source code for this function to operate.
35 */
36
37#include <stdlib.h>
38#include <stdio.h>
39#include <string.h>
40#include <ctype.h>
41#include "libbb.h"
42
43/*
44 * can't be a palindrome - like `R A D A R' or `M A D A M'
45 */
46
47static int palindrome(const char *old, const char *newval)
48{
49 int i, j;
50
51 i = strlen(newval);
52
53 for (j = 0; j < i; j++)
54 if (newval[i - j - 1] != newval[j])
55 return 0;
56
57 return 1;
58}
59
60/*
61 * more than half of the characters are different ones.
62 */
63
64static int similiar(const char *old, const char *newval)
65{
66 int i, j;
67
68 for (i = j = 0; newval[i] && old[i]; i++)
69 if (strchr(newval, old[i]))
70 j++;
71
72 if (i >= j * 2)
73 return 0;
74
75 return 1;
76}
77
78/*
79 * a nice mix of characters.
80 */
81
82static int simple(const char *old, const char *newval)
83{
84 int digits = 0;
85 int uppers = 0;
86 int lowers = 0;
87 int others = 0;
88 int size;
89 int i;
90
91 for (i = 0; newval[i]; i++) {
92 if (isdigit(newval[i]))
93 digits++;
94 else if (isupper(newval[i]))
95 uppers++;
96 else if (islower(newval[i]))
97 lowers++;
98 else
99 others++;
100 }
101
102 /*
103 * The scam is this - a password of only one character type
104 * must be 8 letters long. Two types, 7, and so on.
105 */
106
107 size = 9;
108 if (digits)
109 size--;
110 if (uppers)
111 size--;
112 if (lowers)
113 size--;
114 if (others)
115 size--;
116
117 if (size <= i)
118 return 0;
119
120 return 1;
121}
122
123static char *str_lower(char *string)
124{
125 char *cp;
126
127 for (cp = string; *cp; cp++)
128 *cp = tolower(*cp);
129 return string;
130}
131
132static char *password_check(const char *old, const char *newval, const struct passwd *pwdp)
133{
134 char *msg = NULL;
135 char *oldmono, *newmono, *wrapped;
136
137 if (strcmp(newval, old) == 0)
138 return "no change";
139
140 newmono = str_lower(xstrdup(newval));
141 oldmono = str_lower(xstrdup(old));
142 wrapped = (char *) xmalloc(strlen(oldmono) * 2 + 1);
143 strcpy(wrapped, oldmono);
144 strcat(wrapped, oldmono);
145
146 if (palindrome(oldmono, newmono))
147 msg = "a palindrome";
148
149 if (!msg && strcmp(oldmono, newmono) == 0)
150 msg = "case changes only";
151
152 if (!msg && similiar(oldmono, newmono))
153 msg = "too similiar";
154
155 if (!msg && simple(old, newval))
156 msg = "too simple";
157
158 if (!msg && strstr(wrapped, newmono))
159 msg = "rotated";
160
161 bzero(newmono, strlen(newmono));
162 bzero(oldmono, strlen(oldmono));
163 bzero(wrapped, strlen(wrapped));
164 free(newmono);
165 free(oldmono);
166 free(wrapped);
167
168 return msg;
169}
170
171static char *obscure_msg(const char *old, const char *newval, const struct passwd *pwdp)
172{
173 int maxlen, oldlen, newlen;
174 char *new1, *old1, *msg;
175
176 oldlen = strlen(old);
177 newlen = strlen(newval);
178
179#if 0 /* why not check the password when set for the first time? --marekm */
180 if (old[0] == '\0')
181 /* return (1); */
182 return NULL;
183#endif
184
185 if (newlen < 5)
186 return "too short";
187
188 /*
189 * Remaining checks are optional.
190 */
191 /* Not for us -- Sean
192 *if (!getdef_bool("OBSCURE_CHECKS_ENAB"))
193 * return NULL;
194 */
195 msg = password_check(old, newval, pwdp);
196 if (msg)
197 return msg;
198
199 /* The traditional crypt() truncates passwords to 8 chars. It is
200 possible to circumvent the above checks by choosing an easy
201 8-char password and adding some random characters to it...
202 Example: "password$%^&*123". So check it again, this time
203 truncated to the maximum length. Idea from npasswd. --marekm */
204
205 maxlen = 8;
206 if (oldlen <= maxlen && newlen <= maxlen)
207 return NULL;
208
209 new1 = (char *) xstrdup(newval);
210 old1 = (char *) xstrdup(old);
211 if (newlen > maxlen)
212 new1[maxlen] = '\0';
213 if (oldlen > maxlen)
214 old1[maxlen] = '\0';
215
216 msg = password_check(old1, new1, pwdp);
217
218 bzero(new1, newlen);
219 bzero(old1, oldlen);
220 free(new1);
221 free(old1);
222
223 return msg;
224}
225
226/*
227 * Obscure - see if password is obscure enough.
228 *
229 * The programmer is encouraged to add as much complexity to this
230 * routine as desired. Included are some of my favorite ways to
231 * check passwords.
232 */
233
234extern int obscure(const char *old, const char *newval, const struct passwd *pwdp)
235{
236 char *msg = obscure_msg(old, newval, pwdp);
237
238 /* if (msg) { */
239 if (msg != NULL) {
240 printf("Bad password: %s.\n", msg);
241 /* return 0; */
242 return 1;
243 }
244 /* return 1; */
245 return 0;
246}
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c
new file mode 100644
index 000000000..0e4eb9f8a
--- /dev/null
+++ b/libbb/pw_encrypt.c
@@ -0,0 +1,48 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routine.
4 *
5 * Copyright (C) 1999-2002 by Erik Andersen <andersee@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <string.h>
24#include <crypt.h>
25#include "libbb.h"
26
27
28extern char *pw_encrypt(const char *clear, const char *salt)
29{
30 static char cipher[128];
31 char *cp;
32
33#ifdef CONFIG_FEATURE_SHA1_PASSWORDS
34 if (strncmp(salt, "$2$", 3) == 0) {
35 return sha1_crypt(clear);
36 }
37#endif
38 cp = (char *) crypt(clear, salt);
39 /* if crypt (a nonstandard crypt) returns a string too large,
40 truncate it so we don't overrun buffers and hope there is
41 enough security in what's left */
42 if (strlen(cp) > sizeof(cipher)-1) {
43 cp[sizeof(cipher)-1] = 0;
44 }
45 strcpy(cipher, cp);
46 return cipher;
47}
48
diff --git a/libbb/pwd2spwd.c b/libbb/pwd2spwd.c
new file mode 100644
index 000000000..95a2e4684
--- /dev/null
+++ b/libbb/pwd2spwd.c
@@ -0,0 +1,73 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright 1989 - 1994, Julianne Frances Haugh <jockgrrl@austin.rr.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <time.h>
32#include <sys/types.h>
33#include "libbb.h"
34
35/*
36 * pwd_to_spwd - create entries for new spwd structure
37 *
38 * pwd_to_spwd() creates a new (struct spwd) containing the
39 * information in the pointed-to (struct passwd).
40 */
41#define DAY (24L*3600L)
42#define WEEK (7*DAY)
43#define SCALE DAY
44struct spwd *pwd_to_spwd(const struct passwd *pw)
45{
46 static struct spwd sp;
47
48 /*
49 * Nice, easy parts first. The name and passwd map directly
50 * from the old password structure to the new one.
51 */
52 sp.sp_namp = pw->pw_name;
53 sp.sp_pwdp = pw->pw_passwd;
54
55 /*
56 * Defaults used if there is no pw_age information.
57 */
58 sp.sp_min = 0;
59 sp.sp_max = (10000L * DAY) / SCALE;
60 sp.sp_lstchg = time((time_t *) 0) / SCALE;
61
62 /*
63 * These fields have no corresponding information in the password
64 * file. They are set to uninitialized values.
65 */
66 sp.sp_warn = -1;
67 sp.sp_expire = -1;
68 sp.sp_inact = -1;
69 sp.sp_flag = -1;
70
71 return &sp;
72}
73
diff --git a/libbb/restricted_shell.c b/libbb/restricted_shell.c
new file mode 100644
index 000000000..74a64140f
--- /dev/null
+++ b/libbb/restricted_shell.c
@@ -0,0 +1,57 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdio.h>
32#include <errno.h>
33#include <unistd.h>
34#include <string.h>
35#include <stdlib.h>
36#include <syslog.h>
37#include <ctype.h>
38#include "libbb.h"
39
40
41
42/* Return 1 if SHELL is a restricted shell (one not returned by
43 getusershell), else 0, meaning it is a standard shell. */
44
45int restricted_shell ( const char *shell )
46{
47 char *line;
48
49 setusershell ( );
50 while (( line = getusershell ( ))) {
51 if (( *line != '#' ) && ( strcmp ( line, shell ) == 0 ))
52 break;
53 }
54 endusershell ( );
55 return line ? 0 : 1;
56}
57
diff --git a/libbb/run_shell.c b/libbb/run_shell.c
new file mode 100644
index 000000000..30050fecb
--- /dev/null
+++ b/libbb/run_shell.c
@@ -0,0 +1,81 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright 1989 - 1991, Julianne Frances Haugh <jockgrrl@austin.rr.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <stdio.h>
32#include <errno.h>
33#include <unistd.h>
34#include <string.h>
35#include <stdlib.h>
36#include <syslog.h>
37#include <ctype.h>
38#include "libbb.h"
39
40
41/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
42 If COMMAND is nonzero, pass it to the shell with the -c option.
43 If ADDITIONAL_ARGS is nonzero, pass it to the shell as more
44 arguments. */
45
46void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args )
47{
48 const char **args;
49 int argno = 1;
50 int additional_args_cnt = 0;
51
52 for ( args = additional_args; args && *args; args++ )
53 additional_args_cnt++;
54
55 if ( additional_args )
56 args = (const char **) xmalloc (sizeof (char *) * ( 4 + additional_args_cnt ));
57 else
58 args = (const char **) xmalloc (sizeof (char *) * 4 );
59
60 args [0] = get_last_path_component ( xstrdup ( shell ));
61
62 if ( loginshell ) {
63 char *args0 = xmalloc ( xstrlen ( args [0] ) + 2 );
64 args0 [0] = '-';
65 strcpy ( args0 + 1, args [0] );
66 args [0] = args0;
67 }
68
69 if ( command ) {
70 args [argno++] = "-c";
71 args [argno++] = command;
72 }
73 if ( additional_args ) {
74 for ( ; *additional_args; ++additional_args )
75 args [argno++] = *additional_args;
76 }
77 args [argno] = 0;
78 execv ( shell, (char **) args );
79 perror_msg_and_die ( "cannot run %s", shell );
80}
81
diff --git a/loginutils/tinylogin.c b/libbb/setup_environment.c
index bd611fd70..dc171fa1f 100644
--- a/loginutils/tinylogin.c
+++ b/libbb/setup_environment.c
@@ -28,8 +28,6 @@
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 */ 29 */
30 30
31#include "busybox.h"
32
33#include <stdio.h> 31#include <stdio.h>
34#include <errno.h> 32#include <errno.h>
35#include <unistd.h> 33#include <unistd.h>
@@ -37,98 +35,19 @@
37#include <stdlib.h> 35#include <stdlib.h>
38#include <syslog.h> 36#include <syslog.h>
39#include <ctype.h> 37#include <ctype.h>
38#include "libbb.h"
40 39
41#include "pwd.h"
42#include "grp.h"
43 40
44#ifdef CONFIG_FEATURE_SHADOWPASSWDS
45#include "shadow.h"
46#endif
47 41
48#define DEFAULT_LOGIN_PATH "/bin:/usr/bin" 42#define DEFAULT_LOGIN_PATH "/bin:/usr/bin"
49#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin" 43#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin"
50 44
51
52static void xsetenv ( const char *key, const char *value ) 45static void xsetenv ( const char *key, const char *value )
53{ 46{
54 if ( setenv ( key, value, 1 )) 47 if ( setenv ( key, value, 1 ))
55 error_msg_and_die ( "out of memory" ); 48 error_msg_and_die ( "out of memory" );
56} 49}
57 50
58/* Become the user and group(s) specified by PW. */
59
60void change_identity ( const struct passwd *pw )
61{
62 if ( initgroups ( pw-> pw_name, pw-> pw_gid ) == -1 )
63 perror_msg_and_die ( "cannot set groups" );
64 endgrent ( );
65
66 if ( setgid ( pw-> pw_gid ))
67 perror_msg_and_die ( "cannot set group id" );
68 if ( setuid ( pw->pw_uid ))
69 perror_msg_and_die ( "cannot set user id" );
70}
71
72/* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
73 If COMMAND is nonzero, pass it to the shell with the -c option.
74 If ADDITIONAL_ARGS is nonzero, pass it to the shell as more
75 arguments. */
76
77void run_shell ( const char *shell, int loginshell, const char *command, const char **additional_args )
78{
79 const char **args;
80 int argno = 1;
81 int additional_args_cnt = 0;
82
83 for ( args = additional_args; args && *args; args++ )
84 additional_args_cnt++;
85
86 if ( additional_args )
87 args = (const char **) xmalloc (sizeof (char *) * ( 4 + additional_args_cnt ));
88 else
89 args = (const char **) xmalloc (sizeof (char *) * 4 );
90
91 args [0] = get_last_path_component ( xstrdup ( shell ));
92
93 if ( loginshell ) {
94 char *args0 = xmalloc ( xstrlen ( args [0] ) + 2 );
95 args0 [0] = '-';
96 strcpy ( args0 + 1, args [0] );
97 args [0] = args0;
98 }
99
100 if ( command ) {
101 args [argno++] = "-c";
102 args [argno++] = command;
103 }
104 if ( additional_args ) {
105 for ( ; *additional_args; ++additional_args )
106 args [argno++] = *additional_args;
107 }
108 args [argno] = 0;
109 execv ( shell, (char **) args );
110 perror_msg_and_die ( "cannot run %s", shell );
111}
112
113/* Return 1 if SHELL is a restricted shell (one not returned by
114 getusershell), else 0, meaning it is a standard shell. */
115
116int restricted_shell ( const char *shell )
117{
118 char *line;
119
120 setusershell ( );
121 while (( line = getusershell ( ))) {
122 if (( *line != '#' ) && ( strcmp ( line, shell ) == 0 ))
123 break;
124 }
125 endusershell ( );
126 return line ? 0 : 1;
127}
128
129/* Update `environ' for the new shell based on PW, with SHELL being
130 the value for the SHELL environment variable. */
131
132void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw ) 51void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw )
133{ 52{
134 if ( loginshell ) { 53 if ( loginshell ) {
@@ -172,38 +91,3 @@ void setup_environment ( const char *shell, int loginshell, int changeenv, const
172 } 91 }
173} 92}
174 93
175/* Ask the user for a password.
176 Return 1 if the user gives the correct password for entry PW,
177 0 if not. Return 1 without asking for a password if run by UID 0
178 or if PW has an empty password. */
179
180int correct_password ( const struct passwd *pw )
181{
182 char *unencrypted, *encrypted, *correct;
183
184#ifdef CONFIG_FEATURE_SHADOWPASSWDS
185 if (( strcmp ( pw-> pw_passwd, "x" ) == 0 ) || ( strcmp ( pw-> pw_passwd, "*" ) == 0 )) {
186 struct spwd *sp = getspnam ( pw-> pw_name );
187
188 if ( !sp )
189 error_msg_and_die ( "no valid shadow password" );
190
191 correct = sp-> sp_pwdp;
192 }
193 else
194#endif
195 correct = pw-> pw_passwd;
196
197 if ( correct == 0 || correct[0] == '\0' )
198 return 1;
199
200 unencrypted = getpass ( "Password: " );
201 if ( !unencrypted )
202 {
203 fputs ( "getpass: cannot open /dev/tty\n", stderr );
204 return 0;
205 }
206 encrypted = crypt ( unencrypted, correct );
207 memset ( unencrypted, 0, xstrlen ( unencrypted ));
208 return ( strcmp ( encrypted, correct ) == 0 ) ? 1 : 0;
209}
diff --git a/loginutils/Makefile.in b/loginutils/Makefile.in
index adee35baa..cb6452c39 100644
--- a/loginutils/Makefile.in
+++ b/loginutils/Makefile.in
@@ -26,9 +26,12 @@ LOGINUTILS-y:=
26LOGINUTILS-$(CONFIG_ADDGROUP) += addgroup.o 26LOGINUTILS-$(CONFIG_ADDGROUP) += addgroup.o
27LOGINUTILS-$(CONFIG_ADDUSER) += adduser.o 27LOGINUTILS-$(CONFIG_ADDUSER) += adduser.o
28LOGINUTILS-$(CONFIG_DELUSER) += deluser.o 28LOGINUTILS-$(CONFIG_DELUSER) += deluser.o
29LOGINUTILS-$(CONFIG_GETTY) += getty.o 29LOGINUTILS-$(CONFIG_GETTY) += getty.o
30LOGINUTILS-$(CONFIG_LOGIN) += login.o tinylogin.o 30LOGINUTILS-$(CONFIG_LOGIN) += login.o
31LOGINUTILS-$(CONFIG_SU) += su.o tinylogin.o 31LOGINUTILS-$(CONFIG_PASSWD) += passwd.o
32LOGINUTILS-$(CONFIG_SU) += su.o
33LOGINUTILS-$(CONFIG_SULOGIN) += sulogin.o
34LOGINUTILS-$(CONFIG_VLOCK) += vlock.o
32 35
33libraries-y+=$(LOGINUTILS_DIR)$(LOGINUTILS_AR) 36libraries-y+=$(LOGINUTILS_DIR)$(LOGINUTILS_AR)
34 37
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c
index e04a8d784..87e98fb18 100644
--- a/loginutils/addgroup.c
+++ b/loginutils/addgroup.c
@@ -35,9 +35,6 @@
35#include "pwd.h" 35#include "pwd.h"
36#include "grp.h" 36#include "grp.h"
37 37
38#define GROUP_FILE "/etc/group"
39#define SHADOW_FILE "/etc/gshadow"
40
41 38
42/* structs __________________________ */ 39/* structs __________________________ */
43 40
@@ -92,7 +89,7 @@ static int addgroup(const char *filename, char *group, gid_t gid)
92 89
93#ifdef CONFIG_FEATURE_SHADOWPASSWDS 90#ifdef CONFIG_FEATURE_SHADOWPASSWDS
94 FILE *etc_gshadow; 91 FILE *etc_gshadow;
95 char *gshadow = SHADOW_FILE; 92 char *gshadow = shadow_file;
96#endif 93#endif
97 94
98 struct group gr; 95 struct group gr;
@@ -162,7 +159,7 @@ int addgroup_main(int argc, char **argv)
162 } 159 }
163 160
164 /* werk */ 161 /* werk */
165 return addgroup(GROUP_FILE, group, gid); 162 return addgroup(group_file, group, gid);
166} 163}
167 164
168/* $Id: addgroup.c,v 1.1 2002/06/04 20:45:05 sandman Exp $ */ 165/* $Id: addgroup.c,v 1.2 2002/06/23 04:24:24 andersen Exp $ */
diff --git a/loginutils/adduser.c b/loginutils/adduser.c
index 66fcaa23f..7aa7fcfd3 100644
--- a/loginutils/adduser.c
+++ b/loginutils/adduser.c
@@ -33,11 +33,7 @@
33#include <sys/stat.h> 33#include <sys/stat.h>
34#include <sys/types.h> 34#include <sys/types.h>
35#include "busybox.h" 35#include "busybox.h"
36#include "pwd.h"
37#include "grp.h"
38 36
39#define PASSWD_FILE "/etc/passwd"
40#define SHADOW_FILE "/etc/shadow"
41 37
42 38
43/* structs __________________________ */ 39/* structs __________________________ */
@@ -56,9 +52,6 @@ static const char default_home_prefix[] = "/home";
56static const char default_shell[] = "/bin/sh"; 52static const char default_shell[] = "/bin/sh";
57 53
58#ifdef CONFIG_FEATURE_SHADOWPASSWDS 54#ifdef CONFIG_FEATURE_SHADOWPASSWDS
59
60#include "shadow.h"
61
62/* shadow in use? */ 55/* shadow in use? */
63static int shadow_enabled = 0; 56static int shadow_enabled = 0;
64#endif 57#endif
@@ -138,47 +131,6 @@ static void passwd_wrapper(const char *login)
138 error_msg_and_die("Failed to execute 'passwd', you must set the password for '%s' manually", login); 131 error_msg_and_die("Failed to execute 'passwd', you must set the password for '%s' manually", login);
139} 132}
140 133
141#ifdef CONFIG_FEATURE_SHADOWPASSWDS
142/*
143 * pwd_to_spwd - create entries for new spwd structure
144 *
145 * pwd_to_spwd() creates a new (struct spwd) containing the
146 * information in the pointed-to (struct passwd).
147 */
148#define DAY (24L*3600L)
149#define WEEK (7*DAY)
150#define SCALE DAY
151static struct spwd *pwd_to_spwd(const struct passwd *pw)
152{
153 static struct spwd sp;
154
155 /*
156 * Nice, easy parts first. The name and passwd map directly
157 * from the old password structure to the new one.
158 */
159 sp.sp_namp = pw->pw_name;
160 sp.sp_pwdp = pw->pw_passwd;
161
162 /*
163 * Defaults used if there is no pw_age information.
164 */
165 sp.sp_min = 0;
166 sp.sp_max = (10000L * DAY) / SCALE;
167 sp.sp_lstchg = time((time_t *) 0) / SCALE;
168
169 /*
170 * These fields have no corresponding information in the password
171 * file. They are set to uninitialized values.
172 */
173 sp.sp_warn = -1;
174 sp.sp_expire = -1;
175 sp.sp_inact = -1;
176 sp.sp_flag = -1;
177
178 return &sp;
179}
180#endif
181
182/* putpwent(3) remix */ 134/* putpwent(3) remix */
183static int adduser(const char *filename, struct passwd *p) 135static int adduser(const char *filename, struct passwd *p)
184{ 136{
@@ -222,7 +174,7 @@ static int adduser(const char *filename, struct passwd *p)
222#ifdef CONFIG_FEATURE_SHADOWPASSWDS 174#ifdef CONFIG_FEATURE_SHADOWPASSWDS
223 /* add to shadow if necessary */ 175 /* add to shadow if necessary */
224 if (shadow_enabled) { 176 if (shadow_enabled) {
225 shadow = wfopen(SHADOW_FILE, "a"); 177 shadow = wfopen(shadow_file, "a");
226 if (shadow == NULL) { 178 if (shadow == NULL) {
227 /* return -1; */ 179 /* return -1; */
228 return 1; 180 return 1;
@@ -333,7 +285,7 @@ int adduser_main(int argc, char **argv)
333 } 285 }
334#ifdef CONFIG_FEATURE_SHADOWPASSWDS 286#ifdef CONFIG_FEATURE_SHADOWPASSWDS
335 /* is /etc/shadow in use? */ 287 /* is /etc/shadow in use? */
336 shadow_enabled = (0 == access(SHADOW_FILE, F_OK)); 288 shadow_enabled = (0 == access(shadow_file, F_OK));
337#endif 289#endif
338 290
339 /* create a passwd struct */ 291 /* create a passwd struct */
@@ -346,7 +298,7 @@ int adduser_main(int argc, char **argv)
346 pw.pw_shell = (char *)shell; 298 pw.pw_shell = (char *)shell;
347 299
348 /* grand finale */ 300 /* grand finale */
349 return adduser(PASSWD_FILE, &pw); 301 return adduser(passwd_file, &pw);
350} 302}
351 303
352/* $Id: adduser.c,v 1.1 2002/06/04 20:45:05 sandman Exp $ */ 304/* $Id: adduser.c,v 1.2 2002/06/23 04:24:24 andersen Exp $ */
diff --git a/loginutils/config.in b/loginutils/config.in
index 265d45ab4..b3880aa3d 100644
--- a/loginutils/config.in
+++ b/loginutils/config.in
@@ -7,19 +7,22 @@ mainmenu_option next_comment
7comment 'Login/Password Management Utilities' 7comment 'Login/Password Management Utilities'
8 8
9 9
10bool 'addgroup' CONFIG_ADDGROUP 10bool 'addgroup' CONFIG_ADDGROUP
11bool 'adduser' CONFIG_ADDUSER 11bool 'adduser' CONFIG_ADDUSER
12bool 'deluser' CONFIG_DELUSER 12bool 'deluser' CONFIG_DELUSER
13bool 'delgroup' CONFIG_DELUSER 13bool 'delgroup' CONFIG_DELUSER
14bool 'getty' CONFIG_GETTY 14bool 'getty' CONFIG_GETTY
15bool 'login' CONFIG_LOGIN 15bool 'login' CONFIG_LOGIN
16if [ "$CONFIG_LOGIN" = "y" ]; then 16if [ "$CONFIG_LOGIN" = "y" ]; then
17 bool ' Support for /etc/securetty' CONFIG_FEATURE_SECURETTY 17 bool ' Support for /etc/securetty' CONFIG_FEATURE_SECURETTY
18fi 18fi
19bool 'su' CONFIG_SU 19bool 'passwd' CONFIG_PASSWD
20bool 'su' CONFIG_SU
20if [ "$CONFIG_ADDUSER" = "y" -o "$CONFIG_DELUSER" = "y" -o "$CONFIG_LOGIN" = "y" -o "$CONFIG_SU" = "y" ]; then 21if [ "$CONFIG_ADDUSER" = "y" -o "$CONFIG_DELUSER" = "y" -o "$CONFIG_LOGIN" = "y" -o "$CONFIG_SU" = "y" ]; then
21 bool 'Support for shadow passwords' CONFIG_FEATURE_SHADOWPASSWDS 22 bool ' Support for shadow passwords' CONFIG_FEATURE_SHADOWPASSWDS
22fi 23fi
24bool 'sulogin' CONFIG_SULOGIN
25bool 'vlock' CONFIG_VLOCK
23 26
24endmenu 27endmenu
25 28
diff --git a/loginutils/deluser.c b/loginutils/deluser.c
index 481a716e7..c7d6ece64 100644
--- a/loginutils/deluser.c
+++ b/loginutils/deluser.c
@@ -28,10 +28,6 @@
28#include <string.h> 28#include <string.h>
29#include "busybox.h" 29#include "busybox.h"
30 30
31#define PASSWD_FILE "/etc/passwd"
32#define GROUP_FILE "/etc/group"
33#define SHADOW_FILE "/etc/shadow"
34#define GSHADOW_FILE "/etc/gshadow"
35 31
36 32
37/* where to start and stop deletion */ 33/* where to start and stop deletion */
@@ -123,11 +119,11 @@ int delgroup_main(int argc, char **argv)
123 show_usage(); 119 show_usage();
124 } else { 120 } else {
125 121
126 failure = del_line_matching(argv[1], GROUP_FILE); 122 failure = del_line_matching(argv[1], group_file);
127#ifdef CONFIG_FEATURE_SHADOWPASSWDS 123#ifdef CONFIG_FEATURE_SHADOWPASSWDS
128 if (access(GSHADOW_FILE, W_OK) == 0) { 124 if (access(gshadow_file, W_OK) == 0) {
129 /* EDR the |= works if the error is not 0, so he had it wrong */ 125 /* EDR the |= works if the error is not 0, so he had it wrong */
130 failure |= del_line_matching(argv[1], GSHADOW_FILE); 126 failure |= del_line_matching(argv[1], gshadow_file);
131 } 127 }
132#endif /* CONFIG_FEATURE_SHADOWPASSWDS */ 128#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
133 /* if (!successful) { */ 129 /* if (!successful) { */
@@ -149,35 +145,35 @@ int deluser_main(int argc, char **argv)
149 show_usage(); 145 show_usage();
150 } else { 146 } else {
151 147
152 failure = del_line_matching(argv[1], PASSWD_FILE); 148 failure = del_line_matching(argv[1], passwd_file);
153 /* if (!successful) { */ 149 /* if (!successful) { */
154 if (failure) { 150 if (failure) {
155 error_msg_and_die("%s: User could not be removed from %s\n", 151 error_msg_and_die("%s: User could not be removed from %s\n",
156 argv[1], PASSWD_FILE); 152 argv[1], passwd_file);
157 } 153 }
158#ifdef CONFIG_FEATURE_SHADOWPASSWDS 154#ifdef CONFIG_FEATURE_SHADOWPASSWDS
159 failure = del_line_matching(argv[1], SHADOW_FILE); 155 failure = del_line_matching(argv[1], shadow_file);
160 /* if (!successful) { */ 156 /* if (!successful) { */
161 if (failure) { 157 if (failure) {
162 error_msg_and_die("%s: User could not be removed from %s\n", 158 error_msg_and_die("%s: User could not be removed from %s\n",
163 argv[1], SHADOW_FILE); 159 argv[1], shadow_file);
164 } 160 }
165 failure = del_line_matching(argv[1], GSHADOW_FILE); 161 failure = del_line_matching(argv[1], gshadow_file);
166 /* if (!successful) { */ 162 /* if (!successful) { */
167 if (failure) { 163 if (failure) {
168 error_msg_and_die("%s: User could not be removed from %s\n", 164 error_msg_and_die("%s: User could not be removed from %s\n",
169 argv[1], GSHADOW_FILE); 165 argv[1], gshadow_file);
170 } 166 }
171#endif /* CONFIG_FEATURE_SHADOWPASSWDS */ 167#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
172 failure = del_line_matching(argv[1], GROUP_FILE); 168 failure = del_line_matching(argv[1], group_file);
173 /* if (!successful) { */ 169 /* if (!successful) { */
174 if (failure) { 170 if (failure) {
175 error_msg_and_die("%s: User could not be removed from %s\n", 171 error_msg_and_die("%s: User could not be removed from %s\n",
176 argv[1], GROUP_FILE); 172 argv[1], group_file);
177 } 173 }
178 174
179 } 175 }
180 return (EXIT_SUCCESS); 176 return (EXIT_SUCCESS);
181} 177}
182 178
183/* $Id: deluser.c,v 1.1 2002/06/04 20:45:05 sandman Exp $ */ 179/* $Id: deluser.c,v 1.2 2002/06/23 04:24:24 andersen Exp $ */
diff --git a/loginutils/login.c b/loginutils/login.c
index 8ccc5bc8a..7687556ba 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -14,16 +14,9 @@
14#include <sys/types.h> 14#include <sys/types.h>
15#include <ctype.h> 15#include <ctype.h>
16#include <time.h> 16#include <time.h>
17#include "busybox.h"
18
19#include "pwd.h"
20#include "grp.h"
21 17
22#ifdef CONFIG_FEATURE_SHADOWPASSWDS 18#include "busybox.h"
23#include "shadow.h"
24#endif
25 19
26#include "tinylogin.h"
27 20
28// import from utmp.c 21// import from utmp.c
29static void checkutmp(int picky); 22static void checkutmp(int picky);
@@ -35,12 +28,7 @@ extern char *pw_encrypt(const char *clear, const char *salt);
35 28
36// login defines 29// login defines
37#define TIMEOUT 60 30#define TIMEOUT 60
38#define FAIL_DELAY 3
39#define EMPTY_USERNAME_COUNT 10 31#define EMPTY_USERNAME_COUNT 10
40#define MOTD_FILE "/etc/motd"
41#define NOLOGIN_FILE "/etc/nologin"
42#define SECURETTY_FILE "/etc/securetty"
43
44#define USERNAME_SIZE 32 32#define USERNAME_SIZE 32
45 33
46/* Stuff global to this file */ 34/* Stuff global to this file */
@@ -81,7 +69,9 @@ extern int login_main(int argc, char **argv)
81 int failed; 69 int failed;
82 int count=0; 70 int count=0;
83 struct passwd *pw, pw_copy; 71 struct passwd *pw, pw_copy;
84 72#ifdef CONFIG_WHEEL_GROUP
73 struct group *grp;
74#endif
85 int opt_preserve = 0; 75 int opt_preserve = 0;
86 int opt_fflag = 0; 76 int opt_fflag = 0;
87 char *opt_host = 0; 77 char *opt_host = 0;
@@ -283,11 +273,11 @@ static int login_prompt ( char *buf_name )
283 273
284static int check_nologin ( int amroot ) 274static int check_nologin ( int amroot )
285{ 275{
286 if ( access ( NOLOGIN_FILE, F_OK ) == 0 ) { 276 if ( access ( nologin_file, F_OK ) == 0 ) {
287 FILE *fp; 277 FILE *fp;
288 int c; 278 int c;
289 279
290 if (( fp = fopen ( NOLOGIN_FILE, "r" ))) { 280 if (( fp = fopen ( nologin_file, "r" ))) {
291 while (( c = getc ( fp )) != EOF ) 281 while (( c = getc ( fp )) != EOF )
292 putchar (( c == '\n' ) ? '\r' : c ); 282 putchar (( c == '\n' ) ? '\r' : c );
293 283
@@ -312,7 +302,7 @@ static int check_tty ( const char *tty )
312 int i; 302 int i;
313 char buf[BUFSIZ]; 303 char buf[BUFSIZ];
314 304
315 if (( fp = fopen ( SECURETTY_FILE, "r" ))) { 305 if (( fp = fopen ( securetty_file, "r" ))) {
316 while ( fgets ( buf, sizeof( buf ) - 1, fp )) { 306 while ( fgets ( buf, sizeof( buf ) - 1, fp )) {
317 for ( i = xstrlen( buf ) - 1; i >= 0; --i ) { 307 for ( i = xstrlen( buf ) - 1; i >= 0; --i ) {
318 if ( !isspace ( buf[i] )) 308 if ( !isspace ( buf[i] ))
@@ -358,7 +348,7 @@ static void motd ( )
358 FILE *fp; 348 FILE *fp;
359 register int c; 349 register int c;
360 350
361 if (( fp = fopen ( MOTD_FILE, "r" ))) { 351 if (( fp = fopen ( motd_file, "r" ))) {
362 while (( c = getc ( fp )) != EOF ) 352 while (( c = getc ( fp )) != EOF )
363 putchar ( c ); 353 putchar ( c );
364 fclose ( fp ); 354 fclose ( fp );
@@ -429,23 +419,6 @@ static void checkutmp(int picky)
429 } 419 }
430} 420}
431 421
432#if __GNU_LIBRARY__ < 5
433/*
434 * Some systems already have updwtmp() and possibly updwtmpx(). Others
435 * don't, so we re-implement these functions if necessary. --marekm
436 */
437static void updwtmp(const char *filename, const struct utmp *ut)
438{
439 int fd;
440
441 fd = open(filename, O_APPEND | O_WRONLY, 0);
442 if (fd >= 0) {
443 write(fd, (const char *) ut, sizeof(*ut));
444 close(fd);
445 }
446}
447#endif
448
449/* 422/*
450 * setutmp - put a USER_PROCESS entry in the utmp file 423 * setutmp - put a USER_PROCESS entry in the utmp file
451 * 424 *
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
new file mode 100644
index 000000000..9c84c167c
--- /dev/null
+++ b/loginutils/passwd.c
@@ -0,0 +1,408 @@
1/* vi: set sw=4 ts=4: */
2#include <fcntl.h>
3#include <stdio.h>
4#include <string.h>
5#include <signal.h>
6#include <sys/stat.h>
7#include <sys/types.h>
8#include <unistd.h>
9#include <utime.h>
10#include <syslog.h>
11#include <time.h>
12#include <sys/resource.h>
13#include <errno.h>
14
15#include "busybox.h"
16
17static char crypt_passwd[128];
18
19static int create_backup(const char *backup, FILE * fp);
20static int new_password(const struct passwd *pw, int amroot, int algo);
21static void set_filesize_limit(int blocks);
22
23
24int get_algo(char *a)
25{
26 int x = 0; /* standart: DES */
27
28 if (strcasecmp(a, "md5") == 0)
29 x = 1;
30 return x;
31}
32
33
34extern int update_passwd(const struct passwd *pw, char *crypt_pw)
35{
36 char filename[1024];
37 char buf[1025];
38 char buffer[80];
39 char username[32];
40 char *pw_rest;
41 int has_shadow = 0;
42 int mask;
43 int continued;
44 FILE *fp;
45 FILE *out_fp;
46 struct stat sb;
47 struct flock lock;
48
49 if (access(shadow_file, F_OK) == 0) {
50 has_shadow = 1;
51 }
52 if (has_shadow) {
53 snprintf(filename, sizeof filename, "%s", shadow_file);
54 } else {
55 snprintf(filename, sizeof filename, "%s", passwd_file);
56 }
57
58 if (((fp = fopen(filename, "r+")) == 0) || (fstat(fileno(fp), &sb))) {
59 /* return 0; */
60 return 1;
61 }
62
63 /* Lock the password file before updating */
64 lock.l_type = F_WRLCK;
65 lock.l_whence = SEEK_SET;
66 lock.l_start = 0;
67 lock.l_len = 0;
68 if (fcntl(fileno(fp), F_SETLK, &lock) < 0) {
69 fprintf(stderr, "%s: %s\n", filename, strerror(errno));
70 return 1;
71 }
72 lock.l_type = F_UNLCK;
73
74 snprintf(buf, sizeof buf, "%s-", filename);
75 if (create_backup(buf, fp)) {
76 fcntl(fileno(fp), F_SETLK, &lock);
77 fclose(fp);
78 return 1;
79 }
80 snprintf(buf, sizeof buf, "%s+", filename);
81 mask = umask(0777);
82 out_fp = fopen(buf, "w");
83 umask(mask);
84 if ((!out_fp) || (fchmod(fileno(out_fp), sb.st_mode & 0777))
85 || (fchown(fileno(out_fp), sb.st_uid, sb.st_gid))) {
86 fcntl(fileno(fp), F_SETLK, &lock);
87 fclose(fp);
88 fclose(out_fp);
89 return 1;
90 }
91
92 continued = 0;
93 snprintf(username, sizeof username, "%s:", pw->pw_name);
94 rewind(fp);
95 while (!feof(fp)) {
96 fgets(buffer, sizeof buffer, fp);
97 if (!continued) { // Check to see if we're updating this line.
98 if (strncmp(username, buffer, strlen(username)) == 0) { // we have a match.
99 pw_rest = strchr(buffer, ':');
100 *pw_rest++ = '\0';
101 pw_rest = strchr(pw_rest, ':');
102 fprintf(out_fp, "%s:%s%s", buffer, crypt_pw, pw_rest);
103 } else {
104 fputs(buffer, out_fp);
105 }
106 } else {
107 fputs(buffer, out_fp);
108 }
109 if (buffer[strlen(buffer) - 1] == '\n') {
110 continued = 0;
111 } else {
112 continued = 1;
113 }
114 bzero(buffer, sizeof buffer);
115 }
116
117 if (fflush(out_fp) || fsync(fileno(out_fp)) || fclose(out_fp)) {
118 unlink(buf);
119 fcntl(fileno(fp), F_SETLK, &lock);
120 fclose(fp);
121 return 1;
122 }
123 if (rename(buf, filename) < 0) {
124 fcntl(fileno(fp), F_SETLK, &lock);
125 fclose(fp);
126 return 1;
127 } else {
128 fcntl(fileno(fp), F_SETLK, &lock);
129 fclose(fp);
130 return 0;
131 }
132}
133
134
135extern int passwd_main(int argc, char **argv)
136{
137 int amroot;
138 char *cp;
139 char *np;
140 char *name;
141 char *myname;
142 int flag;
143 int algo = 0; /* -a - password algorithm */
144 int lflg = 0; /* -l - lock account */
145 int uflg = 0; /* -u - unlock account */
146 int dflg = 0; /* -d - delete password */
147 const struct passwd *pw;
148 unsigned short ruid;
149
150#ifdef CONFIG_FEATURE_SHADOWPASSWDS
151 const struct spwd *sp;
152#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
153 amroot = (getuid() == 0);
154 openlog("passwd", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
155 while ((flag = getopt(argc, argv, "a:dlu")) != EOF) {
156 switch (flag) {
157 case 'a':
158 algo = get_algo(optarg);
159 break;
160 case 'd':
161 dflg++;
162 break;
163 case 'l':
164 lflg++;
165 break;
166 case 'u':
167 uflg++;
168 break;
169 default:
170 show_usage();
171 }
172 }
173 ruid = getuid();
174 pw = (struct passwd *) getpwuid(ruid);
175 if (!pw) {
176 error_msg_and_die("Cannot determine your user name.\n");
177 }
178 myname = (char *) xstrdup(pw->pw_name);
179 if (optind < argc) {
180 name = argv[optind];
181 } else {
182 name = myname;
183 }
184 if ((lflg || uflg || dflg) && (optind >= argc || !amroot)) {
185 show_usage();
186 }
187 pw = getpwnam(name);
188 if (!pw) {
189 error_msg_and_die("Unknown user %s\n", name);
190 }
191 if (!amroot && pw->pw_uid != getuid()) {
192 syslog(LOG_WARNING, "can't change pwd for `%s'", name);
193 error_msg_and_die("Permission denied.\n");
194 }
195#ifdef CONFIG_FEATURE_SHADOWPASSWDS
196 sp = getspnam(name);
197 if (!sp) {
198 sp = (struct spwd *) pwd_to_spwd(pw);
199 }
200 cp = sp->sp_pwdp;
201 np = sp->sp_namp;
202#else
203 cp = pw->pw_passwd;
204 np = name;
205#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
206
207 safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
208 if (!(dflg || lflg || uflg)) {
209 if (!amroot) {
210 if (cp[0] == '!') {
211 syslog(LOG_WARNING, "password locked for `%s'", np);
212 error_msg_and_die( "The password for `%s' cannot be changed.\n", np);
213 }
214 }
215 printf("Changing password for %s\n", name);
216 if (new_password(pw, amroot, algo)) {
217 error_msg_and_die( "The password for %s is unchanged.\n", name);
218 }
219 } else if (lflg) {
220 if (crypt_passwd[0] != '!') {
221 memmove(&crypt_passwd[1], crypt_passwd,
222 sizeof crypt_passwd - 1);
223 crypt_passwd[sizeof crypt_passwd - 1] = '\0';
224 crypt_passwd[0] = '!';
225 }
226 } else if (uflg) {
227 if (crypt_passwd[0] == '!') {
228 memmove(crypt_passwd, &crypt_passwd[1],
229 sizeof crypt_passwd - 1);
230 }
231 } else if (dflg) {
232 crypt_passwd[0] = '\0';
233 }
234 set_filesize_limit(30000);
235 signal(SIGHUP, SIG_IGN);
236 signal(SIGINT, SIG_IGN);
237 signal(SIGQUIT, SIG_IGN);
238 umask(077);
239 if (setuid(0)) {
240 syslog(LOG_ERR, "can't setuid(0)");
241 error_msg_and_die( "Cannot change ID to root.\n");
242 }
243 if (!update_passwd(pw, crypt_passwd)) {
244 syslog(LOG_INFO, "password for `%s' changed by user `%s'", name,
245 myname);
246 printf("Password changed.\n");
247 } else {
248 syslog(LOG_WARNING,
249 "an error occurred updating the password file");
250 error_msg_and_die("An error occurred updating the password file.\n");
251 }
252 return (0);
253}
254
255
256
257static int create_backup(const char *backup, FILE * fp)
258{
259 struct stat sb;
260 struct utimbuf ub;
261 FILE *bkfp;
262 int c, mask;
263
264 if (fstat(fileno(fp), &sb))
265 /* return -1; */
266 return 1;
267
268 mask = umask(077);
269 bkfp = fopen(backup, "w");
270 umask(mask);
271 if (!bkfp)
272 /* return -1; */
273 return 1;
274
275 /* TODO: faster copy, not one-char-at-a-time. --marekm */
276 rewind(fp);
277 while ((c = getc(fp)) != EOF) {
278 if (putc(c, bkfp) == EOF)
279 break;
280 }
281 if (c != EOF || fflush(bkfp)) {
282 fclose(bkfp);
283 /* return -1; */
284 return 1;
285 }
286 if (fclose(bkfp))
287 /* return -1; */
288 return 1;
289
290 ub.actime = sb.st_atime;
291 ub.modtime = sb.st_mtime;
292 utime(backup, &ub);
293 return 0;
294}
295
296static int i64c(int i)
297{
298 if (i <= 0)
299 return ('.');
300 if (i == 1)
301 return ('/');
302 if (i >= 2 && i < 12)
303 return ('0' - 2 + i);
304 if (i >= 12 && i < 38)
305 return ('A' - 12 + i);
306 if (i >= 38 && i < 63)
307 return ('a' - 38 + i);
308 return ('z');
309}
310
311static char *crypt_make_salt(void)
312{
313 time_t now;
314 static unsigned long x;
315 static char result[3];
316
317 time(&now);
318 x += now + getpid() + clock();
319 result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
320 result[1] = i64c(((x >> 12) ^ x) & 077);
321 result[2] = '\0';
322 return result;
323}
324
325
326static int new_password(const struct passwd *pw, int amroot, int algo)
327{
328 char *clear;
329 char *cipher;
330 char *cp;
331 char orig[200];
332 char pass[200];
333 time_t start, now;
334
335 if (!amroot && crypt_passwd[0]) {
336 if (!(clear = getpass("Old password:"))) {
337 /* return -1; */
338 return 1;
339 }
340 cipher = pw_encrypt(clear, crypt_passwd);
341 if (strcmp(cipher, crypt_passwd) != 0) {
342 syslog(LOG_WARNING, "incorrect password for `%s'",
343 pw->pw_name);
344 time(&start);
345 now = start;
346 while (difftime(now, start) < FAIL_DELAY) {
347 sleep(FAIL_DELAY);
348 time(&now);
349 }
350 fprintf(stderr, "Incorrect password.\n");
351 /* return -1; */
352 return 1;
353 }
354 safe_strncpy(orig, clear, sizeof(orig));
355 bzero(clear, strlen(clear));
356 bzero(cipher, strlen(cipher));
357 } else {
358 orig[0] = '\0';
359 }
360 if (!
361 (cp =
362 getpass ("Enter the new password (minimum of 5, maximum of 8 characters)\n""
363 Please use a combination of upper and lower case letters and numbers.\nEnter new password: ")))
364 {
365 bzero(orig, sizeof orig);
366 /* return -1; */
367 return 1;
368 }
369 safe_strncpy(pass, cp, sizeof(pass));
370 bzero(cp, strlen(cp));
371 /* if (!obscure(orig, pass, pw)) { */
372 if (obscure(orig, pass, pw)) {
373 if (amroot) {
374 printf("\nWarning: weak password (continuing).\n");
375 } else {
376 /* return -1; */
377 return 1;
378 }
379 }
380 if (!(cp = getpass("Re-enter new password: "))) {
381 bzero(orig, sizeof orig);
382 /* return -1; */
383 return 1;
384 }
385 if (strcmp(cp, pass)) {
386 fprintf(stderr, "Passwords do not match.\n");
387 /* return -1; */
388 return 1;
389 }
390 bzero(cp, strlen(cp));
391 bzero(orig, sizeof(orig));
392
393 if (algo == 1) {
394 cp = pw_encrypt(pass, "$1$");
395 } else
396 cp = pw_encrypt(pass, crypt_make_salt());
397 bzero(pass, sizeof pass);
398 safe_strncpy(crypt_passwd, cp, sizeof(crypt_passwd));
399 return 0;
400}
401
402static void set_filesize_limit(int blocks)
403{
404 struct rlimit rlimit_fsize;
405
406 rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks;
407 setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
408}
diff --git a/loginutils/su.c b/loginutils/su.c
index 33e62e837..6d427262e 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -1,7 +1,5 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2 2
3#include "busybox.h"
4
5#include <fcntl.h> 3#include <fcntl.h>
6#include <signal.h> 4#include <signal.h>
7#include <stdio.h> 5#include <stdio.h>
@@ -18,10 +16,7 @@
18#include <ctype.h> 16#include <ctype.h>
19#include <time.h> 17#include <time.h>
20 18
21#include "pwd.h" 19#include "busybox.h"
22#include "grp.h"
23
24#include "tinylogin.h"
25 20
26 21
27 22
@@ -161,7 +156,7 @@ int su_main ( int argc, char **argv )
161 156
162 change_identity ( pw ); 157 change_identity ( pw );
163 setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw ); 158 setup_environment ( opt_shell, opt_loginshell, !opt_preserve, pw );
164 run_shell ( opt_shell, opt_loginshell, opt_command, opt_args ); 159 run_shell ( opt_shell, opt_loginshell, opt_command, (const char**)opt_args );
165 160
166 return EXIT_FAILURE; 161 return EXIT_FAILURE;
167} 162}
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
new file mode 100644
index 000000000..a654ffb89
--- /dev/null
+++ b/loginutils/sulogin.c
@@ -0,0 +1,184 @@
1/* vi: set sw=4 ts=4: */
2#include <fcntl.h>
3#include <signal.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <syslog.h>
8#include <termios.h>
9#include <unistd.h>
10#include <utmp.h>
11#include <sys/resource.h>
12#include <sys/stat.h>
13#include <sys/time.h>
14#include <sys/types.h>
15#include <ctype.h>
16#include <time.h>
17
18#include "busybox.h"
19
20
21// sulogin defines
22#define SULOGIN_PROMPT "\nGive root password for system maintenance\n" \
23 "(or type Control-D for normal startup):"
24
25static const char *forbid[] = {
26 "ENV",
27 "BASH_ENV",
28 "HOME",
29 "IFS",
30 "PATH",
31 "SHELL",
32 "LD_LIBRARY_PATH",
33 "LD_PRELOAD",
34 "LD_TRACE_LOADED_OBJECTS",
35 "LD_BIND_NOW",
36 "LD_AOUT_LIBRARY_PATH",
37 "LD_AOUT_PRELOAD",
38 "LD_NOWARN",
39 "LD_KEEPDIR",
40 (char *) 0
41};
42
43
44
45static void catchalarm(int junk)
46{
47 exit(EXIT_FAILURE);
48}
49
50
51extern int sulogin_main(int argc, char **argv)
52{
53 char *cp;
54 char *device = (char *) 0;
55 const char *name = "root";
56 int timeout = 0;
57 static char pass[BUFSIZ];
58 struct termios termio;
59 struct passwd pwent;
60 struct passwd *pwd;
61 time_t start, now;
62 const char **p;
63#ifdef CONFIG_FEATURE_SHADOWPASSWDS
64 struct spwd *spwd = NULL;
65#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
66
67 tcgetattr(0, &termio);
68 /* set control chars */
69 termio.c_cc[VINTR] = 3; /* C-c */
70 termio.c_cc[VQUIT] = 28; /* C-\ */
71 termio.c_cc[VERASE] = 127; /* C-? */
72 termio.c_cc[VKILL] = 21; /* C-u */
73 termio.c_cc[VEOF] = 4; /* C-d */
74 termio.c_cc[VSTART] = 17; /* C-q */
75 termio.c_cc[VSTOP] = 19; /* C-s */
76 termio.c_cc[VSUSP] = 26; /* C-z */
77 /* use line dicipline 0 */
78 termio.c_line = 0;
79 /* Make it be sane */
80 termio.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
81 termio.c_cflag |= CREAD|HUPCL|CLOCAL;
82 /* input modes */
83 termio.c_iflag = ICRNL | IXON | IXOFF;
84 /* output modes */
85 termio.c_oflag = OPOST | ONLCR;
86 /* local modes */
87 termio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
88 tcsetattr(0, TCSANOW, &termio);
89 openlog("sulogin", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
90 if (argc > 1) {
91 if (strncmp(argv[1], "-t", 2) == 0) {
92 if (strcmp(argv[1], "-t") == 0) {
93 if (argc > 2) {
94 timeout = atoi(argv[2]);
95 if (argc > 3) {
96 device = argv[3];
97 }
98 }
99 } else {
100 if (argc > 2) {
101 device = argv[2];
102 }
103 }
104 } else {
105 device = argv[1];
106 }
107 if (device) {
108 close(0);
109 close(1);
110 close(2);
111 if (open(device, O_RDWR) >= 0) {
112 dup(0);
113 dup(0);
114 } else {
115 syslog(LOG_WARNING, "cannot open %s\n", device);
116 exit(EXIT_FAILURE);
117 }
118 }
119 }
120 if (access(passwd_file, 0) == -1) {
121 syslog(LOG_WARNING, "No password file\n");
122 error_msg_and_die("No password file\n");
123 }
124 if (!isatty(0) || !isatty(1) || !isatty(2)) {
125 exit(EXIT_FAILURE);
126 }
127
128
129 /* Clear out anything dangerous from the environment */
130 for (p = forbid; *p; p++)
131 unsetenv(*p);
132
133
134 signal(SIGALRM, catchalarm);
135 alarm(timeout);
136 if (!(pwd = getpwnam(name))) {
137 syslog(LOG_WARNING, "No password entry for `root'\n");
138 error_msg_and_die("No password entry for `root'\n");
139 }
140 pwent = *pwd;
141#ifdef CONFIG_FEATURE_SHADOWPASSWDS
142 spwd = NULL;
143 if (pwd && ((strcmp(pwd->pw_passwd, "x") == 0)
144 || (strcmp(pwd->pw_passwd, "*") == 0))) {
145 endspent();
146 spwd = getspnam(name);
147 if (spwd) {
148 pwent.pw_passwd = spwd->sp_pwdp;
149 }
150 }
151#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
152 while (1) {
153 cp = getpass(SULOGIN_PROMPT);
154 if (!cp || !*cp) {
155 puts("\n");
156 fflush(stdout);
157 syslog(LOG_INFO, "Normal startup\n");
158 exit(EXIT_SUCCESS);
159 } else {
160 safe_strncpy(pass, cp, sizeof(pass));
161 bzero(cp, strlen(cp));
162 }
163 if (strcmp(pw_encrypt(pass, pwent.pw_passwd), pwent.pw_passwd) == 0) {
164 break;
165 }
166 time(&start);
167 now = start;
168 while (difftime(now, start) < FAIL_DELAY) {
169 sleep(FAIL_DELAY);
170 time(&now);
171 }
172 puts("Login incorrect");
173 fflush(stdout);
174 syslog(LOG_WARNING, "Incorrect root password\n");
175 }
176 bzero(pass, strlen(pass));
177 alarm(0);
178 signal(SIGALRM, SIG_DFL);
179 puts("Entering System Maintenance Mode\n");
180 fflush(stdout);
181 syslog(LOG_INFO, "System Maintenance Mode\n");
182 run_shell(pwent.pw_shell, 1, 0, 0);
183 return (0);
184}
diff --git a/loginutils/tinylogin.h b/loginutils/tinylogin.h
deleted file mode 100644
index 5e56a2c7f..000000000
--- a/loginutils/tinylogin.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef BB_LOGINUTILS_SHELL_H
2#define BB_LOGINUTILS_SHELL_H
3
4extern void change_identity ( const struct passwd *pw );
5extern void run_shell ( const char *shell, int loginshell, const char *command, char **additional_args );
6extern int restricted_shell ( const char *shell );
7extern void setup_environment ( const char *shell, int loginshell, int changeenv, const struct passwd *pw );
8extern int correct_password ( const struct passwd *pw );
9
10#endif
diff --git a/loginutils/vlock.c b/loginutils/vlock.c
new file mode 100644
index 000000000..a26999f89
--- /dev/null
+++ b/loginutils/vlock.c
@@ -0,0 +1,229 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * vlock implementation for busybox
4 *
5 * Copyright (C) 2000 by spoon <spoon@ix.netcom.com>
6 * Written by spoon <spon@ix.netcom.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24/* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the
25 * original vlock. I snagged a bunch of his code to write this
26 * minimalistic vlock.
27 */
28/* Fixed by Erik Andersen to do passwords the tinylogin way...
29 * It now works with md5, sha1, etc passwords. */
30
31#include <stdio.h>
32#include <sys/vt.h>
33#include <signal.h>
34#include <string.h>
35#include <unistd.h>
36#include <fcntl.h>
37#include <errno.h>
38#include <sys/ioctl.h>
39#include <termios.h>
40
41#include "busybox.h"
42
43static struct passwd *pw;
44static struct spwd *spw;
45static struct vt_mode ovtm;
46static struct termios oterm;
47static int vfd;
48static int o_lock_all = 0;
49
50/* getspuid - get a shadow entry by uid */
51struct spwd *getspuid(uid_t uid)
52{
53 struct spwd *sp;
54 struct passwd *mypw;
55
56 if ((mypw = getpwuid(getuid())) == NULL) {
57 return (NULL);
58 }
59 setspent();
60 while ((sp = getspent()) != NULL) {
61 if (strcmp(mypw->pw_name, sp->sp_namp) == 0)
62 break;
63 }
64 endspent();
65 return (sp);
66}
67
68static void release_vt(int signo)
69{
70 if (!o_lock_all)
71 ioctl(vfd, VT_RELDISP, 1);
72 else
73 ioctl(vfd, VT_RELDISP, 0);
74}
75
76static void acquire_vt(int signo)
77{
78 ioctl(vfd, VT_RELDISP, VT_ACKACQ);
79}
80
81static void restore_terminal(void)
82{
83 ioctl(vfd, VT_SETMODE, &ovtm);
84 tcsetattr(STDIN_FILENO, TCSANOW, &oterm);
85}
86
87extern int vlock_main(int argc, char **argv)
88{
89 sigset_t sig;
90 struct sigaction sa;
91 struct vt_mode vtm;
92 int times = 0;
93 struct termios term;
94
95 if (argc > 2) {
96 show_usage();
97 }
98
99 if (argc == 2) {
100 if (strncmp(argv[1], "-a", 2)) {
101 show_usage();
102 } else {
103 o_lock_all = 1;
104 }
105 }
106
107 if ((pw = getpwuid(getuid())) == NULL) {
108 error_msg_and_die("no password for uid %d\n", getuid());
109 }
110#ifdef CONFIG_FEATURE_SHADOWPASSWDS
111 if ((strcmp(pw->pw_passwd, "x") == 0)
112 || (strcmp(pw->pw_passwd, "*") == 0)) {
113
114 if ((spw = getspuid(getuid())) == NULL) {
115 error_msg_and_die("could not read shadow password for uid %d: %s\n",
116 getuid(), strerror(errno));
117 }
118 if (spw->sp_pwdp) {
119 pw->pw_passwd = spw->sp_pwdp;
120 }
121 }
122#endif /* CONFIG_FEATURE_SHADOWPASSWDS */
123 if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*') {
124 error_msg_and_die("Account disabled for uid %d\n", getuid());
125 }
126
127 /* we no longer need root privs */
128 setuid(getuid());
129 setgid(getgid());
130
131 if ((vfd = open("/dev/tty", O_RDWR)) < 0) {
132 error_msg_and_die("/dev/tty");
133 };
134
135 if (ioctl(vfd, VT_GETMODE, &vtm) < 0) {
136 error_msg_and_die("/dev/tty");
137 };
138
139 /* mask a bunch of signals */
140 sigprocmask(SIG_SETMASK, NULL, &sig);
141 sigdelset(&sig, SIGUSR1);
142 sigdelset(&sig, SIGUSR2);
143 sigaddset(&sig, SIGTSTP);
144 sigaddset(&sig, SIGTTIN);
145 sigaddset(&sig, SIGTTOU);
146 sigaddset(&sig, SIGHUP);
147 sigaddset(&sig, SIGCHLD);
148 sigaddset(&sig, SIGQUIT);
149 sigaddset(&sig, SIGINT);
150
151 sigemptyset(&(sa.sa_mask));
152 sa.sa_flags = SA_RESTART;
153 sa.sa_handler = release_vt;
154 sigaction(SIGUSR1, &sa, NULL);
155 sa.sa_handler = acquire_vt;
156 sigaction(SIGUSR2, &sa, NULL);
157
158 /* need to handle some signals so that we don't get killed by them */
159 sa.sa_handler = SIG_IGN;
160 sigaction(SIGHUP, &sa, NULL);
161 sigaction(SIGQUIT, &sa, NULL);
162 sigaction(SIGINT, &sa, NULL);
163 sigaction(SIGTSTP, &sa, NULL);
164
165 ovtm = vtm;
166 vtm.mode = VT_PROCESS;
167 vtm.relsig = SIGUSR1;
168 vtm.acqsig = SIGUSR2;
169 ioctl(vfd, VT_SETMODE, &vtm);
170
171 tcgetattr(STDIN_FILENO, &oterm);
172 term = oterm;
173 term.c_iflag &= ~BRKINT;
174 term.c_iflag |= IGNBRK;
175 term.c_lflag &= ~ISIG;
176 term.c_lflag &= ~(ECHO | ECHOCTL);
177 tcsetattr(STDIN_FILENO, TCSANOW, &term);
178
179 do {
180 char *pass, *crypt_pass;
181 char prompt[100];
182
183 if (o_lock_all) {
184 printf("All Virtual Consoles locked.\n");
185 } else {
186 printf("This Virtual Console locked.\n");
187 }
188 fflush(stdout);
189
190 snprintf(prompt, 100, "%s's password: ", pw->pw_name);
191
192 if ((pass = getpass(prompt)) == NULL) {
193 perror("getpass");
194 restore_terminal();
195 exit(1);
196 }
197
198 crypt_pass = pw_encrypt(pass, pw->pw_passwd);
199 if (strncmp(crypt_pass, pw->pw_passwd, sizeof(crypt_pass)) == 0) {
200 memset(pass, 0, strlen(pass));
201 memset(crypt_pass, 0, strlen(crypt_pass));
202 restore_terminal();
203 return 0;
204 }
205 memset(pass, 0, strlen(pass));
206 memset(crypt_pass, 0, strlen(crypt_pass));
207
208 if (isatty(STDIN_FILENO) == 0) {
209 perror("isatty");
210 restore_terminal();
211 exit(1);
212 }
213
214 sleep(++times);
215 printf("Password incorrect.\n");
216 if (times >= 3) {
217 sleep(15);
218 times = 2;
219 }
220 } while (1);
221}
222
223/*
224Local Variables:
225c-file-style: "linux"
226c-basic-offset: 4
227tab-width: 4
228End:
229*/