Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/loginutils
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- Location:
- branches/3.2/mindi-busybox/loginutils
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/loginutils/Config.src
r2725 r3232 182 182 select FEATURE_SYSLOG 183 183 help 184 getty lets you log in on a tty, it is normally invoked by init. 184 getty lets you log in on a tty. It is normally invoked by init. 185 186 Note that you can save a few bytes by disabling it and 187 using login applet directly. 188 If you need to reset tty attributes before calling login, 189 this script approximates getty: 190 191 exec </dev/$1 >/dev/$1 2>&1 || exit 1 192 reset 193 stty sane; stty ispeed 38400; stty ospeed 38400 194 printf "%s login: " "`hostname`" 195 read -r login 196 exec /bin/login "$login" 185 197 186 198 config LOGIN … … 193 205 Note that Busybox binary must be setuid root for this applet to 194 206 work properly. 207 208 config LOGIN_SESSION_AS_CHILD 209 bool "Run logged in session in a child process" 210 default y if PAM 211 depends on LOGIN 212 help 213 Run the logged in session in a child process. This allows 214 login to clean up things such as utmp entries or PAM sessions 215 when the login session is complete. If you use PAM, you 216 almost always would want this to be set to Y, else PAM session 217 will not be cleaned up. 195 218 196 219 config PAM … … 261 284 and uses this information to update a group of existing users. 262 285 286 config FEATURE_DEFAULT_PASSWD_ALGO 287 string "Default password encryption method (passwd -a, cryptpw -m parameter)" 288 default "des" 289 depends on PASSWD || CRYPTPW 290 help 291 Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512". 292 263 293 config SU 264 294 bool "su" -
branches/3.2/mindi-busybox/loginutils/add-remove-shell.c
r2725 r3232 9 9 */ 10 10 11 //applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, _BB_DIR_USR_BIN, _BB_SUID_DROP, add_shell ))12 //applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, _BB_DIR_USR_BIN, _BB_SUID_DROP, remove_shell))11 //applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell )) 12 //applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell)) 13 13 14 14 //kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o -
branches/3.2/mindi-busybox/loginutils/addgroup.c
r2725 r3232 10 10 * 11 11 */ 12 13 //usage:#define addgroup_trivial_usage 14 //usage: "[-g GID] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP" 15 //usage:#define addgroup_full_usage "\n\n" 16 //usage: "Add a group " IF_FEATURE_ADDUSER_TO_GROUP("or add a user to a group") "\n" 17 //usage: "\n -g GID Group id" 18 //usage: "\n -S Create a system group" 19 12 20 #include "libbb.h" 13 21 -
branches/3.2/mindi-busybox/loginutils/adduser.c
r2725 r3232 8 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 9 */ 10 11 //usage:#define adduser_trivial_usage 12 //usage: "[OPTIONS] USER [GROUP]" 13 //usage:#define adduser_full_usage "\n\n" 14 //usage: "Create new user, or add USER to GROUP\n" 15 //usage: "\n -h DIR Home directory" 16 //usage: "\n -g GECOS GECOS field" 17 //usage: "\n -s SHELL Login shell" 18 //usage: "\n -G GRP Add user to existing group" 19 //usage: "\n -S Create a system user" 20 //usage: "\n -D Don't assign a password" 21 //usage: "\n -H Don't create home directory" 22 //usage: "\n -u UID User id" 23 10 24 #include "libbb.h" 11 25 … … 53 67 if (p->pw_uid == max) { 54 68 bb_error_msg_and_die("no %cids left", 'u'); 69 /* this format string is reused in adduser and addgroup */ 55 70 } 56 71 p->pw_uid++; … … 66 81 } 67 82 68 static void addgroup_wrapper(struct passwd *p, const char *group_name) 69 { 70 char *cmd; 71 72 if (group_name) /* Add user to existing group */ 73 cmd = xasprintf("addgroup '%s' '%s'", p->pw_name, group_name); 74 else /* Add user to his own group with the first free gid found in passwd_study */ 75 cmd = xasprintf("addgroup -g %u '%s'", (unsigned)p->pw_gid, p->pw_name); 76 /* Warning: to be compatible with external addgroup programs we should use --gid instead */ 77 system(cmd); 78 free(cmd); 79 } 80 81 static void passwd_wrapper(const char *login) NORETURN; 82 83 static void passwd_wrapper(const char *login) 84 { 85 BB_EXECLP("passwd", "passwd", login, NULL); 83 static int addgroup_wrapper(struct passwd *p, const char *group_name) 84 { 85 char *argv[6]; 86 87 argv[0] = (char*)"addgroup"; 88 if (group_name) { 89 /* Add user to existing group */ 90 argv[1] = (char*)"--"; 91 argv[2] = p->pw_name; 92 argv[3] = (char*)group_name; 93 argv[4] = NULL; 94 } else { 95 /* Add user to his own group with the first free gid 96 * found in passwd_study. 97 */ 98 #if ENABLE_FEATURE_ADDGROUP_LONG_OPTIONS || !ENABLE_ADDGROUP 99 /* We try to use --gid, not -g, because "standard" addgroup 100 * has no short option -g, it has only long --gid. 101 */ 102 argv[1] = (char*)"--gid"; 103 #else 104 /* Breaks if system in fact does NOT use busybox addgroup */ 105 argv[1] = (char*)"-g"; 106 #endif 107 argv[2] = utoa(p->pw_gid); 108 argv[3] = (char*)"--"; 109 argv[4] = p->pw_name; 110 argv[5] = NULL; 111 } 112 113 return spawn_and_wait(argv); 114 } 115 116 static void passwd_wrapper(const char *login_name) NORETURN; 117 118 static void passwd_wrapper(const char *login_name) 119 { 120 BB_EXECLP("passwd", "passwd", "--", login_name, NULL); 86 121 bb_error_msg_and_die("can't execute passwd, you must set password manually"); 87 122 } … … 124 159 125 160 pw.pw_gecos = (char *)"Linux User,,,"; 126 pw.pw_shell = (char *)DEFAULT_SHELL; 161 /* We assume that newly created users "inherit" root's shell setting */ 162 pw.pw_shell = (char *)get_shell_name(); 127 163 pw.pw_dir = NULL; 128 164 129 /* exactly one non-option arg*/165 /* at most two non-option args */ 130 166 /* disable interactive passwd for system accounts */ 131 opt_complementary = " =1:SD:u+";167 opt_complementary = "?2:SD:u+"; 132 168 if (sizeof(pw.pw_uid) == sizeof(int)) { 133 169 opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &pw.pw_uid); … … 140 176 } 141 177 argv += optind; 178 pw.pw_name = argv[0]; 179 180 if (!opts && argv[1]) { 181 /* if called with two non-option arguments, adduser 182 * will add an existing user to an existing group. 183 */ 184 return addgroup_wrapper(&pw, argv[1]); 185 } 142 186 143 187 /* fill in the passwd struct */ 144 pw.pw_name = argv[0];145 188 die_if_bad_username(pw.pw_name); 146 189 if (!pw.pw_dir) { … … 170 213 if (ENABLE_FEATURE_CLEAN_UP) 171 214 free(p); 172 173 215 #if ENABLE_FEATURE_SHADOWPASSWDS 174 216 /* /etc/shadow fields: … … 204 246 /* New home. Copy /etc/skel to it */ 205 247 const char *args[] = { 206 "chown", "-R", 248 "chown", 249 "-R", 207 250 xasprintf("%u:%u", (int)pw.pw_uid, (int)pw.pw_gid), 208 pw.pw_dir, NULL 251 pw.pw_dir, 252 NULL 209 253 }; 210 254 /* Be silent on any errors (like: no /etc/skel) */ -
branches/3.2/mindi-busybox/loginutils/chpasswd.c
r2725 r3232 7 7 */ 8 8 #include "libbb.h" 9 10 //usage:#define chpasswd_trivial_usage 11 //usage: IF_LONG_OPTS("[--md5|--encrypted]") IF_NOT_LONG_OPTS("[-m|-e]") 12 //usage:#define chpasswd_full_usage "\n\n" 13 //usage: "Read user:password from stdin and update /etc/passwd\n" 14 //usage: IF_LONG_OPTS( 15 //usage: "\n -e,--encrypted Supplied passwords are in encrypted form" 16 //usage: "\n -m,--md5 Use MD5 encryption instead of DES" 17 //usage: ) 18 //usage: IF_NOT_LONG_OPTS( 19 //usage: "\n -e Supplied passwords are in encrypted form" 20 //usage: "\n -m Use MD5 encryption instead of DES" 21 //usage: ) 22 23 //TODO: implement -c ALGO 9 24 10 25 #if ENABLE_LONG_OPTS … … 21 36 int chpasswd_main(int argc UNUSED_PARAM, char **argv) 22 37 { 23 char *name, *pass; 24 char salt[sizeof("$N$XXXXXXXX")]; 25 int opt, rc; 26 int rnd = rnd; /* we *want* it to be non-initialized! */ 38 char *name; 39 int opt; 27 40 28 if (getuid() )41 if (getuid() != 0) 29 42 bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); 30 43 … … 34 47 35 48 while ((name = xmalloc_fgetline(stdin)) != NULL) { 49 char *free_me; 50 char *pass; 51 int rc; 52 36 53 pass = strchr(name, ':'); 37 54 if (!pass) … … 41 58 xuname2uid(name); /* dies if there is no such user */ 42 59 60 free_me = NULL; 43 61 if (!(opt & OPT_ENC)) { 44 rnd = crypt_make_salt(salt, 1, rnd); 62 char salt[sizeof("$N$XXXXXXXX")]; 63 64 crypt_make_salt(salt, 1); 45 65 if (opt & OPT_MD5) { 46 strcpy(salt, "$1$"); 47 rnd = crypt_make_salt(salt + 3, 4, rnd); 66 salt[0] = '$'; 67 salt[1] = '1'; 68 salt[2] = '$'; 69 crypt_make_salt(salt + 3, 4); 48 70 } 49 pass = pw_encrypt(pass, salt, 0);71 free_me = pass = pw_encrypt(pass, salt, 0); 50 72 } 51 73 … … 54 76 #if ENABLE_FEATURE_SHADOWPASSWDS 55 77 rc = update_passwd(bb_path_shadow_file, name, pass, NULL); 56 if (rc == 0) /* no lines updated, no errors detected */ 78 if (rc > 0) /* password in /etc/shadow was updated */ 79 pass = (char*)"x"; 80 if (rc >= 0) 81 /* 0 = /etc/shadow missing (not an error), >0 = passwd changed in /etc/shadow */ 57 82 #endif 58 83 rc = update_passwd(bb_path_passwd_file, name, pass, NULL); … … 65 90 logmode = LOGMODE_STDIO; 66 91 free(name); 67 if (!(opt & OPT_ENC)) 68 free(pass); 92 free(free_me); 69 93 } 70 94 return EXIT_SUCCESS; -
branches/3.2/mindi-busybox/loginutils/cryptpw.c
r2725 r3232 10 10 * Licensed under GPLv2, see file LICENSE in this source tree. 11 11 */ 12 13 //usage:#define cryptpw_trivial_usage 14 //usage: "[OPTIONS] [PASSWORD] [SALT]" 15 /* We do support -s, we just don't mention it */ 16 //usage:#define cryptpw_full_usage "\n\n" 17 //usage: "Crypt PASSWORD using crypt(3)\n" 18 //usage: IF_LONG_OPTS( 19 //usage: "\n -P,--password-fd=N Read password from fd N" 20 /* //usage: "\n -s,--stdin Use stdin; like -P0" */ 21 //usage: "\n -m,--method=TYPE Encryption method" 22 //usage: "\n -S,--salt=SALT" 23 //usage: ) 24 //usage: IF_NOT_LONG_OPTS( 25 //usage: "\n -P N Read password from fd N" 26 /* //usage: "\n -s Use stdin; like -P0" */ 27 //usage: "\n -m TYPE Encryption method TYPE" 28 //usage: "\n -S SALT" 29 //usage: ) 30 31 /* mkpasswd is an alias to cryptpw */ 32 //usage:#define mkpasswd_trivial_usage 33 //usage: "[OPTIONS] [PASSWORD] [SALT]" 34 /* We do support -s, we just don't mention it */ 35 //usage:#define mkpasswd_full_usage "\n\n" 36 //usage: "Crypt PASSWORD using crypt(3)\n" 37 //usage: IF_LONG_OPTS( 38 //usage: "\n -P,--password-fd=N Read password from fd N" 39 /* //usage: "\n -s,--stdin Use stdin; like -P0" */ 40 //usage: "\n -m,--method=TYPE Encryption method" 41 //usage: "\n -S,--salt=SALT" 42 //usage: ) 43 //usage: IF_NOT_LONG_OPTS( 44 //usage: "\n -P N Read password from fd N" 45 /* //usage: "\n -s Use stdin; like -P0" */ 46 //usage: "\n -m TYPE Encryption method TYPE" 47 //usage: "\n -S SALT" 48 //usage: ) 12 49 13 50 #include "libbb.h" … … 54 91 int cryptpw_main(int argc UNUSED_PARAM, char **argv) 55 92 { 56 /* $N$ + sha_salt_16_bytes + NUL */ 57 char salt[3 + 16 + 1]; 93 char salt[MAX_PW_SALT_LEN]; 58 94 char *salt_ptr; 59 95 const char *opt_m, *opt_S; 60 int len;61 96 int fd; 62 97 … … 71 106 #endif 72 107 fd = STDIN_FILENO; 73 opt_m = "d";108 opt_m = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO; 74 109 opt_S = NULL; 75 110 /* at most two non-option arguments; -P NUM */ … … 83 118 opt_S = argv[1]; 84 119 85 len = 2/2; 86 salt_ptr = salt; 87 if (opt_m[0] != 'd') { /* not des */ 88 len = 8/2; /* so far assuming md5 */ 89 *salt_ptr++ = '$'; 90 *salt_ptr++ = '1'; 91 *salt_ptr++ = '$'; 92 #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA 93 if (opt_m[0] == 's') { /* sha */ 94 salt[1] = '5' + (strcmp(opt_m, "sha512") == 0); 95 len = 16/2; 96 } 97 #endif 98 } 120 salt_ptr = crypt_make_pw_salt(salt, opt_m); 99 121 if (opt_S) 100 safe_strncpy(salt_ptr, opt_S, sizeof(salt) - 3); 101 else 102 crypt_make_salt(salt_ptr, len, 0); 122 safe_strncpy(salt_ptr, opt_S, sizeof(salt) - (sizeof("$N$")-1)); 103 123 104 124 xmove_fd(fd, STDIN_FILENO); -
branches/3.2/mindi-busybox/loginutils/deluser.c
r2725 r3232 10 10 * 11 11 */ 12 13 //usage:#define deluser_trivial_usage 14 //usage: "USER" 15 //usage:#define deluser_full_usage "\n\n" 16 //usage: "Delete USER from the system" 17 18 //usage:#define delgroup_trivial_usage 19 //usage: IF_FEATURE_DEL_USER_FROM_GROUP("[USER] ")"GROUP" 20 //usage:#define delgroup_full_usage "\n\n" 21 //usage: "Delete group GROUP from the system" 22 //usage: IF_FEATURE_DEL_USER_FROM_GROUP(" or user USER from group GROUP") 23 12 24 #include "libbb.h" 13 25 -
branches/3.2/mindi-busybox/loginutils/getty.c
r2725 r3232 1 1 /* vi: set sw=4 ts=4: */ 2 /* agetty.c - another getty program for Linux. By W. Z. Venema 1989 2 /* 3 * Based on agetty - another getty program for Linux. By W. Z. Venema 1989 3 4 * Ported to Linux by Peter Orbaek <poe@daimi.aau.dk> 4 * This program is freely distributable. The entire man-page used to 5 * be here. Now read the real man-page agetty.8 instead. 5 * This program is freely distributable. 6 6 * 7 7 * option added by Eric Rasmussen <ear@usfirst.org> - 12/28/95 8 8 * 9 9 * 1999-02-22 Arkadiusz Mickiewicz <misiek@misiek.eu.org> 10 * - added Native Language Support10 * - Added Native Language Support 11 11 * 12 12 * 1999-05-05 Thorsten Kranzkowski <dl8bcu@gmx.net> 13 * - enable hardware flow control before displaying /etc/issue 13 * - Enabled hardware flow control before displaying /etc/issue 14 * 15 * 2011-01 Venys Vlasenko 16 * - Removed parity detection code. It can't work reliably: 17 * if all chars received have bit 7 cleared and odd (or even) parity, 18 * it is impossible to determine whether other side is 8-bit,no-parity 19 * or 7-bit,odd(even)-parity. It also interferes with non-ASCII usernames. 20 * - From now on, we assume that parity is correctly set. 14 21 * 15 22 * Licensed under GPLv2 or later, see file LICENSE in this source tree. … … 18 25 #include "libbb.h" 19 26 #include <syslog.h> 20 21 #if ENABLE_FEATURE_UTMP22 # include <utmp.h> /* LOGIN_PROCESS */23 #endif24 25 27 #ifndef IUCLC 26 28 # define IUCLC 0 27 29 #endif 28 30 29 /* 30 * Some heuristics to find out what environment we are in: if it is not 31 * System V, assume it is SunOS 4. 32 */ 33 #ifdef LOGIN_PROCESS /* defined in System V utmp.h */ 34 #include <sys/utsname.h> 35 #else /* if !sysV style, wtmp/utmp code is off */ 36 #undef ENABLE_FEATURE_UTMP 37 #undef ENABLE_FEATURE_WTMP 38 #define ENABLE_FEATURE_UTMP 0 39 #define ENABLE_FEATURE_WTMP 0 40 #endif /* LOGIN_PROCESS */ 31 #ifndef LOGIN_PROCESS 32 # undef ENABLE_FEATURE_UTMP 33 # undef ENABLE_FEATURE_WTMP 34 # define ENABLE_FEATURE_UTMP 0 35 # define ENABLE_FEATURE_WTMP 0 36 #endif 37 38 39 /* The following is used for understandable diagnostics */ 40 #ifdef DEBUGGING 41 static FILE *dbf; 42 # define DEBUGTERM "/dev/ttyp0" 43 # define debug(...) do { fprintf(dbf, __VA_ARGS__); fflush(dbf); } while (0) 44 #else 45 # define debug(...) ((void)0) 46 #endif 47 41 48 42 49 /* … … 47 54 * and for line editing at the same time. 48 55 */ 49 50 /* I doubt there are systems which still need this */ 51 #undef HANDLE_ALLCAPS 52 #undef ANCIENT_BS_KILL_CHARS 53 56 #undef _PATH_LOGIN 54 57 #define _PATH_LOGIN "/bin/login" 55 58 56 /* If ISSUE is not defined, getty will never display the contents of the 59 /* Displayed before the login prompt. 60 * If ISSUE is not defined, getty will never display the contents of the 57 61 * /etc/issue file. You will not want to spit out large "issue" files at the 58 62 * wrong baud rate. 59 63 */ 60 #define ISSUE "/etc/issue" /* displayed before the login prompt */ 61 62 /* Some shorthands for control characters. */ 63 #define CTL(x) ((x) ^ 0100) /* Assumes ASCII dialect */ 64 #define CR CTL('M') /* carriage return */ 65 #define NL CTL('J') /* line feed */ 66 #define BS CTL('H') /* back space */ 67 #define DEL CTL('?') /* delete */ 68 69 /* Defaults for line-editing etc. characters; you may want to change this. */ 70 #define DEF_ERASE DEL /* default erase character */ 71 #define DEF_INTR CTL('C') /* default interrupt character */ 72 #define DEF_QUIT CTL('\\') /* default quit char */ 73 #define DEF_KILL CTL('U') /* default kill char */ 74 #define DEF_EOF CTL('D') /* default EOF char */ 75 #define DEF_EOL '\n' 76 #define DEF_SWITCH 0 /* default switch char */ 64 #define ISSUE "/etc/issue" 65 66 /* Macro to build Ctrl-LETTER. Assumes ASCII dialect */ 67 #define CTL(x) ((x) ^ 0100) 77 68 78 69 /* 79 * When multiple baud rates are specified on the command line, the first one80 * we will try is the first one specified.70 * When multiple baud rates are specified on the command line, 71 * the first one we will try is the first one specified. 81 72 */ 82 73 #define MAX_SPEED 10 /* max. nr. of baud rates */ 83 74 84 /* Storage for command-line options. */ 85 struct options { 86 int flags; /* toggle switches, see below */ 87 unsigned timeout; /* time-out period */ 75 struct globals { 76 unsigned timeout; 88 77 const char *login; /* login program */ 89 const char *tty; /* name of tty */ 90 const char *initstring; /* modem init string */ 78 const char *fakehost; 79 const char *tty_name; 80 char *initstring; /* modem init string */ 91 81 const char *issue; /* alternative issue file */ 92 82 int numspeed; /* number of baud rates to try */ 93 83 int speeds[MAX_SPEED]; /* baud rates to be tried */ 84 unsigned char eol; /* end-of-line char seen (CR or NL) */ 85 struct termios tty_attrs; 86 char line_buf[128]; 94 87 }; 95 88 96 /* Storage for things detected while the login name was read. */ 97 struct chardata { 98 unsigned char erase; /* erase character */ 99 unsigned char kill; /* kill character */ 100 unsigned char eol; /* end-of-line character */ 101 unsigned char parity; /* what parity did we see */ 102 /* (parity & 1): saw odd parity char with 7th bit set */ 103 /* (parity & 2): saw even parity char with 7th bit set */ 104 /* parity == 0: probably 7-bit, space parity? */ 105 /* parity == 1: probably 7-bit, odd parity? */ 106 /* parity == 2: probably 7-bit, even parity? */ 107 /* parity == 3: definitely 8 bit, no parity! */ 108 /* Hmm... with any value of "parity" 8 bit, no parity is possible */ 109 #ifdef HANDLE_ALLCAPS 110 unsigned char capslock; /* upper case without lower case */ 111 #endif 112 }; 113 114 115 /* Initial values for the above. */ 116 static const struct chardata init_chardata = { 117 DEF_ERASE, /* default erase character */ 118 DEF_KILL, /* default kill character */ 119 13, /* default eol char */ 120 0, /* space parity */ 121 #ifdef HANDLE_ALLCAPS 122 0, /* no capslock */ 123 #endif 124 }; 89 #define G (*ptr_to_globals) 90 #define INIT_G() do { \ 91 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 92 } while (0) 93 94 //usage:#define getty_trivial_usage 95 //usage: "[OPTIONS] BAUD_RATE[,BAUD_RATE]... TTY [TERMTYPE]" 96 //usage:#define getty_full_usage "\n\n" 97 //usage: "Open TTY, prompt for login name, then invoke /bin/login\n" 98 //usage: "\n -h Enable hardware RTS/CTS flow control" 99 //usage: "\n -L Set CLOCAL (ignore Carrier Detect state)" 100 //usage: "\n -m Get baud rate from modem's CONNECT status message" 101 //usage: "\n -n Don't prompt for login name" 102 //usage: "\n -w Wait for CR or LF before sending /etc/issue" 103 //usage: "\n -i Don't display /etc/issue" 104 //usage: "\n -f ISSUE_FILE Display ISSUE_FILE instead of /etc/issue" 105 //usage: "\n -l LOGIN Invoke LOGIN instead of /bin/login" 106 //usage: "\n -t SEC Terminate after SEC if no login name is read" 107 //usage: "\n -I INITSTR Send INITSTR before anything else" 108 //usage: "\n -H HOST Log HOST into the utmp file as the hostname" 109 //usage: "\n" 110 //usage: "\nBAUD_RATE of 0 leaves it unchanged" 125 111 126 112 static const char opt_string[] ALIGN1 = "I:LH:f:hil:mt:wn"; 127 #define F_INITSTRING (1 << 0) /* -I initstring is set */ 128 #define F_LOCAL (1 << 1) /* -L force local */ 129 #define F_FAKEHOST (1 << 2) /* -H fake hostname */ 130 #define F_CUSTISSUE (1 << 3) /* -f give alternative issue file */ 131 #define F_RTSCTS (1 << 4) /* -h enable RTS/CTS flow control */ 132 #define F_ISSUE (1 << 5) /* -i display /etc/issue */ 133 #define F_LOGIN (1 << 6) /* -l non-default login program */ 134 #define F_PARSE (1 << 7) /* -m process modem status messages */ 135 #define F_TIMEOUT (1 << 8) /* -t time out */ 136 #define F_WAITCRLF (1 << 9) /* -w wait for CR or LF */ 137 #define F_NOPROMPT (1 << 10) /* -n don't ask for login name */ 138 139 140 #define line_buf bb_common_bufsiz1 141 142 /* The following is used for understandable diagnostics. */ 143 #ifdef DEBUGGING 144 static FILE *dbf; 145 #define DEBUGTERM "/dev/ttyp0" 146 #define debug(...) do { fprintf(dbf, __VA_ARGS__); fflush(dbf); } while (0) 147 #else 148 #define debug(...) ((void)0) 149 #endif 150 151 152 /* bcode - convert speed string to speed code; return <= 0 on failure */ 113 #define F_INITSTRING (1 << 0) /* -I */ 114 #define F_LOCAL (1 << 1) /* -L */ 115 #define F_FAKEHOST (1 << 2) /* -H */ 116 #define F_CUSTISSUE (1 << 3) /* -f */ 117 #define F_RTSCTS (1 << 4) /* -h */ 118 #define F_NOISSUE (1 << 5) /* -i */ 119 #define F_LOGIN (1 << 6) /* -l */ 120 #define F_PARSE (1 << 7) /* -m */ 121 #define F_TIMEOUT (1 << 8) /* -t */ 122 #define F_WAITCRLF (1 << 9) /* -w */ 123 #define F_NOPROMPT (1 << 10) /* -n */ 124 125 126 /* convert speed string to speed code; return <= 0 on failure */ 153 127 static int bcode(const char *s) 154 128 { … … 159 133 } 160 134 161 /* parse _speeds - parsealternate baud rates */162 static void parse_speeds( struct options *op,char *arg)135 /* parse alternate baud rates */ 136 static void parse_speeds(char *arg) 163 137 { 164 138 char *cp; … … 167 141 debug("entered parse_speeds\n"); 168 142 while ((cp = strsep(&arg, ",")) != NULL) { 169 op->speeds[op->numspeed] = bcode(cp);170 if ( op->speeds[op->numspeed] < 0)143 G.speeds[G.numspeed] = bcode(cp); 144 if (G.speeds[G.numspeed] < 0) 171 145 bb_error_msg_and_die("bad speed: %s", cp); 172 146 /* note: arg "0" turns into speed B0 */ 173 op->numspeed++;174 if ( op->numspeed > MAX_SPEED)147 G.numspeed++; 148 if (G.numspeed > MAX_SPEED) 175 149 bb_error_msg_and_die("too many alternate speeds"); 176 150 } … … 178 152 } 179 153 180 /* parse _args - parsecommand-line arguments */181 static void parse_args(char **argv , struct options *op, char **fakehost_p)154 /* parse command-line arguments */ 155 static void parse_args(char **argv) 182 156 { 183 157 char *ts; 158 int flags; 184 159 185 160 opt_complementary = "-2:t+"; /* at least 2 args; -t N */ 186 op->flags = getopt32(argv, opt_string, 187 &(op->initstring), fakehost_p, &(op->issue), 188 &(op->login), &op->timeout); 161 flags = getopt32(argv, opt_string, 162 &G.initstring, &G.fakehost, &G.issue, 163 &G.login, &G.timeout 164 ); 165 if (flags & F_INITSTRING) { 166 G.initstring = xstrdup(G.initstring); 167 /* decode \ddd octal codes into chars */ 168 strcpy_and_process_escape_sequences(G.initstring, G.initstring); 169 } 189 170 argv += optind; 190 if (op->flags & F_INITSTRING) {191 op->initstring = xstrdup(op->initstring);192 /* decode \ddd octal codes into chars */193 strcpy_and_process_escape_sequences((char*)op->initstring, op->initstring);194 }195 op->flags ^= F_ISSUE; /* invert flag "show /etc/issue" */196 171 debug("after getopt\n"); 197 172 198 /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */199 op->tty = argv[0]; /* tty name */200 ts = argv[1]; /* baud rate(s) */173 /* We loosen up a bit and accept both "baudrate tty" and "tty baudrate" */ 174 G.tty_name = argv[0]; 175 ts = argv[1]; /* baud rate(s) */ 201 176 if (isdigit(argv[0][0])) { 202 /* a number first, assume it's a speed (BSD style) */ 203 op->tty = ts; /* tty name is in argv[1] */ 204 ts = argv[0]; /* baud rate(s) */ 205 } 206 parse_speeds(op, ts); 207 applet_name = xasprintf("getty: %s", op->tty); 177 /* A number first, assume it's a speed (BSD style) */ 178 G.tty_name = ts; /* tty name is in argv[1] */ 179 ts = argv[0]; /* baud rate(s) */ 180 } 181 parse_speeds(ts); 208 182 209 183 if (argv[2]) … … 213 187 } 214 188 215 /* open_tty - set up tty as standard { input, output, error } */ 216 static void open_tty(const char *tty) 217 { 218 /* Set up new standard input, unless we are given an already opened port. */ 219 if (NOT_LONE_DASH(tty)) { 220 // struct stat st; 221 // int cur_dir_fd; 222 // int fd; 223 224 /* Sanity checks... */ 225 // cur_dir_fd = xopen(".", O_DIRECTORY | O_NONBLOCK); 226 // xchdir("/dev"); 227 // xstat(tty, &st); 228 // if (!S_ISCHR(st.st_mode)) 229 // bb_error_msg_and_die("not a character device"); 230 231 if (tty[0] != '/') 232 tty = xasprintf("/dev/%s", tty); /* will leak it */ 233 234 /* Open the tty as standard input. */ 189 /* set up tty as standard input, output, error */ 190 static void open_tty(void) 191 { 192 /* Set up new standard input, unless we are given an already opened port */ 193 if (NOT_LONE_DASH(G.tty_name)) { 194 if (G.tty_name[0] != '/') 195 G.tty_name = xasprintf("/dev/%s", G.tty_name); /* will leak it */ 196 197 /* Open the tty as standard input */ 235 198 debug("open(2)\n"); 236 199 close(0); 237 /*fd =*/ xopen(tty, O_RDWR | O_NONBLOCK); /* uses fd 0 */ 238 239 // /* Restore current directory */ 240 // fchdir(cur_dir_fd); 241 242 /* Open the tty as standard input, continued */ 243 // xmove_fd(fd, 0); 244 // /* fd is >= cur_dir_fd, and cur_dir_fd gets closed too here: */ 245 // while (fd > 2) 246 // close(fd--); 247 248 /* Set proper protections and ownership. */ 200 xopen(G.tty_name, O_RDWR | O_NONBLOCK); /* uses fd 0 */ 201 202 /* Set proper protections and ownership */ 249 203 fchown(0, 0, 0); /* 0:0 */ 250 204 fchmod(0, 0620); /* crw--w---- */ 251 205 } else { 206 char *n; 252 207 /* 253 * Standard input should already be connected to an open port. Make254 * sure it is open for read/write.208 * Standard input should already be connected to an open port. 209 * Make sure it is open for read/write. 255 210 */ 256 if ((fcntl(0, F_GETFL) & O_RDWR) != O_RDWR)211 if ((fcntl(0, F_GETFL) & (O_RDWR|O_RDONLY|O_WRONLY)) != O_RDWR) 257 212 bb_error_msg_and_die("stdin is not open for read/write"); 258 } 259 } 260 261 /* termios_init - initialize termios settings */ 262 static void termios_init(struct termios *tp, int speed, struct options *op) 263 { 264 speed_t ispeed, ospeed; 265 /* 266 * Initial termios settings: 8-bit characters, raw-mode, blocking i/o. 213 214 /* Try to get real tty name instead of "-" */ 215 n = xmalloc_ttyname(0); 216 if (n) 217 G.tty_name = n; 218 } 219 applet_name = xasprintf("getty: %s", skip_dev_pfx(G.tty_name)); 220 } 221 222 static void set_tty_attrs(void) 223 { 224 if (tcsetattr_stdin_TCSANOW(&G.tty_attrs) < 0) 225 bb_perror_msg_and_die("tcsetattr"); 226 } 227 228 /* We manipulate tty_attrs this way: 229 * - first, we read existing tty_attrs 230 * - init_tty_attrs modifies some parts and sets it 231 * - auto_baud and/or BREAK processing can set different speed and set tty attrs 232 * - finalize_tty_attrs again modifies some parts and sets tty attrs before 233 * execing login 234 */ 235 static void init_tty_attrs(int speed) 236 { 237 /* Try to drain output buffer, with 5 sec timeout. 238 * Added on request from users of ~600 baud serial interface 239 * with biggish buffer on a 90MHz CPU. 240 * They were losing hundreds of bytes of buffered output 241 * on tcflush. 242 */ 243 signal_no_SA_RESTART_empty_mask(SIGALRM, record_signo); 244 alarm(5); 245 tcdrain(STDIN_FILENO); 246 alarm(0); 247 248 /* Flush input and output queues, important for modems! */ 249 tcflush(STDIN_FILENO, TCIOFLUSH); 250 251 /* Set speed if it wasn't specified as "0" on command line */ 252 if (speed != B0) 253 cfsetspeed(&G.tty_attrs, speed); 254 255 /* Initial settings: 8-bit characters, raw mode, blocking i/o. 267 256 * Special characters are set after we have read the login name; all 268 * reads will be done in raw mode anyway. Errors will be dealt with 269 * later on. 270 */ 271 /* flush input and output queues, important for modems! */ 272 tcflush(0, TCIOFLUSH); 273 ispeed = ospeed = speed; 274 if (speed == B0) { 275 /* Speed was specified as "0" on command line. 276 * Just leave it unchanged */ 277 ispeed = cfgetispeed(tp); 278 ospeed = cfgetospeed(tp); 279 } 280 tp->c_cflag = CS8 | HUPCL | CREAD; 281 if (op->flags & F_LOCAL) 282 tp->c_cflag |= CLOCAL; 283 cfsetispeed(tp, ispeed); 284 cfsetospeed(tp, ospeed); 285 286 tp->c_iflag = tp->c_lflag = 0; 287 tp->c_oflag = OPOST | ONLCR; 288 tp->c_cc[VMIN] = 1; 289 tp->c_cc[VTIME] = 0; 257 * reads will be done in raw mode anyway. 258 */ 259 /* Clear all bits except: */ 260 G.tty_attrs.c_cflag &= (0 261 /* 2 stop bits (1 otherwise) 262 * Enable parity bit (both on input and output) 263 * Odd parity (else even) 264 */ 265 | CSTOPB | PARENB | PARODD 266 #ifdef CMSPAR 267 | CMSPAR /* mark or space parity */ 268 #endif 269 #ifdef CBAUD 270 | CBAUD /* (output) baud rate */ 271 #endif 272 #ifdef CBAUDEX 273 | CBAUDEX /* (output) baud rate */ 274 #endif 275 #ifdef CIBAUD 276 | CIBAUD /* input baud rate */ 277 #endif 278 ); 279 /* Set: 8 bits; hang up (drop DTR) on last close; enable receive */ 280 G.tty_attrs.c_cflag |= CS8 | HUPCL | CREAD; 281 if (option_mask32 & F_LOCAL) { 282 /* ignore Carrier Detect pin: 283 * opens don't block when CD is low, 284 * losing CD doesn't hang up processes whose ctty is this tty 285 */ 286 G.tty_attrs.c_cflag |= CLOCAL; 287 } 288 #ifdef CRTSCTS 289 if (option_mask32 & F_RTSCTS) 290 G.tty_attrs.c_cflag |= CRTSCTS; /* flow control using RTS/CTS pins */ 291 #endif 292 G.tty_attrs.c_iflag = 0; 293 G.tty_attrs.c_lflag = 0; 294 /* non-raw output; add CR to each NL */ 295 G.tty_attrs.c_oflag = OPOST | ONLCR; 296 297 /* reads would block only if < 1 char is available */ 298 G.tty_attrs.c_cc[VMIN] = 1; 299 /* no timeout (reads block forever) */ 300 G.tty_attrs.c_cc[VTIME] = 0; 290 301 #ifdef __linux__ 291 tp->c_line = 0; 292 #endif 293 294 /* Optionally enable hardware flow control */ 295 #ifdef CRTSCTS 296 if (op->flags & F_RTSCTS) 297 tp->c_cflag |= CRTSCTS; 298 #endif 299 300 tcsetattr_stdin_TCSANOW(tp); 302 G.tty_attrs.c_line = 0; 303 #endif 304 305 set_tty_attrs(); 301 306 302 307 debug("term_io 2\n"); 303 308 } 304 309 305 /* auto_baud - extract baud rate from modem status message */ 306 static void auto_baud(char *buf, unsigned size_buf, struct termios *tp) 307 { 308 int speed; 309 int vmin; 310 unsigned iflag; 311 char *bp; 310 static void finalize_tty_attrs(void) 311 { 312 /* software flow control on output (stop sending if XOFF is recvd); 313 * and on input (send XOFF when buffer is full) 314 */ 315 G.tty_attrs.c_iflag |= IXON | IXOFF; 316 if (G.eol == '\r') { 317 G.tty_attrs.c_iflag |= ICRNL; /* map CR on input to NL */ 318 } 319 /* Other bits in c_iflag: 320 * IXANY Any recvd char enables output (any char is also a XON) 321 * INPCK Enable parity check 322 * IGNPAR Ignore parity errors (drop bad bytes) 323 * PARMRK Mark parity errors with 0xff, 0x00 prefix 324 * (else bad byte is received as 0x00) 325 * ISTRIP Strip parity bit 326 * IGNBRK Ignore break condition 327 * BRKINT Send SIGINT on break - maybe set this? 328 * INLCR Map NL to CR 329 * IGNCR Ignore CR 330 * ICRNL Map CR to NL 331 * IUCLC Map uppercase to lowercase 332 * IMAXBEL Echo BEL on input line too long 333 * IUTF8 Appears to affect tty's idea of char widths, 334 * observed to improve backspacing through Unicode chars 335 */ 336 337 /* line buffered input (NL or EOL or EOF chars end a line); 338 * recognize INT/QUIT/SUSP chars; 339 * echo input chars; 340 * echo BS-SP-BS on erase character; 341 * echo kill char specially, not as ^c (ECHOKE controls how exactly); 342 * erase all input via BS-SP-BS on kill char (else go to next line) 343 */ 344 G.tty_attrs.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; 345 /* Other bits in c_lflag: 346 * XCASE Map uppercase to \lowercase [tried, doesn't work] 347 * ECHONL Echo NL even if ECHO is not set 348 * ECHOCTL Echo ctrl chars as ^c (else don't echo) - maybe set this? 349 * ECHOPRT On erase, echo erased chars 350 * [qwe<BS><BS><BS> input looks like "qwe\ewq/" on screen] 351 * NOFLSH Don't flush input buffer after interrupt or quit chars 352 * IEXTEN Enable extended functions (??) 353 * [glibc says it enables c_cc[LNEXT] "enter literal char" 354 * and c_cc[VDISCARD] "toggle discard buffered output" chars] 355 * FLUSHO Output being flushed (c_cc[VDISCARD] is in effect) 356 * PENDIN Retype pending input at next read or input char 357 * (c_cc[VREPRINT] is being processed) 358 * TOSTOP Send SIGTTOU for background output 359 * (why "stty sane" unsets this bit?) 360 */ 361 362 G.tty_attrs.c_cc[VINTR] = CTL('C'); 363 G.tty_attrs.c_cc[VQUIT] = CTL('\\'); 364 G.tty_attrs.c_cc[VEOF] = CTL('D'); 365 G.tty_attrs.c_cc[VEOL] = '\n'; 366 #ifdef VSWTC 367 G.tty_attrs.c_cc[VSWTC] = 0; 368 #endif 369 #ifdef VSWTCH 370 G.tty_attrs.c_cc[VSWTCH] = 0; 371 #endif 372 G.tty_attrs.c_cc[VKILL] = CTL('U'); 373 /* Other control chars: 374 * VEOL2 375 * VERASE, VWERASE - (word) erase. we may set VERASE in get_logname 376 * VREPRINT - reprint current input buffer 377 * VLNEXT, VDISCARD, VSTATUS 378 * VSUSP, VDSUSP - send (delayed) SIGTSTP 379 * VSTART, VSTOP - chars used for IXON/IXOFF 380 */ 381 382 set_tty_attrs(); 383 384 /* Now the newline character should be properly written */ 385 full_write(STDOUT_FILENO, "\n", 1); 386 } 387 388 /* extract baud rate from modem status message */ 389 static void auto_baud(void) 390 { 312 391 int nread; 313 392 … … 327 406 */ 328 407 329 /* 330 * Use 7-bit characters, don't block if input queue is empty. Errors will 331 * be dealt with later on. 332 */ 333 iflag = tp->c_iflag; 334 tp->c_iflag |= ISTRIP; /* enable 8th-bit stripping */ 335 vmin = tp->c_cc[VMIN]; 336 tp->c_cc[VMIN] = 0; /* don't block if queue empty */ 337 tcsetattr_stdin_TCSANOW(tp); 408 G.tty_attrs.c_cc[VMIN] = 0; /* don't block reads (min read is 0 chars) */ 409 set_tty_attrs(); 338 410 339 411 /* … … 342 414 */ 343 415 sleep(1); 344 nread = safe_read(STDIN_FILENO, buf, size_buf- 1);416 nread = safe_read(STDIN_FILENO, G.line_buf, sizeof(G.line_buf) - 1); 345 417 if (nread > 0) { 346 buf[nread] = '\0'; 347 for (bp = buf; bp < buf + nread; bp++) { 418 int speed; 419 char *bp; 420 G.line_buf[nread] = '\0'; 421 for (bp = G.line_buf; bp < G.line_buf + nread; bp++) { 348 422 if (isdigit(*bp)) { 349 423 speed = bcode(bp); 350 424 if (speed > 0) 351 cfsetspeed( tp, speed);425 cfsetspeed(&G.tty_attrs, speed); 352 426 break; 353 427 } … … 355 429 } 356 430 357 /* Restore terminal settings. Errors will be dealt with later on. */ 358 tp->c_iflag = iflag; 359 tp->c_cc[VMIN] = vmin; 360 tcsetattr_stdin_TCSANOW(tp); 361 } 362 363 /* do_prompt - show login prompt, optionally preceded by /etc/issue contents */ 364 static void do_prompt(struct options *op) 365 { 431 /* Restore terminal settings */ 432 G.tty_attrs.c_cc[VMIN] = 1; /* restore to value set by init_tty_attrs */ 433 set_tty_attrs(); 434 } 435 436 /* get user name, establish parity, speed, erase, kill, eol; 437 * return NULL on BREAK, logname on success 438 */ 439 static char *get_logname(void) 440 { 441 char *bp; 442 char c; 443 444 /* Flush pending input (esp. after parsing or switching the baud rate) */ 445 usleep(100*1000); /* 0.1 sec */ 446 tcflush(STDIN_FILENO, TCIFLUSH); 447 448 /* Prompt for and read a login name */ 449 do { 450 /* Write issue file and prompt */ 366 451 #ifdef ISSUE 367 print_login_issue(op->issue, op->tty); 368 #endif 369 print_login_prompt(); 370 } 371 372 #ifdef HANDLE_ALLCAPS 373 /* all_is_upcase - string contains upper case without lower case */ 374 /* returns 1 if true, 0 if false */ 375 static int all_is_upcase(const char *s) 376 { 377 while (*s) 378 if (islower(*s++)) 379 return 0; 380 return 1; 381 } 382 #endif 383 384 /* get_logname - get user name, establish parity, speed, erase, kill, eol; 385 * return NULL on BREAK, logname on success */ 386 static char *get_logname(char *logname, unsigned size_logname, 387 struct options *op, struct chardata *cp) 388 { 389 char *bp; 390 char c; /* input character, full eight bits */ 391 char ascval; /* low 7 bits of input character */ 392 int bits; /* # of "1" bits per character */ 393 int mask; /* mask with 1 bit up */ 394 static const char erase[][3] = {/* backspace-space-backspace */ 395 "\010\040\010", /* space parity */ 396 "\010\040\010", /* odd parity */ 397 "\210\240\210", /* even parity */ 398 "\010\040\010", /* 8 bit no parity */ 399 }; 400 401 /* NB: *cp is pre-initialized with init_chardata */ 402 403 /* Flush pending input (esp. after parsing or switching the baud rate). */ 404 sleep(1); 405 tcflush(0, TCIOFLUSH); 406 407 /* Prompt for and read a login name. */ 408 logname[0] = '\0'; 409 while (!logname[0]) { 410 /* Write issue file and prompt, with "parity" bit == 0. */ 411 do_prompt(op); 412 413 /* Read name, watch for break, parity, erase, kill, end-of-line. */ 414 bp = logname; 415 cp->eol = '\0'; 416 while (cp->eol == '\0') { 417 418 /* Do not report trivial EINTR/EIO errors. */ 452 if (!(option_mask32 & F_NOISSUE)) 453 print_login_issue(G.issue, G.tty_name); 454 #endif 455 print_login_prompt(); 456 457 /* Read name, watch for break, erase, kill, end-of-line */ 458 bp = G.line_buf; 459 while (1) { 460 /* Do not report trivial EINTR/EIO errors */ 419 461 errno = EINTR; /* make read of 0 bytes be silent too */ 420 462 if (read(STDIN_FILENO, &c, 1) < 1) { 463 finalize_tty_attrs(); 421 464 if (errno == EINTR || errno == EIO) 422 465 exit(EXIT_SUCCESS); … … 424 467 } 425 468 426 /* BREAK. If we have speeds to try, 427 * return NULL (will switch speeds and return here) */ 428 if (c == '\0' && op->numspeed > 1) 429 return NULL; 430 431 /* Do parity bit handling. */ 432 if (!(op->flags & F_LOCAL) && (c & 0x80)) { /* "parity" bit on? */ 433 bits = 1; 434 mask = 1; 435 while (mask & 0x7f) { 436 if (mask & c) 437 bits++; /* count "1" bits */ 438 mask <<= 1; 439 } 440 /* ... |= 2 - even, 1 - odd */ 441 cp->parity |= 2 - (bits & 1); 442 } 443 444 /* Do erase, kill and end-of-line processing. */ 445 ascval = c & 0x7f; 446 switch (ascval) { 447 case CR: 448 case NL: 449 *bp = '\0'; /* terminate logname */ 450 cp->eol = ascval; /* set end-of-line char */ 451 break; 452 case BS: 453 case DEL: 454 #ifdef ANCIENT_BS_KILL_CHARS 455 case '#': 456 #endif 457 cp->erase = ascval; /* set erase character */ 458 if (bp > logname) { 459 full_write(STDOUT_FILENO, erase[cp->parity], 3); 469 switch (c) { 470 case '\r': 471 case '\n': 472 *bp = '\0'; 473 G.eol = c; 474 goto got_logname; 475 case CTL('H'): 476 case 0x7f: 477 G.tty_attrs.c_cc[VERASE] = c; 478 if (bp > G.line_buf) { 479 full_write(STDOUT_FILENO, "\010 \010", 3); 460 480 bp--; 461 481 } 462 482 break; 463 483 case CTL('U'): 464 #ifdef ANCIENT_BS_KILL_CHARS 465 case '@': 466 #endif 467 cp->kill = ascval; /* set kill character */ 468 while (bp > logname) { 469 full_write(STDOUT_FILENO, erase[cp->parity], 3); 484 while (bp > G.line_buf) { 485 full_write(STDOUT_FILENO, "\010 \010", 3); 470 486 bp--; 471 487 } 472 488 break; 489 case CTL('C'): 473 490 case CTL('D'): 491 finalize_tty_attrs(); 474 492 exit(EXIT_SUCCESS); 493 case '\0': 494 /* BREAK. If we have speeds to try, 495 * return NULL (will switch speeds and return here) */ 496 if (G.numspeed > 1) 497 return NULL; 498 /* fall through and ignore it */ 475 499 default: 476 if ( ascval< ' ') {500 if ((unsigned char)c < ' ') { 477 501 /* ignore garbage characters */ 478 } else if ((int)(bp - logname) >= size_logname - 1) { 479 bb_error_msg_and_die("input overrun"); 480 } else { 481 full_write(STDOUT_FILENO, &c, 1); /* echo the character */ 482 *bp++ = ascval; /* and store it */ 502 } else if ((int)(bp - G.line_buf) < sizeof(G.line_buf) - 1) { 503 /* echo and store the character */ 504 full_write(STDOUT_FILENO, &c, 1); 505 *bp++ = c; 483 506 } 484 507 break; 485 508 } 486 } 487 } 488 /* Handle names with upper case and no lower case. */ 489 490 #ifdef HANDLE_ALLCAPS 491 cp->capslock = all_is_upcase(logname); 492 if (cp->capslock) { 493 for (bp = logname; *bp; bp++) 494 if (isupper(*bp)) 495 *bp = tolower(*bp); /* map name to lower case */ 496 } 497 #endif 498 return logname; 499 } 500 501 /* termios_final - set the final tty mode bits */ 502 static void termios_final(struct options *op, struct termios *tp, struct chardata *cp) 503 { 504 /* General terminal-independent stuff. */ 505 tp->c_iflag |= IXON | IXOFF; /* 2-way flow control */ 506 tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; 507 /* no longer| ECHOCTL | ECHOPRT */ 508 tp->c_oflag |= OPOST; 509 /* tp->c_cflag = 0; */ 510 tp->c_cc[VINTR] = DEF_INTR; /* default interrupt */ 511 tp->c_cc[VQUIT] = DEF_QUIT; /* default quit */ 512 tp->c_cc[VEOF] = DEF_EOF; /* default EOF character */ 513 tp->c_cc[VEOL] = DEF_EOL; 514 #ifdef VSWTC 515 tp->c_cc[VSWTC] = DEF_SWITCH; /* default switch character */ 516 #endif 517 518 /* Account for special characters seen in input. */ 519 if (cp->eol == CR) { 520 tp->c_iflag |= ICRNL; /* map CR in input to NL */ 521 tp->c_oflag |= ONLCR; /* map NL in output to CR-NL */ 522 } 523 tp->c_cc[VERASE] = cp->erase; /* set erase character */ 524 tp->c_cc[VKILL] = cp->kill; /* set kill character */ 525 526 /* Account for the presence or absence of parity bits in input. */ 527 switch (cp->parity) { 528 case 0: /* space (always 0) parity */ 529 // I bet most people go here - they use only 7-bit chars in usernames.... 530 break; 531 case 1: /* odd parity */ 532 tp->c_cflag |= PARODD; 533 /* FALLTHROUGH */ 534 case 2: /* even parity */ 535 tp->c_cflag |= PARENB; 536 tp->c_iflag |= INPCK | ISTRIP; 537 /* FALLTHROUGH */ 538 case (1 | 2): /* no parity bit */ 539 tp->c_cflag &= ~CSIZE; 540 tp->c_cflag |= CS7; 541 // FIXME: wtf? case 3: we saw both even and odd 8-bit bytes - 542 // it's probably some umlauts etc, but definitely NOT 7-bit!!! 543 // Entire parity detection madness here just begs for deletion... 544 break; 545 } 546 547 /* Account for upper case without lower case. */ 548 #ifdef HANDLE_ALLCAPS 549 if (cp->capslock) { 550 tp->c_iflag |= IUCLC; 551 tp->c_lflag |= XCASE; 552 tp->c_oflag |= OLCUC; 553 } 554 #endif 555 /* Optionally enable hardware flow control */ 556 #ifdef CRTSCTS 557 if (op->flags & F_RTSCTS) 558 tp->c_cflag |= CRTSCTS; 559 #endif 560 561 /* Finally, make the new settings effective */ 562 if (tcsetattr_stdin_TCSANOW(tp) < 0) 563 bb_perror_msg_and_die("tcsetattr"); 509 } /* end of get char loop */ 510 got_logname: ; 511 } while (G.line_buf[0] == '\0'); /* while logname is empty */ 512 513 return G.line_buf; 514 } 515 516 static void alarm_handler(int sig UNUSED_PARAM) 517 { 518 finalize_tty_attrs(); 519 _exit(EXIT_SUCCESS); 564 520 } 565 521 … … 568 524 { 569 525 int n; 570 pid_t pid; 571 char *fakehost = NULL; /* Fake hostname for ut_host */ 572 char *logname; /* login name, given to /bin/login */ 573 /* Merging these into "struct local" may _seem_ to reduce 574 * parameter passing, but today's gcc will inline 575 * statics which are called once anyway, so don't do that */ 576 struct chardata chardata; /* set by get_logname() */ 577 struct termios termios; /* terminal mode bits */ 578 struct options options; 579 580 chardata = init_chardata; 581 582 memset(&options, 0, sizeof(options)); 583 options.login = _PATH_LOGIN; /* default login program */ 584 options.tty = "tty1"; /* default tty line */ 585 options.initstring = ""; /* modem init string */ 526 pid_t pid, tsid; 527 char *logname; 528 529 INIT_G(); 530 G.login = _PATH_LOGIN; /* default login program */ 586 531 #ifdef ISSUE 587 options.issue = ISSUE; /* default issue file */ 588 #endif 589 590 /* Parse command-line arguments. */ 591 parse_args(argv, &options, &fakehost); 592 593 logmode = LOGMODE_NONE; 594 595 /* Create new session, lose controlling tty, if any */ 596 /* docs/ctty.htm says: 597 * "This is allowed only when the current process 598 * is not a process group leader" - is this a problem? */ 599 setsid(); 600 /* close stdio, and stray descriptors, just in case */ 532 G.issue = ISSUE; /* default issue file */ 533 #endif 534 G.eol = '\r'; 535 536 /* Parse command-line arguments */ 537 parse_args(argv); 538 539 /* Create new session and pgrp, lose controlling tty */ 540 pid = setsid(); /* this also gives us our pid :) */ 541 if (pid < 0) { 542 int fd; 543 /* :( 544 * docs/ctty.htm says: 545 * "This is allowed only when the current process 546 * is not a process group leader". 547 * Thus, setsid() will fail if we _already_ are 548 * a session leader - which is quite possible for getty! 549 */ 550 pid = getpid(); 551 if (getsid(0) != pid) { 552 //for debugging: 553 //bb_perror_msg_and_die("setsid failed:" 554 // " pid %d ppid %d" 555 // " sid %d pgid %d", 556 // pid, getppid(), 557 // getsid(0), getpgid(0)); 558 bb_perror_msg_and_die("setsid"); 559 } 560 /* Looks like we are already a session leader. 561 * In this case (setsid failed) we may still have ctty, 562 * and it may be different from tty we need to control! 563 * If we still have ctty, on Linux ioctl(TIOCSCTTY) 564 * (which we are going to use a bit later) always fails - 565 * even if we try to take ctty which is already ours! 566 * Try to drop old ctty now to prevent that. 567 * Use O_NONBLOCK: old ctty may be a serial line. 568 */ 569 fd = open("/dev/tty", O_RDWR | O_NONBLOCK); 570 if (fd >= 0) { 571 /* TIOCNOTTY sends SIGHUP to the foreground 572 * process group - which may include us! 573 * Make sure to not die on it: 574 */ 575 sighandler_t old = signal(SIGHUP, SIG_IGN); 576 ioctl(fd, TIOCNOTTY); 577 close(fd); 578 signal(SIGHUP, old); 579 } 580 } 581 582 /* Close stdio, and stray descriptors, just in case */ 601 583 n = xopen(bb_dev_null, O_RDWR); 602 584 /* dup2(n, 0); - no, we need to handle "getty - 9600" too */ … … 622 604 623 605 /* Open the tty as standard input, if it is not "-" */ 624 /* If it's not "-" and not taken yet, it will become our ctty */625 606 debug("calling open_tty\n"); 626 open_tty( options.tty);627 ndelay_off( 0);607 open_tty(); 608 ndelay_off(STDIN_FILENO); 628 609 debug("duping\n"); 629 xdup2(0, 1); 630 xdup2(0, 2); 610 xdup2(STDIN_FILENO, 1); 611 xdup2(STDIN_FILENO, 2); 612 613 /* Steal ctty if we don't have it yet */ 614 tsid = tcgetsid(STDIN_FILENO); 615 if (tsid < 0 || pid != tsid) { 616 if (ioctl(STDIN_FILENO, TIOCSCTTY, /*force:*/ (long)1) < 0) 617 bb_perror_msg_and_die("TIOCSCTTY"); 618 } 619 620 #ifdef __linux__ 621 /* Make ourself a foreground process group within our session */ 622 if (tcsetpgrp(STDIN_FILENO, pid) < 0) 623 bb_perror_msg_and_die("tcsetpgrp"); 624 #endif 631 625 632 626 /* … … 638 632 * 5 seconds seems to be a good value. 639 633 */ 640 if (tcgetattr( 0, &termios) < 0)634 if (tcgetattr(STDIN_FILENO, &G.tty_attrs) < 0) 641 635 bb_perror_msg_and_die("tcgetattr"); 642 636 643 pid = getpid();644 #ifdef __linux__645 // FIXME: do we need this? Otherwise "-" case seems to be broken...646 // /* Forcibly make fd 0 our controlling tty, even if another session647 // * has it as a ctty. (Another session loses ctty). */648 // ioctl(0, TIOCSCTTY, (void*)1);649 /* Make ourself a foreground process group within our session */650 tcsetpgrp(0, pid);651 #endif652 653 637 /* Update the utmp file. This tty is ours now! */ 654 update_utmp(pid, LOGIN_PROCESS, options.tty, "LOGIN",fakehost);655 656 /* Initialize t he termios settings (raw mode, eight-bit, blocking i/o).*/657 debug("calling termios_init\n");658 termios_init(&termios, options.speeds[0], &options);638 update_utmp(pid, LOGIN_PROCESS, G.tty_name, "LOGIN", G.fakehost); 639 640 /* Initialize tty attrs (raw mode, eight-bit, blocking i/o) */ 641 debug("calling init_tty_attrs\n"); 642 init_tty_attrs(G.speeds[0]); 659 643 660 644 /* Write the modem init string and DON'T flush the buffers */ 661 if (option s.flags& F_INITSTRING) {645 if (option_mask32 & F_INITSTRING) { 662 646 debug("writing init string\n"); 663 full_write1_str( options.initstring);647 full_write1_str(G.initstring); 664 648 } 665 649 666 650 /* Optionally detect the baud rate from the modem status message */ 667 651 debug("before autobaud\n"); 668 if (option s.flags& F_PARSE)669 auto_baud( line_buf, sizeof(line_buf), &termios);652 if (option_mask32 & F_PARSE) 653 auto_baud(); 670 654 671 655 /* Set the optional timer */ 672 alarm(options.timeout); /* if 0, alarm is not set */ 656 signal(SIGALRM, alarm_handler); 657 alarm(G.timeout); /* if 0, alarm is not set */ 673 658 674 659 /* Optionally wait for CR or LF before writing /etc/issue */ 675 if (option s.flags& F_WAITCRLF) {660 if (option_mask32 & F_WAITCRLF) { 676 661 char ch; 677 678 662 debug("waiting for cr-lf\n"); 679 663 while (safe_read(STDIN_FILENO, &ch, 1) == 1) { 680 664 debug("read %x\n", (unsigned char)ch); 681 ch &= 0x7f; /* strip "parity bit" */682 665 if (ch == '\n' || ch == '\r') 683 666 break; … … 686 669 687 670 logname = NULL; 688 if (!(option s.flags& F_NOPROMPT)) {689 /* NB: termios_initalready set line speed690 * to options.speeds[0] */671 if (!(option_mask32 & F_NOPROMPT)) { 672 /* NB: init_tty_attrs already set line speed 673 * to G.speeds[0] */ 691 674 int baud_index = 0; 692 675 693 676 while (1) { 694 /* Read the login name .*/677 /* Read the login name */ 695 678 debug("reading login name\n"); 696 logname = get_logname(line_buf, sizeof(line_buf), 697 &options, &chardata); 679 logname = get_logname(); 698 680 if (logname) 699 681 break; 700 /* we are here only if options.numspeed > 1 */ 701 baud_index = (baud_index + 1) % options.numspeed; 702 cfsetispeed(&termios, options.speeds[baud_index]); 703 cfsetospeed(&termios, options.speeds[baud_index]); 704 tcsetattr_stdin_TCSANOW(&termios); 682 /* We are here only if G.numspeed > 1 */ 683 baud_index = (baud_index + 1) % G.numspeed; 684 cfsetspeed(&G.tty_attrs, G.speeds[baud_index]); 685 set_tty_attrs(); 705 686 } 706 687 } 707 688 708 /* Disable timer .*/689 /* Disable timer */ 709 690 alarm(0); 710 691 711 /* Finalize the termios settings. */ 712 termios_final(&options, &termios, &chardata); 713 714 /* Now the newline character should be properly written. */ 715 full_write(STDOUT_FILENO, "\n", 1); 716 717 /* Let the login program take care of password validation. */ 692 finalize_tty_attrs(); 693 694 /* Let the login program take care of password validation */ 718 695 /* We use PATH because we trust that root doesn't set "bad" PATH, 719 * and getty is not suid-root applet .*/696 * and getty is not suid-root applet */ 720 697 /* With -n, logname == NULL, and login will ask for username instead */ 721 BB_EXECLP( options.login, options.login, "--", logname, NULL);722 bb_error_msg_and_die("can't execute '%s'", options.login);723 } 698 BB_EXECLP(G.login, G.login, "--", logname, NULL); 699 bb_error_msg_and_die("can't execute '%s'", G.login); 700 } -
branches/3.2/mindi-busybox/loginutils/login.c
r2725 r3232 3 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 6 //usage:#define login_trivial_usage 7 //usage: "[-p] [-h HOST] [[-f] USER]" 8 //usage:#define login_full_usage "\n\n" 9 //usage: "Begin a new session on the system\n" 10 //usage: "\n -f Don't authenticate (user already authenticated)" 11 //usage: "\n -h Name of the remote host" 12 //usage: "\n -p Preserve environment" 13 5 14 #include "libbb.h" 6 15 #include <syslog.h> 7 #if ENABLE_FEATURE_UTMP8 # include <utmp.h> /* USER_PROCESS */9 #endif10 16 #include <sys/resource.h> 11 17 … … 32 38 TIMEOUT = 60, 33 39 EMPTY_USERNAME_COUNT = 10, 34 USERNAME_SIZE = 32, 40 /* Some users found 32 chars limit to be too low: */ 41 USERNAME_SIZE = 64, 35 42 TTYNAME_SIZE = 32, 36 43 }; 37 44 38 static char* short_tty; 45 struct globals { 46 struct termios tty_attrs; 47 } FIX_ALIASING; 48 #define G (*(struct globals*)&bb_common_bufsiz1) 49 #define INIT_G() do { } while (0) 50 39 51 40 52 #if ENABLE_FEATURE_NOLOGIN … … 69 81 70 82 #if ENABLE_FEATURE_SECURETTY && !ENABLE_PAM 71 static int check_securetty( void)83 static int check_securetty(const char *short_tty) 72 84 { 73 85 char *buf = (char*)"/etc/securetty"; /* any non-NULL is ok */ … … 84 96 } 85 97 #else 86 static ALWAYS_INLINE int check_securetty( void) { return 1; }98 static ALWAYS_INLINE int check_securetty(const char *short_tty UNUSED_PARAM) { return 1; } 87 99 #endif 88 100 … … 137 149 #endif 138 150 151 #if ENABLE_LOGIN_SESSION_AS_CHILD && ENABLE_PAM 152 static void login_pam_end(pam_handle_t *pamh) 153 { 154 int pamret; 155 156 pamret = pam_setcred(pamh, PAM_DELETE_CRED); 157 if (pamret != PAM_SUCCESS) { 158 bb_error_msg("pam_%s failed: %s (%d)", "setcred", 159 pam_strerror(pamh, pamret), pamret); 160 } 161 pamret = pam_close_session(pamh, 0); 162 if (pamret != PAM_SUCCESS) { 163 bb_error_msg("pam_%s failed: %s (%d)", "close_session", 164 pam_strerror(pamh, pamret), pamret); 165 } 166 pamret = pam_end(pamh, pamret); 167 if (pamret != PAM_SUCCESS) { 168 bb_error_msg("pam_%s failed: %s (%d)", "end", 169 pam_strerror(pamh, pamret), pamret); 170 } 171 } 172 #endif /* ENABLE_PAM */ 173 139 174 static void get_username_or_die(char *buf, int size_buf) 140 175 { … … 180 215 static void alarm_handler(int sig UNUSED_PARAM) 181 216 { 182 /* This is the escape hatch! 217 /* This is the escape hatch! Poor serial line users and the like 183 218 * arrive here when their connection is broken. 184 219 * We don't want to block here */ 185 ndelay_on(1); 186 printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT); 220 ndelay_on(STDOUT_FILENO); 221 /* Test for correct attr restoring: 222 * run "getty 0 -" from a shell, enter bogus username, stop at 223 * password prompt, let it time out. Without the tcsetattr below, 224 * when you are back at shell prompt, echo will be still off. 225 */ 226 tcsetattr_stdin_TCSANOW(&G.tty_attrs); 227 printf("\r\nLogin timed out after %u seconds\r\n", TIMEOUT); 187 228 fflush_all(); 188 229 /* unix API is brain damaged regarding O_NONBLOCK, 189 230 * we should undo it, or else we can affect other processes */ 190 ndelay_off( 1);231 ndelay_off(STDOUT_FILENO); 191 232 _exit(EXIT_SUCCESS); 192 233 } … … 202 243 char *fromhost; 203 244 char username[USERNAME_SIZE]; 204 const char *shell;205 245 int run_by_root; 206 246 unsigned opt; … … 210 250 char *opt_user = opt_user; /* for compiler */ 211 251 char *full_tty; 252 char *short_tty; 212 253 IF_SELINUX(security_context_t user_sid = NULL;) 213 254 #if ENABLE_PAM … … 218 259 struct passwd pwdstruct; 219 260 char pwdbuf[256]; 220 #endif 221 222 username[0] = '\0'; 223 signal(SIGALRM, alarm_handler); 224 alarm(TIMEOUT); 261 char **pamenv; 262 #endif 263 #if ENABLE_LOGIN_SESSION_AS_CHILD 264 pid_t child_pid; 265 #endif 266 267 INIT_G(); 225 268 226 269 /* More of suid paranoia if called by non-root: */ … … 234 277 bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE | DAEMON_CLOSE_EXTRA_FDS, NULL); 235 278 279 username[0] = '\0'; 236 280 opt = getopt32(argv, "f:h:p", &opt_user, &opt_host); 237 281 if (opt & LOGIN_OPT_f) { … … 244 288 safe_strncpy(username, argv[0], sizeof(username)); 245 289 246 /* Let's find out and memorize our tty */ 247 if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) 290 /* Save tty attributes - and by doing it, check that it's indeed a tty */ 291 if (tcgetattr(STDIN_FILENO, &G.tty_attrs) < 0 292 || !isatty(STDOUT_FILENO) 293 /*|| !isatty(STDERR_FILENO) - no, guess some people might want to redirect this */ 294 ) { 248 295 return EXIT_FAILURE; /* Must be a terminal */ 296 } 297 298 /* We install timeout handler only _after_ we saved G.tty_attrs */ 299 signal(SIGALRM, alarm_handler); 300 alarm(TIMEOUT); 301 302 /* Find out and memorize our tty name */ 249 303 full_tty = xmalloc_ttyname(STDIN_FILENO); 250 304 if (!full_tty) … … 282 336 goto pam_auth_failed; 283 337 } 284 pamret = pam_authenticate(pamh, 0); 285 if (pamret != PAM_SUCCESS) { 286 failed_msg = "authenticate"; 287 goto pam_auth_failed; 288 /* TODO: or just "goto auth_failed" 289 * since user seems to enter wrong password 290 * (in this case pamret == 7) 291 */ 338 /* set RHOST */ 339 if (opt_host) { 340 pamret = pam_set_item(pamh, PAM_RHOST, opt_host); 341 if (pamret != PAM_SUCCESS) { 342 failed_msg = "set_item(RHOST)"; 343 goto pam_auth_failed; 344 } 345 } 346 if (!(opt & LOGIN_OPT_f)) { 347 pamret = pam_authenticate(pamh, 0); 348 if (pamret != PAM_SUCCESS) { 349 failed_msg = "authenticate"; 350 goto pam_auth_failed; 351 /* TODO: or just "goto auth_failed" 352 * since user seems to enter wrong password 353 * (in this case pamret == 7) 354 */ 355 } 292 356 } 293 357 /* check that the account is healthy */ … … 346 410 break; /* -f USER: success without asking passwd */ 347 411 348 if (pw->pw_uid == 0 && !check_securetty( ))412 if (pw->pw_uid == 0 && !check_securetty(short_tty)) 349 413 goto auth_failed; 350 414 … … 353 417 break; 354 418 fake_it: 355 /* authorization takes place here */ 419 /* Password reading and authorization takes place here. 420 * Note that reads (in no-echo mode) trash tty attributes. 421 * If we get interrupted by SIGALRM, we need to restore attrs. 422 */ 356 423 if (correct_password(pw)) 357 424 break; … … 359 426 auth_failed: 360 427 opt &= ~LOGIN_OPT_f; 361 bb_do_delay( FAIL_DELAY);428 bb_do_delay(LOGIN_FAIL_DELAY); 362 429 /* TODO: doesn't sound like correct English phrase to me */ 363 430 puts("Login incorrect"); … … 380 447 die_if_nologin(); 381 448 382 IF_SELINUX(initselinux(username, full_tty, &user_sid)); 449 #if ENABLE_LOGIN_SESSION_AS_CHILD 450 child_pid = vfork(); 451 if (child_pid != 0) { 452 if (child_pid < 0) 453 bb_perror_msg("vfork"); 454 else { 455 if (safe_waitpid(child_pid, NULL, 0) == -1) 456 bb_perror_msg("waitpid"); 457 update_utmp(child_pid, DEAD_PROCESS, NULL, NULL, NULL); 458 } 459 IF_PAM(login_pam_end(pamh);) 460 return 0; 461 } 462 #endif 463 464 IF_SELINUX(initselinux(username, full_tty, &user_sid);) 383 465 384 466 /* Try these, but don't complain if they fail. … … 394 476 395 477 change_identity(pw); 396 shell = pw->pw_shell; 397 if (!shell || !shell[0]) 398 shell = DEFAULT_SHELL; 399 setup_environment(shell, 478 setup_environment(pw->pw_shell, 400 479 (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV, 401 480 pw); 481 482 #if ENABLE_PAM 483 /* Modules such as pam_env will setup the PAM environment, 484 * which should be copied into the new environment. */ 485 pamenv = pam_getenvlist(pamh); 486 if (pamenv) while (*pamenv) { 487 putenv(*pamenv); 488 pamenv++; 489 } 490 #endif 402 491 403 492 motd(); … … 435 524 436 525 /* Exec login shell with no additional parameters */ 437 run_shell( shell, 1, NULL, NULL);526 run_shell(pw->pw_shell, 1, NULL, NULL); 438 527 439 528 /* return EXIT_FAILURE; - not reached */ -
branches/3.2/mindi-busybox/loginutils/passwd.c
r2725 r3232 3 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 6 //usage:#define passwd_trivial_usage 7 //usage: "[OPTIONS] [USER]" 8 //usage:#define passwd_full_usage "\n\n" 9 //usage: "Change USER's password (default: current user)" 10 //usage: "\n" 11 //usage: "\n -a ALG Encryption method" 12 //usage: "\n -d Set password to ''" 13 //usage: "\n -l Lock (disable) account" 14 //usage: "\n -u Unlock (enable) account" 15 5 16 #include "libbb.h" 6 17 #include <syslog.h> 18 #include <sys/resource.h> /* setrlimit */ 7 19 8 20 static void nuke_str(char *str) … … 11 23 } 12 24 13 static char* new_password(const struct passwd *pw, uid_t myuid, intalgo)25 static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo) 14 26 { 15 char salt[ sizeof("$N$XXXXXXXX")]; /* "$N$XXXXXXXX" or "XX" */27 char salt[MAX_PW_SALT_LEN]; 16 28 char *orig = (char*)""; 17 29 char *newp = NULL; … … 19 31 char *ret = NULL; /* failure so far */ 20 32 21 if (myuid && pw->pw_passwd[0]) {33 if (myuid != 0 && pw->pw_passwd[0]) { 22 34 char *encrypted; 23 35 … … 27 39 encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */ 28 40 if (strcmp(encrypted, pw->pw_passwd) != 0) { 29 syslog(LOG_WARNING, "incorrect password for %s", 30 pw->pw_name); 31 bb_do_delay(FAIL_DELAY); 41 syslog(LOG_WARNING, "incorrect password for %s", pw->pw_name); 42 bb_do_delay(LOGIN_FAIL_DELAY); 32 43 puts("Incorrect password"); 33 44 goto err_ret; 34 45 } 35 if (ENABLE_FEATURE_CLEAN_UP) free(encrypted); 46 if (ENABLE_FEATURE_CLEAN_UP) 47 free(encrypted); 36 48 } 37 49 orig = xstrdup(orig); /* or else bb_ask_stdin() will destroy it */ … … 41 53 newp = xstrdup(newp); /* we are going to bb_ask_stdin() again, so save it */ 42 54 if (ENABLE_FEATURE_PASSWD_WEAK_CHECK 43 && obscure(orig, newp, pw) && myuid) 55 && obscure(orig, newp, pw) 56 && myuid != 0 57 ) { 44 58 goto err_ret; /* non-root is not allowed to have weak passwd */ 59 } 45 60 46 61 cp = bb_ask_stdin("Retype password: "); 47 62 if (!cp) 48 63 goto err_ret; 49 if (strcmp(cp, newp) ) {64 if (strcmp(cp, newp) != 0) { 50 65 puts("Passwords don't match"); 51 66 goto err_ret; 52 67 } 53 68 54 crypt_make_salt(salt, 1, 0); /* des */ 55 if (algo) { /* MD5 */ 56 strcpy(salt, "$1$"); 57 crypt_make_salt(salt + 3, 4, 0); 58 } 69 crypt_make_pw_salt(salt, algo); 70 59 71 /* pw_encrypt returns malloced str */ 60 72 ret = pw_encrypt(newp, salt, 1); … … 64 76 nuke_str(orig); 65 77 if (ENABLE_FEATURE_CLEAN_UP) free(orig); 78 66 79 nuke_str(newp); 67 80 if (ENABLE_FEATURE_CLEAN_UP) free(newp); 81 68 82 nuke_str(cp); 69 83 return ret; … … 74 88 { 75 89 enum { 76 OPT_algo = 0x1, /* -a - password algorithm */ 77 OPT_lock = 0x2, /* -l - lock account */ 78 OPT_unlock = 0x4, /* -u - unlock account */ 79 OPT_delete = 0x8, /* -d - delete password */ 80 OPT_lud = 0xe, 81 STATE_ALGO_md5 = 0x10, 82 //STATE_ALGO_des = 0x20, not needed yet 90 OPT_algo = (1 << 0), /* -a - password algorithm */ 91 OPT_lock = (1 << 1), /* -l - lock account */ 92 OPT_unlock = (1 << 2), /* -u - unlock account */ 93 OPT_delete = (1 << 3), /* -d - delete password */ 94 OPT_lud = OPT_lock | OPT_unlock | OPT_delete, 83 95 }; 84 96 unsigned opt; 85 97 int rc; 86 const char *opt_a = "";98 const char *opt_a = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO; 87 99 const char *filename; 88 100 char *myname; … … 105 117 argv += optind; 106 118 107 if (strcasecmp(opt_a, "des") != 0) /* -a */108 opt |= STATE_ALGO_md5;109 //else110 // opt |= STATE_ALGO_des;111 119 myuid = getuid(); 112 120 /* -l, -u, -d require root priv and username argument */ 113 if ((opt & OPT_lud) && (myuid || !argv[0]))121 if ((opt & OPT_lud) && (myuid != 0 || !argv[0])) 114 122 bb_show_usage(); 115 123 … … 119 127 120 128 pw = xgetpwnam(name); 121 if (myuid && pw->pw_uid != myuid) {129 if (myuid != 0 && pw->pw_uid != myuid) { 122 130 /* LOGMODE_BOTH */ 123 131 bb_error_msg_and_die("%s can't change password for %s", myname, name); … … 153 161 c = pw->pw_passwd[0] - '!'; 154 162 if (!(opt & OPT_lud)) { 155 if (myuid && !c) { /* passwd starts with '!' */163 if (myuid != 0 && !c) { /* passwd starts with '!' */ 156 164 /* LOGMODE_BOTH */ 157 165 bb_error_msg_and_die("can't change " … … 159 167 } 160 168 printf("Changing password for %s\n", name); 161 newp = new_password(pw, myuid, opt & STATE_ALGO_md5);169 newp = new_password(pw, myuid, opt_a); 162 170 if (!newp) { 163 171 logmode = LOGMODE_STDIO; … … 165 173 } 166 174 } else if (opt & OPT_lock) { 167 if (!c) goto skip; /* passwd starts with '!' */ 175 if (!c) 176 goto skip; /* passwd starts with '!' */ 168 177 newp = xasprintf("!%s", pw->pw_passwd); 169 178 } else if (opt & OPT_unlock) { 170 if (c) goto skip; /* not '!' */ 179 if (c) 180 goto skip; /* not '!' */ 171 181 /* pw->pw_passwd points to static storage, 172 182 * strdup'ing to avoid nasty surprizes */ 173 183 newp = xstrdup(&pw->pw_passwd[1]); 174 184 } else if (opt & OPT_delete) { 175 //newp = xstrdup("");176 185 newp = (char*)""; 177 186 } … … 190 199 filename = bb_path_shadow_file; 191 200 rc = update_passwd(bb_path_shadow_file, name, newp, NULL); 192 if (rc == 0) /* no lines updated, no errors detected */ 201 if (rc > 0) 202 /* password in /etc/shadow was updated */ 203 newp = (char*) "x"; 204 if (rc >= 0) 205 /* 0 = /etc/shadow missing (not an error), >0 = passwd changed in /etc/shadow */ 193 206 #endif 194 207 { … … 198 211 /* LOGMODE_BOTH */ 199 212 if (rc < 0) 200 bb_error_msg_and_die("can't update password file %s", 201 filename); 213 bb_error_msg_and_die("can't update password file %s", filename); 202 214 bb_info_msg("Password for %s changed by %s", name, myname); 203 215 204 / /if (ENABLE_FEATURE_CLEAN_UP) free(newp);216 /*if (ENABLE_FEATURE_CLEAN_UP) free(newp); - can't, it may be non-malloced */ 205 217 skip: 206 218 if (!newp) { … … 208 220 name, (opt & OPT_unlock) ? "un" : ""); 209 221 } 210 if (ENABLE_FEATURE_CLEAN_UP) free(myname); 222 223 if (ENABLE_FEATURE_CLEAN_UP) 224 free(myname); 211 225 return 0; 212 226 } -
branches/3.2/mindi-busybox/loginutils/su.c
r2725 r3232 8 8 #include "libbb.h" 9 9 #include <syslog.h> 10 11 //usage:#define su_trivial_usage 12 //usage: "[OPTIONS] [-] [USER]" 13 //usage:#define su_full_usage "\n\n" 14 //usage: "Run shell under USER (by default, root)\n" 15 //usage: "\n -,-l Clear environment, run shell as login shell" 16 //usage: "\n -p,-m Do not set new $HOME, $SHELL, $USER, $LOGNAME" 17 //usage: "\n -c CMD Command to pass to 'sh -c'" 18 //usage: "\n -s SH Shell to use instead of user's default" 10 19 11 20 #if ENABLE_FEATURE_SU_CHECKS_SHELLS … … 43 52 uid_t cur_uid = getuid(); 44 53 const char *tty; 54 #if ENABLE_FEATURE_UTMP 45 55 char user_buf[64]; 56 #endif 46 57 const char *old_user; 47 58 … … 103 114 } 104 115 105 /* Make sure pw->pw_shell is non-NULL. It may be NULL when NEW_USER106 * is a username that is retrieved via NIS (YP), that doesn't have107 * a default shell listed. */108 if (!pw->pw_shell || !pw->pw_shell[0])109 pw->pw_shell = (char *)DEFAULT_SHELL;110 111 116 #if ENABLE_FEATURE_SU_CHECKS_SHELLS 112 if (opt_shell && cur_uid != 0 && restricted_shell(pw->pw_shell)) {117 if (opt_shell && cur_uid != 0 && pw->pw_shell && restricted_shell(pw->pw_shell)) { 113 118 /* The user being su'd to has a nonstandard shell, and so is 114 119 * probably a uucp account or has restricted access. Don't … … 116 121 * shell. */ 117 122 bb_error_msg("using restricted shell"); 118 opt_shell = NULL; 123 opt_shell = NULL; /* ignore -s PROG */ 119 124 } 120 125 /* else: user can run whatever he wants via "su -s PROG USER". … … 127 132 setup_environment(opt_shell, 128 133 ((flags & SU_OPT_l) / SU_OPT_l * SETUP_ENV_CLEARENV) 129 + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV), 134 + (!(flags & SU_OPT_mp) * SETUP_ENV_CHANGEENV) 135 + (!(flags & SU_OPT_l) * SETUP_ENV_NO_CHDIR), 130 136 pw); 131 137 IF_SELINUX(set_current_security_context(NULL);) -
branches/3.2/mindi-busybox/loginutils/sulogin.c
r2725 r3232 5 5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 6 */ 7 8 //usage:#define sulogin_trivial_usage 9 //usage: "[-t N] [TTY]" 10 //usage:#define sulogin_full_usage "\n\n" 11 //usage: "Single user login\n" 12 //usage: "\n -t N Timeout" 7 13 8 14 #include "libbb.h" … … 89 95 break; 90 96 } 91 bb_do_delay( FAIL_DELAY);92 bb_ error_msg("login incorrect");97 bb_do_delay(LOGIN_FAIL_DELAY); 98 bb_info_msg("Login incorrect"); 93 99 } 94 100 memset(cp, 0, strlen(cp)); -
branches/3.2/mindi-busybox/loginutils/vlock.c
r2725 r3232 15 15 /* Fixed by Erik Andersen to do passwords the tinylogin way... 16 16 * It now works with md5, sha1, etc passwords. */ 17 18 //usage:#define vlock_trivial_usage 19 //usage: "[-a]" 20 //usage:#define vlock_full_usage "\n\n" 21 //usage: "Lock a virtual terminal. A password is required to unlock.\n" 22 //usage: "\n -a Lock all VTs" 17 23 18 24 #include "libbb.h" … … 94 100 tcsetattr_stdin_TCSANOW(&term); 95 101 96 do{102 while (1) { 97 103 printf("Virtual console%s locked by %s.\n", 98 option_mask32 /*o_lock_all*/ ? "s" : "", 99 pw->pw_name); 104 /* "s" if -a, else "": */ "s" + !option_mask32, 105 pw->pw_name 106 ); 100 107 if (correct_password(pw)) { 101 108 break; 102 109 } 103 bb_do_delay( FAIL_DELAY);104 puts(" Password incorrect");105 } while (1);110 bb_do_delay(LOGIN_FAIL_DELAY); 111 puts("Incorrect password"); 112 } 106 113 107 114 #ifdef __linux__
Note:
See TracChangeset
for help on using the changeset viewer.