Linux系统裁减之,制作一个极度精简的Linux-5-重新编译login去除对pam模块的依赖...
第5章 重新编译login去除对pam模块的依赖
在阅读这篇博文之前,建议先阅读我的前4篇博文,而且最好按顺序阅读:(不然可能会觉得我写得不知所云,呵呵!)
第1篇:Linux系统裁减之,制作一个极度精简的Linux-1 https://blog.51cto.com/linuxprince/2045703
第2篇:Linux系统裁减之,制作一个极度精简的Linux-2-用脚本实现自动拷贝命令和依赖库文件 https://blog.51cto.com/linuxprince/2046142
第3篇:Linux系统裁减之,制作一个极度精简的Linux-3-为精简的系统增加网络功能和关机重启功能 https://blog.51cto.com/linuxprince/2047373
第4篇:Linux系统裁减之,制作一个极度精简的Linux-4-使用mingetty绕开/bin/login https://blog.51cto.com/linuxprince/2049081
5.1 下载login程序源代码
之前我在第4篇博文已经写过下载 login 程序源代码的方法,这篇文章省略。我把源码放在/root/Softwares/Source目录。
[root@CentOS5lsrv01 ~]# ll Softwares/Source/
total 2892
-rw-r--r-- 1 root root 19624 Apr 9 2007 mingetty-1.07-5.2.2.src.rpm
-rw-r--r-- 1 root root 2933601 Nov 9 2012 util-linux-2.13-0.59.el5_8.src.rpm
提示:login的源代码都放在包 util-linux-2.13-0.59.el5_8.src.rpm 中
5.2 安装并重新编译 login 源码
第1步:安装 util-linux-2.13-0.59.el5_8.src.rpm 包
[root@CentOS5lsrv01 Source]# rpm -ivh util-linux-2.13-0.59.el5_8.src.rpm
[root@CentOS5lsrv01 SOURCES]# cd /usr/src/redhat/SOURCES/ ß进入红帽源码包的安装目录
[root@CentOS5lsrv01 SOURCES]# ll | grep util-linux-2.13-pre7.tar.bz2 ßlogin所在的源码包
-rw-rw-r-- 1 root root 2534328 Mar 29 2006 util-linux-2.13-pre7.tar.bz2
第2步:解压 util-linux-2.13-pre7.tar.bz2 包并进入包“util-linux-2.13-pre7”目录
[root@CentOS5lsrv01 SOURCES]# tar xf util-linux-2.13-pre7.tar.bz2 <--解压
[root@CentOS5lsrv01 SOURCES]# cd util-linux-2.13-pre7 <--进入源码目录
特别提示:按照以下”错误的第3步“的方法编译login程序是不行的(我之前使用这种方法编译),登陆时会提示“Login incorrect”,意思是密码错误(哪怕是你输入的密码完全正确),在错误的“第3步”后有正确的编译方法,保证能成功。
**********错误的第3步开始**********
第3步:重新编译 login 程序
并设置好预备编译参数(去除对pam模块的依赖)
[root@CentOS5lsrv01 util-linux-2.13-pre7]# ./configure --without-pam <--设置预编译参数,去除对pam模块的依赖
注意:使用本文的方法编译login程序,可以不添加参数“--without-pam”,下面的内容将会说明原因。
[root@CentOS5lsrv01 util-linux-2.13-pre7]# cd login-utils/ <--预编译成功后进入login程序的源码目录
重点提示:编译前先要修改login.c 源码文件,添加头文件locale.h,不加的话编译会报错:
[root@CentOS5lsrv01 login-utils]# gcc -o login login.c ../lib/setproctitle.c checktty.c -Wall -lcrypt -I ../include/
login.c: In function ‘main’:
login.c:327: warning: implicit declaration of function ‘setlocale’
login.c:327: error: ‘LC_ALL’ undeclared (first use in this function)
login.c:327: error: (Each undeclared identifier is reported only once
login.c:327: error: for each function it appears in.)
login.c:843: warning: passing argument 1 of ‘gettimeofday’ from incompatible pointer type
login.c: In function ‘dolastlog’:
login.c:1302: warning: passing argument 1 of ‘time’ from incompatible pointer type
打开login.c源代码文件:
[root@CentOS5lsrv01 login-utils]# vi login.c
115 #include <sys/sysmacros.h>
116 #include <linux/major.h>
117
118 #include <utmp.h>
119
120 #include <locale.h> <--添加locale.h头文件
121
122 #ifdef HAVE_SECURITY_PAM_MISC_H
123 # include <security/pam_appl.h>
124 # include <security/pam_misc.h>
125 # define PAM_MAX_LOGIN_TRIES 3
由于login程序没有make文件,所以需要自己写编译命令:
[root@CentOS5lsrv01 login-utils]# gcc -o login login.c ../lib/setproctitle.c checktty.c -Wall -lcrypt -I ../include/
login.c: In function ‘main’:
login.c:842: warning: passing argument 1 of ‘gettimeofday’ from incompatible pointer type
login.c: In function ‘dolastlog’:
login.c:1301: warning: passing argument 1 of ‘time’ from incompatible pointer type
[root@CentOS5lsrv01 login-utils]# ll | grep login
-rwxr-xr-x 1 root root 36746 Dec 9 14:58 login <--生成了login二进制文件
-rw-r--r-- 1 1000 1000 10481 Aug 2 2005 login.1
-rw-r--r-- 1 1000 1000 34478 Dec 2 06:36 login.c
-rw-r--r-- 1 1000 1000 247 Aug 2 2005 login.h
[root@CentOS5lsrv01 login-utils]# file login
login: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), not stripped <--二进制可执行文件login
**********错误的第3步结束**********
**********正确的第3步开始**********
第3步:重新编译login程序(需要稍微修改一下源代码)
进入包“util-linux-2.13-pre7”解压后的目录并设置预编译参数
[root@CentOS5lsrv01 ~]# cd /usr/src/redhat/SOURCES/util-linux-2.13-pre7
[root@CentOS5lsrv01 util-linux-2.13-pre7]# ./configure --enable-login-utils --without-selinux
参数解释:
--enable-login-utils build chfn, chsh, login, newgrp, vipw
意思是编译util-linux-2.13-pre7时生成chfn,chsh,login,newgrp,vipw几个二进制可执行文件。
--without-selinux compile login-utils without SELinux support
意思是编译util-linux-2.13-pre7时不提供对 SELinux 的支持,本文生成的miniLinux系统没有SELinux,若不加此参数,编译会报如下错误:
chfn.c:44:29: error: selinux/selinux.h: No such file or directory
chfn.c:45:36: error: selinux/av_permissions.h: No such file or directory
chfn.c: In function ‘main’:
chfn.c:148: error: ‘PASSWD__CHFN’ undeclared (first use in this function)
chfn.c:148: error: (Each undeclared identifier is reported only once
chfn.c:148: error: for each function it appears in.)
chfn.c:149: error: ‘security_context_t’ undeclared (first use in this function)
chfn.c:149: error: expected ‘;’ before ‘user_context’
chfn.c:150: error: ‘user_context’ undeclared (first use in this function)
make[2]: *** [chfn.o] Error 1
make[2]: Leaving directory `/usr/src/redhat/SOURCES/util-linux-2.13-pre7/login-utils'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/src/redhat/SOURCES/util-linux-2.13-pre7'
make: *** [all] Error 2
下面先进入login-utils目录修改login程序的源代码文件"login.c",我这里只取出这篇文章最重要的部分源代码做一些摘要解释:
[root@CentOS5lsrv01 util-linux-2.13-pre7]# cd login-utils/
[root@CentOS5lsrv01 login-utils]# vi login.c
117 #include <utmp.h>118 #include <shadow.h> //添加头文件“shadow.h”,下面的结构体“spwd”定义在该文件//此处省略119行到651行的代码652 if ((pwd = getpwnam(username))) { //获取用户输入的用户名,如果用户名能在文件// /etc/passwd中找到,则执行下面的代码//653行到658行的意思是如果宏“SHADOW_PWD”定义了,则654行到657行的代码会被编译,宏“SHADOW_PWD”//应该是定义在某个头文件中,但本文使用的方法并没有使用相应的头文件。login程序的源码大量使用了类//似的条件编译代码,或者我找个时间详细了解下条件编译中的宏定义在哪些文件吧!!这里就暂不纠结了!653 // # ifdef SHADOW_PWD <--把这行注释掉。654 struct spwd *sp;//定义一个结构体指针,用于对应/etc/shadow文件的数据结构655 656 if ((sp = getspnam(username)))//根据用户输入的用户名,如果在/etc/shadow//文件中查找到,则执行下面的代码657 pwd->pw_passwd = sp->sp_pwdp;//把从/etc/shadow文件中取出的密码加密密文//赋值给pwd->pw_passwd658 // # endif <--把这行注释掉659 salt = pwd->pw_passwd;660 } else661 salt = "xx";662663 if (pwd) {664 initgroups(username, pwd->pw_gid);665 checktty(username, tty_name, pwd); /* in checktty.c */666 }667668 /* if user not super-user, check for disabled logins */669 if (pwd == NULL || pwd->pw_uid)670 checknologin();671672 /*673 * Disallow automatic login to root; if not invoked by674 * root, disallow if the uid's differ.675 */676 if (fflag && pwd) {677 int uid = getuid();678 679 passwd_req = pwd->pw_uid == 0 ||680 (uid && uid != pwd->pw_uid);681 }682683 /*684 * If trying to log in as root, but with insecure terminal,685 * refuse the login attempt.686 */687 if (pwd && pwd->pw_uid == 0 && !rootterm(tty_name)) {688 fprintf(stderr,689 _("%s login refused on this terminal.\n"),690 pwd->pw_name);691 692 if (hostname)693 syslog(LOG_NOTICE,694 _("LOGIN %s REFUSED FROM %s ON TTY %s"),695 pwd->pw_name, hostname, tty_name);696 else697 syslog(LOG_NOTICE,698 _("LOGIN %s REFUSED ON TTY %s"),699 pwd->pw_name, tty_name);700 continue;701 }702703 /*704 * If no pre-authentication and a password exists705 * for this user, prompt for one and verify it.706 */707 if (!passwd_req || (pwd && !*pwd->pw_passwd))708 break;709710 setpriority(PRIO_PROCESS, 0, -4);711 pp = getpass(_("Password: ")); //获取屏幕输入的密码赋值给变量 pp712713 # ifdef CRYPTOCARD714 if (strncmp(pp, "CRYPTO", 6) == 0) {715 if (pwd && cryptocard()) break;716 }717 # endif /* CRYPTOCARD */718719 p = crypt(pp, salt);//对用户通过屏幕输入的密码进行加密720 setpriority(PRIO_PROCESS, 0, 0);721//省略722到745行,都是关于KERBEROS认证方式的746 memset(pp, 0, strlen(pp));//出于安全的考虑,获取了用户输入密码并加密后清空747 //明文密码所在的内存区748 if (pwd && !strcmp(p, pwd->pw_passwd))//对比用户输入的密码与/etc/shadow文749 break; //件中记录的密码,如果匹配,就退出循环,//表示认证成功,用户可以登陆啦!!
到此修改完成,保存退出,返回util-linux-2.13-pre7目录,直接编译:
[root@CentOS5lsrv01 ~]# cd /usr/src/redhat/SOURCES/util-linux-2.13-pre7
[root@CentOS5lsrv01 util-linux-2.13-pre7]# make
如果编译没有出错,就会看到 login-utils/目录下已经生成了login 二进制可执行文件
[root@CentOS5lsrv01 util-linux-2.13-pre7]# cd login-utils/
[root@CentOS5lsrv01 login-utils]# ll | grep login
-rwxr-xr-x 1 root root 68321 Jan 5 14:01 login <--生成了 login 二进制可执行文件
-rw-r--r-- 1 1000 1000 10481 Aug 2 2005 login.1
-rw-r--r-- 1 1000 1000 34701 Jan 5 14:01 login.c
-rw-r--r-- 1 root root 34458 Jan 4 23:31 login.c.bak
-rw-r--r-- 1 1000 1000 247 Aug 2 2005 login.h
-rw-r--r-- 1 root root 51992 Jan 5 14:01 login.o
**********正确的第3步结束**********
第4步:重新拷贝 mingetty 程序到miniLinux系统
之前的测试中,miniLinux 系统使用了重新编译过的 mingetty 程序,这一步把它替换成红帽官方系统的 mingetty 程序,从源系统(CentOS5lsrv01)重新拷贝到miniLinux系统:
[root@CentOS5lsrv01 ~]# rm -f /mnt/sysroot/sbin/mingetty <--删除编译过的mingetty
[root@CentOS5lsrv01 ~]# ./bincp.sh <--重新拷贝源系统的mingetty程序到miniLinux系统
Input command what you want to copy to miniLinux:mingetty
Copy /sbin/mingetty Finished.
Continue input command to miniLinux:q
[root@CentOS5lsrv01 ~]#
第5步:把编译好的 login 程序拷贝到miniLinux系统
[root@CentOS5lsrv01 ~]# ldd /bin/login <--login程序有很多依赖的库文件呢!!
linux-vdso.so.1 => (0x00007fff695fd000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x0000003979c00000)
libpam.so.0 => /lib64/libpam.so.0 (0x000000397c800000)
libpam_misc.so.0 => /lib64/libpam_misc.so.0 (0x000000397a400000)
libaudit.so.0 => /lib64/libaudit.so.0 (0x000000397a000000)
libc.so.6 => /lib64/libc.so.6 (0x0000003977400000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003977800000)
/lib64/ld-linux-x86-64.so.2 (0x0000003977000000)
[root@CentOS5lsrv01 ~]# ./bincp.sh <--先拷贝源系统的login程序,下面再覆盖,偷懒嘛!!
Input command what you want to copy to miniLinux:login
Copy lib file /lib64/libcrypt.so.1 Finished.
Copy lib file /lib64/libpam.so.0 Finished. <--注意,这里拷贝了两个关于 pam 的库,其实是不需要的,已经重新编译login
Copy lib file /lib64/libpam_misc.so.0 Finished. <--去除了对 pam 模块的依赖,可以删除,看来还是不能偷懒了,呵呵!!
Copy lib file /lib64/libaudit.so.0 Finished.
Copy /bin/login Finished.
Continue input command to miniLinux:q
为miniLinux系统删除多余的 libpam.so.0 和 libpam_misc.so.0 文件:
[root@CentOS5lsrv01 ~]# rm -f /mnt/sysroot/lib64/libpam.so.0
[root@CentOS5lsrv01 ~]# rm -f /mnt/sysroot/lib64/libpam_misc.so.0
把编译好的login程序覆盖过去:
[root@CentOS5lsrv01 ~]# cp -f /usr/src/redhat/SOURCES/util-linux-2.13-pre7/login-utils/login /mnt/sysroot/bin/
cp: overwrite `/mnt/sysroot/bin/login'? y
[root@CentOS5lsrv01 ~]#
提示:第4步和第5步中使用的 bincp.sh 脚本是我编写的用于自动移植命令和命令依赖的库文件到 miniLinux 系统,详细可以查看我之前发布的第3篇博文:Linux系统裁减之,制作一个极度精简的Linux-3-为精简的系统增加网络功能和关机重启功能 https://blog.51cto.com/linuxprince/2047373,里面有bincp.sh的完整程序。
5.3 拷贝 nsswitch 的库文件到 minLinux 系统
nsswitch简介:
nsswitch全称为: network service switch(网络服务转换),是一个通用框架,与各种类型存储交互的公共实现,实现名称解析服务。例如:用户名到ID,或者ID到用户名,再或者IP到域名的查找方式。nsswitch 加载了各存储的 API 接口,并以模块方式装载进 nsswitch 中,当程序发起对 nsswitch 的 API调用时,nsswitch 会自动完成到各种存储中查找内容。
Linux系统中nsswitch的库文件有很多,但本文实现的本地用户登陆只需要/lib64下的两个文件:
[root@CentOS5lsrv01 ~]# ll /lib64/libnss_files*
-rwxr-xr-x 1 root root 53880 Sep 16 2014 /lib64/libnss_files-2.5.so
lrwxrwxrwx 1 root root 19 Nov 29 09:53 /lib64/libnss_files.so.2 -> libnss_files-2.5.so
拷贝需要的libnss_files*文件到miniLinux系统:
64位系统:
[root@CentOS5lsrv01 ~]# cp -d /lib64/libnss_files* /mnt/sysroot/lib64/
32位系统:
[root@CentOS5lsrv01 ~]# cp -d /lib/libnss_files* /mnt/sysroot/lib/
cp命令的“-d”参数让链接文件保持原来的链接文件属性
5.4为minLinux系统建立用户信息文件(/etc/pwsswd、/etc/group、/etc/shadow)
在源系统中移植用户root和redhat到miniLinux系统:
[root@CentOS5lsrv01 ~]# grep -E ^"root|redhat" /etc/passwd > /mnt/sysroot/etc/passwd
[root@CentOS5lsrv01 ~]# grep -E ^"root|redhat" /etc/group > /mnt/sysroot/etc/group
[root@CentOS5lsrv01 ~]# grep -E ^"root|redhat" /etc/shadow > /mnt/sysroot/etc/shadow
修改miniLinux系统中shadow文件权限:
[root@CentOS5lsrv01 ~]# chmod 400 /mnt/sysroot/etc/shadow
5.5为miniLinux系统建立nsswitch.conf配置文件
[root@CentOS5lsrv01 ~]# vi /mnt/sysroot/etc/nsswitch.conf
passwd: files files:用户以本地认证方式登陆
shadow: files
group: files
启动miniLinux系统测试吧(必须先挂起源系统,不要怪我唠叨,这步很重要),如下两图:
到此,大功告成啦!!噢耶!!!
小结:
1. 经历了7次修改,终于完美的实现了重新编译login程序。
2. 各位同行在网上找到的方法应该都是直接给出已经编译过的login程序的,没有详细编译过程,
貌似都是马哥给出的,我也看过马哥的教程哦!!
3. 从源码的层面去解决问题确实比较复杂,必须要有比较坚韧的精神才能坚持(貌似不小心赞了赞自己!!呵呵!)
4. 遇到问题不要轻易放弃,修改源代码我觉得难度还是比较大的(起码要将源码读几遍,了解了才能下手),但同时也更清楚Linux系统的工作原理,我觉得还是值得花时间的。
5. 希望本文提供的方法可以帮助到各位同行或对大家有借鉴作用。
最后如果各位同行小伙伴发现文章有错误或是有更好的方法,可以告诉我,大家一起交流,共同进步!谢谢!!
转载于:https://blog.51cto.com/linuxprince/2054153
Linux系统裁减之,制作一个极度精简的Linux-5-重新编译login去除对pam模块的依赖...相关推荐
- Linux 系统裁剪--制作一个最小化的Linux iso镜像
1.前言 一直以来都想制作一个最小化的Linux系统,这个小系统需要有常用的Linux 命令,以及定制化的某些功能.可是由于种种原因一直没能实现,最近终于有时间把它做了出来. 本文所说的精简的Linu ...
- linux 系统裁减指南,Linux 系统裁减指南
Linux 系统裁减指南 第一步:裁减内核 打开终端,输入:cd /usr/src/linux2.4,然后输入make xconfig.现在编译内核正式开始了 1.1 "cod ...
- linux 已打开文件图标管理,Linux_没有启动图标利用Linux命令在终端打开文件, 在Linux系统中,打开一个 - phpStudy...
没有启动图标利用Linux命令在终端打开文件 在Linux系统中,打开一个文件很简单,只要有启动图标就可以了,但是如果没有启动图标的话要如何在终端下打开文件呢?使用命令就能很好的解决这个问题,下面小编 ...
- linux 系统qcow2镜像制作
文章目录 一.linux 系统qcow2镜像制作 1. 基础知识 KVM 虚拟化kvm发展 VMware与KVM KVM和Qemu.libvirt的关系 2. 什么是qcow2 3. KVM环境下制作 ...
- u盘安装完linux系统没镜像,U盘刻录kali linux启动盘提示找不到镜像解决方案
U盘刻录14.10镜像出问题的解决方法 从几个月前的14.10 daily 版本就有U盘刻录无法启动的现象,相关bug可参见:https://bugs.launchpad.net/ubunt ... ...
- linux系统怎样写单片机程序,单片机知识是Linux驱动开发的基础之一以及如何学单片机...
这是arm裸机1期加强版第1课第2.3节课程的wiki文字版. 为什么没前途也要学习单片机? 因为它是个很好的入口. 学习单片机可以让我们抛开复杂的软件结构,先掌握硬件操作,如:看原理图.芯片手册.写 ...
- linux系统下的打印机驱动下载,方法论:Linux下如何驱动主流品牌打印机
薄荷站长浸淫 Linux 桌面领域十余年,一直致力于 Linux 桌面系统的推广.对于桌面用户办公中必需的打印功能,薄荷站长也是有所研究.为了使新手朋友们少走弯路,薄荷站长介绍一下常见品牌打印机的 L ...
- Java File.getPath() File.getAbsolutePath()函数在Windows和Linux系统上存在区别!win正常而linux会报错!
Java File.getPath() File.getAbsolutePath()函数在Windows和Linux系统上存在区别!win正常而linux会报错! 如下图: windows下的源代码和 ...
- linux系统能做什么的,Linux系统适合日常使用吗?普通人学Linux能干什么
Linux是多用户多任务系统,多个用户可以同时使用,计算机同时执行多个任务.但对于普通人来说,Linux系统适合日常使用吗?普通人学Linux能干什么?确实是值得深思. Linux是程序员的标配.Li ...
- Linux系统适合日常使用吗?普通人学Linux能干什么
Linux是多用户多任务系统,多个用户可以同时使用,计算机同时执行多个任务.但对于普通人来说,Linux系统适合日常使用吗?普通人学Linux能干什么?确实是值得深思. Linux是程序员的标配.Li ...
最新文章
- 指针02 - 零基础入门学习C语言42
- 图像处理与计算机视觉:基础,经典以及最近发展(3)计算机视觉中的信号处理与模式识别
- 使用Angular可重用Component思路实现一个自带图标(icon)的input控件
- 利用Nmap对MS-SQLSERVER进行渗透
- linux 深度 root,深度刷机让毫秒级一键ROOT成为现实
- JS for循环 if判断、white循环。小练习
- div+css格式规范
- 电话聊天狂人(25 分)(散列函数)
- CF1062F Upgrading Cities
- SQL注入攻击原理及防御策略
- IDEA统计代码行数
- VS2018+TensorFlow安装
- 网页版MSDOS的实现网站
- 工作到现在的一些感想
- 【嵌入式系统开发19】理解嵌入式实时操作系统,以uc/OS为例利用C8T6完成LED周期闪烁以及串口周期输出
- 传国宝玺 第二部 降墓 第十六章 三煞天棺
- 分享 | masked自编码器(MAE):一种可扩展的用于计算机视觉任务的自监督学习器
- 记录:【DIY】一块SSD拯救了我的笔记本
- 微信文件过大不能上传?学会这几种方法,再大文件也能轻松发
- 自然语言处理nltk分词断句(2)