Linux下Terminal的密碼輸入(轉)

ba發表於2007-08-17
Linux下Terminal的密碼輸入(轉)[@more@]最近由於一個程式安全的需要,在執行程式時需要使用者輸入使用者名稱密碼。哎,一直沒做過在程式執行時的許可權認證,以前都是透過對機器系統級的使用者許可權控制達到許可權管理的需求(事實這也是我覺得最實用,簡單的一種)。OK,不做是不可能的,有時候被迫接受別人的思想,自己的思想無法體現也是非常痛苦的啊,題外話,呵呵。切入正題。

誰規定的輸入密碼時不能顯示出來?揹著點人不就行了嘛,還要給技術找麻煩,要知道做技術多辛苦啊,又累!算了,順應大眾習慣吧。本來Linux下有系統提供的getpass()函式,可由於寫的時候太早了(我猜的呵呵,當時可能就這需求),只支援8位字元,同時有安全隱患(溢位!),obsolate了,可憐的孩子啊。那總該有個替換的吧?例如像getpass_new()這種的函式,K~找了半天,沒找到啊!鬱悶。沒辦法,想辦法吧。查了點資料,最多的是用ncurses庫裡的getch(),可我的是Terminal啊,盜版SecureCRT,用不成。還有兩種就差不多了,都是透過termios來控制低層。一種是透過最最最強大的函式:ioctl(),用資料struct termio設定TCGETA、TCSETA。最討厭用ioctl了!本來這函式挺簡單,可我覺得就是做OS開發的人在偷懶!你要控制IO的哪部分,怎麼控制,都得自己去找引數,找資料結構,鬱悶。嘿,終於輪到主角出場了,我覺得這個才是正道啊!猜對了,這就是termios.h裡藏著的:

int tcgetattr (int __fd, struct termios *__termios_p);
int tcsetattr (int __fd, int __optional_actions,
__const struct termios *__termios_p);

哎,找了半天,終於找到讓我一見鍾情的她了~
這個其實也是對檔案(UNIX概念的檔案)進行設定,應該也是呼叫ioctl吧?猜的,沒看原始碼:)但起碼感覺它是專門做這個的呀,看人家多專一!

查了一下,還好,tcsetattr的optional actions只有三個選擇,一目瞭然了,當然是用Flush action(TCSAFLUSH)了。萬事俱備啊!於是_fd用0(stdin),輸出當然要用stderr了,action用TCSAFLUSH, termios_p只需要設定個c_lflag,和~ECHO做個&就OK了。呵,終於搞定了。原始碼奉上:



#include

void UserIf::Echoff(int f)
{
struct termios sg;
tcgetattr(f, &sg); /* get settings */
sg.c_lflag &= ~ECHO; /* turn echo off */
tcsetattr(f,TCSAFLUSH,&sg); /* set settings */
}

void UserIf::Echon(int f)
{
struct termios sg;
tcgetattr(f, &sg); /* get settings */
sg.c_lflag |= ECHO; /* turn echo on */
tcsetattr(f,TCSAFLUSH,&sg); /* set settings */
}

string UserIf::getPassword(string prompt, int n)
{
char c; // for read()
int i; // number of input
char *w; // warning on retry
int f; // file descripto
char *p = new char(n+2);
string ret;
f = 0; // Read from stdin
// get password
w = ""; //warning
do
{
fputs(w, stderr);
fputs(prompt.c_str(), stderr);
fflush(stderr);
i = 0;
Echoff(f);
do { /* read line, keeping n */
read(f, &c, 1);
if (i < n)
p[i++] = c;
} while (c != );
Echon(f);
putc(, stderr);
fflush(stderr);
w = "(line too long) ";
} while (p[i-1] != );
p[i-1] = 0; //!!!notice
ret = string(p);
delete p;
return ret;
} /* end function getPassword */


寫得有點亂,本來想用std的stream來做的,可除了最基本的功能都不太熟悉,還是改用了c 的檔案操作模式。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-963303/,如需轉載,請註明出處,否則將追究法律責任。

相關文章