一个很简陋的认证过程,通过用户名(或用户ID)和密码明文验证该用户是否可以登陆系统,
linux登陆认证模拟Linux
。 just for fun,没有时间完善了,不过应该比较容易扩充和增加其他的功能。 注意链接需要制定-lcrypt。如果需要一般用户同样可以使用,需要将程序setuid(需要验证/etc/s一个很简陋的认证过程,通过用户名(或用户ID)和密码明文验证该用户是否可以登陆系统。
just for fun,没有时间完善了,不过应该比较容易扩充和增加其他的功能。
注意链接需要制定-lcrypt。如果需要一般用户同样可以使用,需要将程序setuid(需要验证/etc/shadow):
# chown root:root checkpasswd
# chmod 4755 checkpasswd
usage:
$ checkpasswd --user testuser --password testpassword --verbose
$ checkpasswd -i 1001 -p empty_passwd -v
#define _XOPEN_SOURCE</p><p> #define _GNU_SOURCE</p><p> #include<sys></p><p> #include<stdlib.h></p><p> #include<string.h></p><p> #include<stdio.h></p><p> #include</p><p> #include<errno.h></p><p> #include<stdarg.h></p><p> #include<unistd.h></p><p> #include<stdint.h></p><p> #include<pwd.h></p><p> #include<shadow.h></p><p> #include<getopt.h></p><p> typedef enum{</p><p> AUTH_TYPE_AUTO,</p><p> AUTH_TYPE_DES,</p><p> AUTH_TYPE_MD5,</p><p> NR_AUTH_TYPE</p><p> }auth_type_t;</p><p> typedef enum{</p><p> AUTH_INFO_AUTO,</p><p> AUTH_INFO_PASSWD,</p><p> AUTH_INFO_SHADOW,</p><p> NR_AUTH_INFO</p><p> }auth_info_t;</p><p> typedef struct login_info{</p><p> char* login; /* login name */</p><p> char* cname; /* cname */</p><p> char* group;</p><p> char* passwd; /* plain text password */</p><p> uid_t uid;</p><p> gid_t gid;</p><p> uint16_t auth_type;</p><p> uint16_t auth_info;</p><p> }login_info_t;</p><p> static login_info_t login_info = {</p><p> NULL, NULL, NULL, NULL, -1, -1, 0, 0,</p><p> };</p><p> static int verbose_flag;</p><p> /**</p><p> * option for getopt_long</p><p> */</p><p> static const struct option opt_options[] = {</p><p> {"user", 1, 0, 'n'},</p><p> {"uid", 1, 0, 'u'},</p><p> {"password", 1, 0, 'p'},</p><p> {"help", 0, 0, '?'},</p><p> {"version", 0, 0, 'V'},</p><p> {"verbose", 0, 0, 'v'},</p><p> {0, 0, 0, 0},</p><p> };</p><p> static void help(void)</p><p> {</p><p> const struct option* o;</p><p> for(o = &opt_options[0]; o && o->name; o++){</p><p> fprintf(stderr, "%s\n", o->name);</p><p> }</p><p> fprintf(stderr, "\n");</p><p> }</p><p> static void version(void)</p><p> {</p><p> fprintf(stderr, "version: 0.0.1\n");</p><p> }</p><p> int verbose(const char* fmt, ...)</p><p> {</p><p> va_list ap;</p><p> int n;</p><p> if(!verbose_flag)</p><p> return 0;</p><p> va_start(ap, fmt);</p><p> n = vfprintf(stderr, fmt, ap);</p><p> va_end(ap);</p><p> return 0;</p><p> }</p><p> int auth_des(const char* plain_text, const char* key_compare)</p><p> {</p><p> char* des_key;</p><p> char salt[2] = ;</p><p> if(strlen(key_compare) < 2)</p><p> return -1;</p><p> strncpy(salt, key_compare, 2);</p><p> des_key = crypt(plain_text, salt);</p><p> if(strcmp(des_key, key_compare) == 0)</p><p> return 0;</p><p> verbose("auth DES: non-match(Wrong) password!\n");</p><p> return -1;</p><p> }</p><p> /**</p><p> * need GNU libc 2.x or higher</p><p> */</p><p> int auth_md5(const char* plain_text, const char* key_compare)</p><p> {</p><p> char* md5_key;</p><p> const char* p;</p><p> char salt[12] = ;</p><p> int n = 0;</p><p> if(strlen(key_compare) < 3)</p><p> return -1;</p><p> if(strncmp(key_compare, "$", 3) != 0){ /* not start with "$", please confirm</p><p> to /etc/shadow file */</p><p> verbose("auth MD5: not start with \"$\"\n");</p><p> return -1;</p><p> }</p><p> p = key_compare + 3;</p><p> while(*p++){</p><p> ++n;</p><p> if(!p){</p><p> verbose("auth MD5: invalid shadowed MD5 password!\n");</p><p> return -1; /* invalid shadowed md5 password */</p><p> }</p><p> if(n > 8){</p><p> break;</p><p> }</p><p> if(*p == '$'){</p><p> break;</p><p> }</p><p> }</p><p> strncpy(salt, key_compare, n + 3);</p><p> md5_key = crypt(plain_text, salt);</p><p> if(strcmp(md5_key, key_compare) == 0)</p><p> return 0;</p><p> verbose("auth MD5, non-match(Wrong) password!\n");</p><p> return -1;</p><p> }</p><p> int check_shadowed_passwd(login_info_t* login_info)</p><p> {</p><p> struct passwd* pw;</p><p> struct spwd* spw;</p><p> if(login_info->login){</p><p> spw = getspnam(login_info->login);</p><p> }else if(login_info->uid >= 0){</p><p> pw = getpwuid(login_info->uid);</p><p> if(!pw){</p><p> verbose("getpwuid [%d] failed, error: %s\n", login_info->uid,</p><p> strerror(errno));</p><p> return -1;</p><p> }</p><p> login_info->login = pw->pw_name;</p><p> spw = getspnam(pw->pw_name);</p><p> }else{</p><p> return -1;</p><p> }</p><p> if(!spw){</p><p> fprintf(stderr, "unable to read shadow passwd info: %s\n",</p><p> strerror(errno));</p><p> return -1;</p><p> }</p><p> if(login_info->auth_type == AUTH_TYPE_AUTO){</p><p> if(strncmp(spw->sp_pwdp, "$", 3) == 0){ /* GNU extension, md5 used */</p><p> return auth_md5(login_info->passwd, spw->sp_pwdp);</p><p> }else{</p><p> return auth_des(login_info->passwd, spw->sp_pwdp);</p><p> }</p><p> }else if(login_info->auth_type == AUTH_TYPE_DES){</p><p> return auth_des(login_info->passwd, spw->sp_pwdp);</p><p> }else if(login_info->auth_type == AUTH_TYPE_MD5){</p><p> return auth_md5(login_info->passwd, spw->sp_pwdp);</p><p> }else{</p><p> verbose("unknown auth type: %d\n", login_info->auth_type);</p><p> return -1;</p><p> }</p><p> }</p><p> /**</p><p> * checkpasswd<user><pass></p><p> */</p><p> int check_passwd(login_info_t* login_info)</p><p> {</p><p> struct passwd* pw;</p><p> if(login_info->login){</p><p> pw = getpwnam(login_info->login);</p><p> if(!pw){</p><p> verbose("getpwnam [%s] failed, error: %s\n", login_info->login,</p><p> strerror(errno));</p><p> return -1;</p><p> }</p><p> login_info->uid = pw->pw_uid;</p><p> }else if(login_info->uid >= 0){</p><p> pw = getpwuid(login_info->uid);</p><p> if(!pw){</p><p> verbose("getpwuid [%d] failed, error: %s\n", login_info->uid,</p><p> strerror(errno));</p><p> return -1;</p><p> }</p><p> login_info->login = pw->pw_name;</p><p> }else{</p><p> return -1;</p><p> }</p><p> if(!login_info->passwd){</p><p> verbose("no password specified!\n");</p><p> return -1;</p><p> }</p><p> if(login_info->auth_info == AUTH_INFO_AUTO){</p><p> if(strlen(pw->pw_passwd) < 2){</p><p> if(strcmp(pw->pw_passwd, "x") == 0){ /* shadow password used */</p><p> return check_shadowed_passwd(login_info);</p><p> }else{</p><p> return -1;</p><p> }</p><p> }</p><p> return auth_des(login_info->passwd, pw->pw_passwd);</p><p> }else if(login_info->auth_info == AUTH_INFO_PASSWD){</p><p> return auth_des(login_info->passwd, pw->pw_passwd);</p><p> }else if(login_info->auth_info == AUTH_INFO_SHADOW){</p><p> return check_shadowed_passwd(login_info);</p><p> }else{</p><p> verbose("unknown auth info: %d\n", login_info->auth_info);</p><p> return -1;</p><p> }</p><p> }</p><p> void handle_args(int argc, char* argv[])</p><p> {</p><p> int ch;</p><p> int option_index;</p><p> while((ch = getopt_long(argc, argv, "u:i:p:Vvh", opt_options, &option_index)) != -1){</p><p> switch(ch){</p><p> case 'u':</p><p> login_info.login = optarg;</p><p> break;</p><p> case 'i':</p><p> login_info.uid = atoi(optarg);</p><p> break;</p><p> case 'p':</p><p> login_info.passwd = optarg;</p><p> break;</p><p> case 'h':</p><p> help();</p><p> exit(0);</p><p> break;</p><p> case 'V':</p><p> version();</p><p> exit(0);</p><p> break;</p><p> case 'v':</p><p> verbose_flag = 1;</p><p> break;</p><p> case '?':</p><p> default:</p><p> help();</p><p> exit(1);</p><p> break;</p><p> }</p><p> }</p><p> if(!login_info.passwd){</p><p> fprintf(stderr, "please specifie login password\n");</p><p> help();</p><p> exit(1);</p><p> }</p><p> if(!login_info.login && !login_info.uid){</p><p> fprintf(stderr, "please specifie either login name or user id\n");</p><p> help();</p><p> exit(1);</p><p> }</p><p> }</p><p> int main(int argc, char* argv[])</p><p> {</p><p> int ret;</p><p> const char seperator[] =</p><p> "==========================================================================================\n";</p><p> int retcode = 1;</p><p> handle_args(argc, argv);</p><p> printf(seperator);</p><p> ret = check_passwd(&login_info);</p><p> if(ret < 0){</p><p> fprintf(stderr, "3[1;31mauthentication failed for user: "</p><p> "[%s], uid[%d], password: [%s]3[m\n",</p><p> login_info.login, login_info.uid, login_info.passwd);</p><p> goto quit;</p><p> }else if(ret == 0){</p><p> printf("3[1;32mauthenticated token su<strong>clearcase</STRONG>/" target="_blank" >cc</STRONG>essfully, user: "</p><p> "[%s], uid: [%d]3[m\n",</p><p> login_info.login, login_info.uid);</p><p> retcode = 0;</p><p> }else{</p><p> assert(0);</p><p> retcode = -1;</p><p> }</p><p> quit:</p><p> printf(seperator);</p><p> exit(retcode);</p><p> }
原文转自:http://www.ltesting.net