NetBSDのソースを読んでいく passwd編
とある研究室の見学に行った時に、linuxのソースが迷宮過ぎて、どうやって読んでいったらいいか分からないと言われた時にすすめられた本「デーモン君のソース探検」の読書メモついでに自分の調べた事も載せていく。
テーマ「UNIXにログインする際にパスワードが表示されないようにする方法」
まずはloginコマンドを調べる
$ locate login.c
/Applications/MAMP/htdocs/cake_1_3/app/views/users/login.ctp
/Applications/MAMP/htdocs/gpr/app/views/users/login.ctp
/usr/src/crypto/dist/heimdal/appl/login/login.c
/usr/src/crypto/dist/heimdal/appl/login/utmp_login.c
......
......
/usr/src/usr.bin/login/login.c
......
$ less /usr/src/usr.bin/login/login.c
vimでPasswordを検索語句に調べていくと、412行目あたりにhit↓
pwprompt = "Password:";
p = getpass(pwprompt);
getpassを調べる
$ man getpass
マニュアルを見る限り、パスワードを読み込む関数でパスワードは表示しないと言ってる。
getpassをみていく。
manのLibralyにはStandard C Libraryと書いてあったのでソースは /usr/src/lib/libcにある。
$ cd /usr/src/lib/libc
$ grep getpass *
$ grep getpass */*
hit! gen/getpass.c
gen/Makefile.inc: getpass.c getprogname.c getpwent.c getsubopt.c getttyent.c \
gen/Makefile.inc: getmntinfo.3 getnetgrent.3 getpagesize.3 getpass.3 \
gen/getpass.3:.\" $NetBSD: getpass.3,v 1.9 2002/02/07 07:00:13 ross Exp $
gen/getpass.3:.\" @(#)getpass.3 8.1 (Berkeley) 6/4/93
gen/getpass.3:.Nm getpass
gen/getpass.3:.Fn getpass "const char *prompt"
gen/getpass.3:.Fn getpass
gen/getpass.c:/* $NetBSD: getpass.c,v 1.14 2000/01/22 22:19:11 mycroft Exp $ */
gen/getpass.c:static char sccsid[] = "@(#)getpass.c 8.1 (Berkeley) 6/4/93";
gen/getpass.c:__RCSID("$NetBSD: getpass.c,v 1.14 2000/01/22 22:19:11 mycroft Exp $");
gen/getpass.c:__weak_alias(getpass,_getpass)
gen/getpass.c:getpass(prompt)
include/namespace.h:#define getpass _getpass
getpass.cを見ていくと、ECHOがある辺りがちょっと臭う。
if ((echo = (term.c_lflag & ECHO)) != 0) {
term.c_lflag &= ~ECHO;
(void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
}
tcsetattrを調べる
$ locate tcsetattr.c
/usr/src/lib/libc/termios/tcsetattr.c
中を見てみる
{
struct termios localterm;
_DIAGASSERT(fd != -1);
_DIAGASSERT(t != NULL);
if (opt & TCSASOFT) {
localterm = *t;
localterm.c_cflag |= CIGNORE;
t = &localterm;
}
switch (opt & ~TCSASOFT) {
case TCSANOW:
return (ioctl(fd, TIOCSETA, t));
case TCSADRAIN:
return (ioctl(fd, TIOCSETAW, t));
case TCSAFLUSH:
return (ioctl(fd, TIOCSETAF, t));
default:
errno = EINVAL;
return (-1);
}
}
ここでioctlはmanで調べれば分かるが2番のシステムコール。
よってUNIX上で動作するプログラム、つまりlogin実行ファイルはカーネルへの標準出力への書き込み要求の発行をioctl、デバイス操作によってキャンセルしていることが分かった。
参考 割り込みメソッドを使用したシステム・コールの簡易フロー