linux命令:su的實現
阿新 • • 發佈:2018-11-21
使用su命令可以切換使用者,不加引數時預設切換到root使用者。
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<assert.h> #include <shadow.h> #include <pwd.h> #include <sys/types.h> #include<termios.h> #include<errno.h> int main(int argc, char *argv[]) { char *user = "root"; if(argv[1] != NULL) { user = argv[1]; } printf("Password: "); fflush(stdout); ///////////////////////////////// /////設定終端不回顯的程式碼 struct termios oldflag, newflag;//儲存原有終端屬性和新設定的終端屬性 tcgetattr(fileno(stdin), &oldflag);//獲得終端原有屬性並儲存在結構體oldflag newflag = oldflag; newflag.c_lflag &= ~ECHO; newflag.c_lflag |= ECHONL; if(tcsetattr(fileno(stdin), TCSANOW, &newflag) != 0) { perror("tcsetattr"); return -1; } ////////////////////// char passwd[128] = {0}; fgets(passwd, 128, stdin); passwd[strlen(passwd) - 1] = 0; ///////////////////////////////// if(tcsetattr(fileno(stdin), TCSANOW, &oldflag) != 0) { perror("tcsetattr"); return -1; } //////////////////////////////// //根據使用者名稱獲取系統儲存使用者的密碼資訊 struct spwd *pwd = getspnam(user); assert(pwd != NULL); ////////////////////////////////////// //根據使用者密碼資訊獲取加密演算法iD以及金鑰 char *p = pwd->sp_pwdp; char salt[128] = {0}; int count = 0, i = 0; while(1) { salt[i] = *p; if(salt[i] == '$') { count++; } if(count == 3) { break; } i++,p++; } //////////////////////////// //根據獲取的演算法ID和金鑰,對輸入的明文加密 char *s = crypt(passwd, salt); if(strcmp(s, pwd->sp_pwdp) != 0) { printf("password is error\n"); exit(0); } pid_t n = fork(); assert(n != -1); if(n == 0) { struct passwd *pw = getpwnam(user); assert(pw != NULL); setenv("HOME", pw->pw_dir, 1); // 設定環境變數 setuid(pw->pw_uid); // 修改使用者 execl(pw->pw_shell, pw->pw_shell, (char*)0); printf("su is fail\n"); exit(0); } else { wait(NULL); } }
系統中的su命令,在你輸入密碼時不會回顯,這樣更加安全,
下面是實現程式碼:
#include<termios.h> #include<errno.h> /////設定終端不回顯的程式碼 struct termios oldflag, newflag;//儲存原有終端屬性和新設定的終端屬性 tcgetattr(fileno(stdin), &oldflag);//獲得終端原有屬性並儲存在結構體oldflag newflag = oldflag; newflag.c_lflag &= ~ECHO; newflag.c_lflag |= ECHONL; if(tcsetattr(fileno(stdin), TCSANOW, &newflag) != 0) { perror("tcsetattr"); return -1; } ////////////////////// char passwd[128] = {0}; fgets(passwd, 128, stdin); passwd[strlen(passwd) - 1] = 0; ///////////////////////////////// if(tcsetattr(fileno(stdin), TCSANOW, &oldflag) != 0) { perror("tcsetattr"); return -1; } ////////////////////////////////
在該命令中,我們要判斷使用者輸入的密碼是否正確,在判斷密碼正確後,要重新設定環境變數,並且修改使用者,將終端切換到當前新使用者的預設終端下。這才真正完成了su命令。
執行結果如下: