第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模块的依赖...相关推荐

  1. Linux 系统裁剪--制作一个最小化的Linux iso镜像

    1.前言 一直以来都想制作一个最小化的Linux系统,这个小系统需要有常用的Linux 命令,以及定制化的某些功能.可是由于种种原因一直没能实现,最近终于有时间把它做了出来. 本文所说的精简的Linu ...

  2. linux 系统裁减指南,Linux 系统裁减指南

    Linux 系统裁减指南 第一步:裁减内核 打开终端,输入:cd /usr/src/linux2.4,然后输入make xconfig.现在编译内核正式开始了 1.1        "cod ...

  3. linux 已打开文件图标管理,Linux_没有启动图标利用Linux命令在终端打开文件,  在Linux系统中,打开一个 - phpStudy...

    没有启动图标利用Linux命令在终端打开文件 在Linux系统中,打开一个文件很简单,只要有启动图标就可以了,但是如果没有启动图标的话要如何在终端下打开文件呢?使用命令就能很好的解决这个问题,下面小编 ...

  4. linux 系统qcow2镜像制作

    文章目录 一.linux 系统qcow2镜像制作 1. 基础知识 KVM 虚拟化kvm发展 VMware与KVM KVM和Qemu.libvirt的关系 2. 什么是qcow2 3. KVM环境下制作 ...

  5. u盘安装完linux系统没镜像,U盘刻录kali linux启动盘提示找不到镜像解决方案

    U盘刻录14.10镜像出问题的解决方法 从几个月前的14.10 daily 版本就有U盘刻录无法启动的现象,相关bug可参见:https://bugs.launchpad.net/ubunt ... ...

  6. linux系统怎样写单片机程序,单片机知识是Linux驱动开发的基础之一以及如何学单片机...

    这是arm裸机1期加强版第1课第2.3节课程的wiki文字版. 为什么没前途也要学习单片机? 因为它是个很好的入口. 学习单片机可以让我们抛开复杂的软件结构,先掌握硬件操作,如:看原理图.芯片手册.写 ...

  7. linux系统下的打印机驱动下载,方法论:Linux下如何驱动主流品牌打印机

    薄荷站长浸淫 Linux 桌面领域十余年,一直致力于 Linux 桌面系统的推广.对于桌面用户办公中必需的打印功能,薄荷站长也是有所研究.为了使新手朋友们少走弯路,薄荷站长介绍一下常见品牌打印机的 L ...

  8. Java File.getPath() File.getAbsolutePath()函数在Windows和Linux系统上存在区别!win正常而linux会报错!

    Java File.getPath() File.getAbsolutePath()函数在Windows和Linux系统上存在区别!win正常而linux会报错! 如下图: windows下的源代码和 ...

  9. linux系统能做什么的,Linux系统适合日常使用吗?普通人学Linux能干什么

    Linux是多用户多任务系统,多个用户可以同时使用,计算机同时执行多个任务.但对于普通人来说,Linux系统适合日常使用吗?普通人学Linux能干什么?确实是值得深思. Linux是程序员的标配.Li ...

  10. Linux系统适合日常使用吗?普通人学Linux能干什么

    Linux是多用户多任务系统,多个用户可以同时使用,计算机同时执行多个任务.但对于普通人来说,Linux系统适合日常使用吗?普通人学Linux能干什么?确实是值得深思. Linux是程序员的标配.Li ...

最新文章

  1. 指针02 - 零基础入门学习C语言42
  2. 图像处理与计算机视觉:基础,经典以及最近发展(3)计算机视觉中的信号处理与模式识别
  3. 使用Angular可重用Component思路实现一个自带图标(icon)的input控件
  4. 利用Nmap对MS-SQLSERVER进行渗透
  5. linux 深度 root,深度刷机让毫秒级一键ROOT成为现实
  6. JS for循环 if判断、white循环。小练习
  7. div+css格式规范
  8. 电话聊天狂人(25 分)(散列函数)
  9. CF1062F Upgrading Cities
  10. SQL注入攻击原理及防御策略
  11. IDEA统计代码行数
  12. VS2018+TensorFlow安装
  13. 网页版MSDOS的实现网站
  14. 工作到现在的一些感想
  15. 【嵌入式系统开发19】理解嵌入式实时操作系统,以uc/OS为例利用C8T6完成LED周期闪烁以及串口周期输出
  16. 传国宝玺 第二部 降墓 第十六章 三煞天棺
  17. 分享 | masked自编码器(MAE):一种可扩展的用于计算机视觉任务的自监督学习器
  18. 记录:【DIY】一块SSD拯救了我的笔记本
  19. 微信文件过大不能上传?学会这几种方法,再大文件也能轻松发
  20. 自然语言处理nltk分词断句(2)

热门文章

  1. C# 使用 Task 替换 ThreadPool ,异步监测所有线程(任务)是否全部执行完毕
  2. IQ推理:P先生和Q先生
  3. IBM AIX5.3 linux下C/C++实现HTTPS接口
  4. 大用户量下Open***部署方案(二)
  5. Hive内部表外部表转化分析(装)
  6. 三维模型等大长方体剖分算法实现
  7. 打造属于自己的 linux版(硬盘版或电子盘)view5 终端
  8. 转载:Oracle导入导出命令的使用
  9. 代码换行符_Excel办公技巧:如何定位、替换、清除单元格中的换行符?
  10. 自旋锁spin_lock