终端开启telnetd服务器功能,当客户端登录telnetd服务器时,服务器的处理流程如下
1. telnetd_main()启动
#define G (*(struct globals*)&bb_common_bufsiz1)
#define INIT_G() do { \
G.loginpath = "/bin/login"; \
G.issuefile = "/etc/issue.net"; \
} while (0)
int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int telnetd_main(int argc UNUSED_PARAM, char **argv)
{
...
INIT_G();
...
G.sessions = make_new_session(); //新建一个新的登录会话
...
}
2. 创建一个新的登录会话
static struct tsession *
make_new_session(
IF_FEATURE_TELNETD_STANDALONE(int sock)
IF_NOT_FEATURE_TELNETD_STANDALONE(void)
)
{
...
/* Exec shell / login / whatever */
login_argv[0] = G.loginpath;
login_argv[1] = NULL;
/* exec busybox applet (if PREFER_APPLETS=y), if that fails,
* exec external program.
* NB: sock is either 0 or has CLOEXEC set on it.
* fd has CLOEXEC set on it too. These two fds will be closed here.
*/
BB_EXECVP(G.loginpath, (char **)login_argv); //启动一个新的工具,这里为“/bin/login”
...
}
#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
这里最通过exec()函数集,启动/bin/login登录程序!
3. login_main()启动
int login_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int login_main(int argc UNUSED_PARAM, char **argv)
{
...
signal(SIGALRM, alarm_handler); //绑定登录超时处理函数
alarm(TIMEOUT);
...
//获取登录的用户名,在远程登录显示的信息“arm login: ”
get_username_or_die(username, sizeof(username));
...
//通过用户名获取根文件下/etc/passward,如root在/etc/passward对应的为:
//root:$1$zKf1FCKT$WjEYAfuWHKkVYICBYJvD1/:11456:0:99999:7:::
//最终将该信息返回到pw
pw = getpwnam(username);
...
if (ask_and_check_password(pw) > 0) //校验密码
...
//熟悉的接口,这里将启动从/etc/passward中获取的/bin/sh,哈哈 o(∩_∩)o 哈哈
run_shell(pw->pw_shell, 1, NULL, NULL);
...
}
最终通过“run_shell(pw->pw_shell, 1, NULL, NULL);”启动一个新的/bin/sh shell环境 ,又见/bin/sh,关于/bin/sh源码分析待续...
本文详细解析了telnetd服务器的登录处理流程,包括telnetd_main()启动、创建新的登录会话、以及login_main()启动过程,深入探讨了如何通过exec()函数启动/bin/login登录程序,最后启动/bin/sh shell环境。
1411

被折叠的 条评论
为什么被折叠?



