Enviar pesquisa
Carregar
env EDITOR=vipw vipwしてみた
•
1 gostou
•
1,402 visualizações
ogatay
Seguir
Denunciar
Compartilhar
Denunciar
Compartilhar
1 de 33
Baixar agora
Baixar para ler offline
Recomendados
PHP Object Injection入門
PHP Object Injection入門
Yu Iwama
Boost jp9 program_options
Boost jp9 program_options
nyaocat
MySQL5.6検証レポート
MySQL5.6検証レポート
Hironori Miura
Kai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / Erlang
Takeru INOUE
Clojure
Clojure
yshigeru
Actor&stm
Actor&stm
潤一 加藤
Scala with DDD
Scala with DDD
潤一 加藤
ConcurrentHashMap Code Reading
ConcurrentHashMap Code Reading
Naoyuki Kakuda
Recomendados
PHP Object Injection入門
PHP Object Injection入門
Yu Iwama
Boost jp9 program_options
Boost jp9 program_options
nyaocat
MySQL5.6検証レポート
MySQL5.6検証レポート
Hironori Miura
Kai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / Erlang
Takeru INOUE
Clojure
Clojure
yshigeru
Actor&stm
Actor&stm
潤一 加藤
Scala with DDD
Scala with DDD
潤一 加藤
ConcurrentHashMap Code Reading
ConcurrentHashMap Code Reading
Naoyuki Kakuda
Glasriket - inspiration kring design
Glasriket - inspiration kring design
SVID
EICG BD Company Profile
EICG BD Company Profile
aelnady
2012 1-00105-if bab 5
2012 1-00105-if bab 5
Jabarin Koni
超簡単!TELNETの話
超簡単!TELNETの話
ogatay
Iageovanyangulo
Iageovanyangulo
geovannyangulo
Social Media Plan for TATA DoCoMo WAT CONSULT
Social Media Plan for TATA DoCoMo WAT CONSULT
Mohin Khan
Mais conteúdo relacionado
Destaque
Glasriket - inspiration kring design
Glasriket - inspiration kring design
SVID
EICG BD Company Profile
EICG BD Company Profile
aelnady
2012 1-00105-if bab 5
2012 1-00105-if bab 5
Jabarin Koni
超簡単!TELNETの話
超簡単!TELNETの話
ogatay
Iageovanyangulo
Iageovanyangulo
geovannyangulo
Social Media Plan for TATA DoCoMo WAT CONSULT
Social Media Plan for TATA DoCoMo WAT CONSULT
Mohin Khan
Destaque
(6)
Glasriket - inspiration kring design
Glasriket - inspiration kring design
EICG BD Company Profile
EICG BD Company Profile
2012 1-00105-if bab 5
2012 1-00105-if bab 5
超簡単!TELNETの話
超簡単!TELNETの話
Iageovanyangulo
Iageovanyangulo
Social Media Plan for TATA DoCoMo WAT CONSULT
Social Media Plan for TATA DoCoMo WAT CONSULT
env EDITOR=vipw vipwしてみた
1.
env EDITOR=vipw vipw
してみた @yogata
2.
vipw • ユーザ追加・削除・情報変更する
vipw useradd/adduser メリット Jviが使える 特に無い デメリット 特にない Luserとaddのどっちが 先かわからない • vipw is 神
3.
こんなにもすばらしいvipw • 使いたくなってきたはず
• でも……viは慣れてないし…… env EDITOR=XXX vipw
4.
vipw と EDITOR変数
• env EDITOR=nano vipw
5.
vipw と EDITOR変数
• env EDITOR=emacs vipw
6.
vipw と EDITOR変数
( ^o^) env EDITOR=emacs vipw → emacsで開く ( ˘⊖˘) 。o( env EDITOR=vipw vipwしたらどうなるんだ) |Terminal.app| ┗(☋` )┓三 ( ◠‿◠ )☛ そこに気づいてしまったか ▂▅▇█▓▒░(’ω’)░▒▓█▇▅▂うわあああああああ
7.
やってみる # env
EDITOR=vipw vipw rootになるのを 忘れずに
8.
やってみる
9.
調べる • FreeBSD
– /usr/src/usr.sbin/vipw/vipw.c – /usr/src/lib/libuMl/pw_uMl.c – /usr/include/pwd.h – err周りはここらへん • /usr/src/lib/libc/gen/err.c
10.
vipw.c (1/3)
65 int 66 main(int argc, char *argv[]) 67 { 68 const char *passwd_dir = NULL; 69 int ch, pfd, ad; 70 char *line; 71 size_t len; 72 73 while ((ch = getopt(argc, argv, "d:")) != -‐1) 74 switch (ch) { 75 case 'd': vipwのオプションは-‐dだけ.それ 76 passwd_dir = optarg; 以外のオプションが来たらusage() 77 break; する 78 case '?': 79 default: 80 usage(); 81 } 82 83 argc -‐= opMnd; 84 argv += opMnd;
11.
vipw.c (2/3)
85 86 if (argc != 0) 87 usage(); 88 89 if (pw_init(passwd_dir, NULL) == -‐1) pw_init() ? 90 err(1, "pw_init()"); 91 if ((pfd = pw_lock()) == -‐1) { 92 pw_fini(); 93 err(1, "pw_lock()"); pw_lock() ? 94 } 95 if ((ad = pw_tmp(pfd)) == -‐1) { 96 pw_fini(); 97 err(1, "pw_tmp()"); pw_tmp() ? 98 } 99 (void)close(ad); 100 /* Force umask for parMal writes made in the edit phase */ 101 (void)umask(077);
12.
vipw.c (3/3)
103 for (;;) { 118 prina("re-‐edit the password file? "); 104 switch (pw_edit(0)) { 119 fflush(stdout); 105 case -‐1: 120 if ((line = fgetln(stdin, &len)) == NULL) { 106 pw_fini(); 121 pw_fini(); 107 err(1, "pw_edit()"); 122 err(1, "fgetln()"); 108 case 0: 123 } 109 pw_fini(); 124 if (len > 0 && (*line == 'N' || *line == 'n')) 110 errx(0, "no changes made"); 125 break; 111 default: 126 } 112 break; 127 pw_fini(); 113 } 128 exit(0); 114 if (pw_mkdb(NULL) == 0) { 129 } 115 pw_fini(); パスワードファイルを再構築に失 116 errx(0, "password list updated"); 敗したら,再度ファイルを編集する 117 } か確認する pw_edit() ? pw_mkdb() ?
13.
vipw.c まとめ
オプション処理.-‐dだけ キニナル
14.
pw_init() (1/2)
93 int 94 pw_init(const char *dir, const char *master) 95 { 96 #if 0 97 struct rlimit rlim; 98 #endif 99 100 if (dir == NULL) { 101 strcpy(passwd_dir, _PATH_ETC); -‐dオプションが無ければ 102 } else { master.passwdファイルがあるディ 103 if (strlen(dir) >= sizeof(passwd_dir)) { レクトリの初期値として_PATH_ETC 104 errno = ENAMETOOLONG; を使う(/usr/include/pwd.h) 105 return (-‐1); 106 } 107 strcpy(passwd_dir, dir); 108 } 109
15.
pw_init() (2/2) 110
if (master == NULL) { 111 if (dir == NULL) { 112 strcpy(masterpasswd, _PATH_MASTERPASSWD); 113 } else if (snprina(masterpasswd, sizeof(masterpasswd), "%s/%s", 114 passwd_dir, _MASTERPASSWD) > (int)sizeof(masterpasswd)) { 115 errno = ENAMETOOLONG; 116 return (-‐1); 117 } 118 } else { 119 if (strlen(master) >= sizeof(masterpasswd)) { 120 errno = ENAMETOOLONG; 121 return (-‐1); 122 } master.passwdのファイル名を指定す 123 strcpy(masterpasswd, master); ることができるが,vipw.cからはNULL 124 } なので_PATH_MASTERPASSWD (/usr/include/pwd.h)を使う
16.
vipw.c まとめ
オプション処理.-‐dだけ パスワードファイルの場所を探す
17.
pw_lock()
166 int 167 pw_lock(void) 168 { 169 170 if (*masterpasswd == '0') 171 return (-‐1); <snip> 179 for (;;) { 180 struct stat st; 181 182 lockfd = open(masterpasswd, O_RDONLY, 0); master.passwdファイルを開いて 183 if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -‐1) 184 err(1, "%s", masterpasswd); 185 /* XXX vulnerable to race condiMons */ 186 if (flock(lockfd, LOCK_EX|LOCK_NB) == -‐1) { ロックする 187 if (errno == EWOULDBLOCK) { 188 errx(1, "the password db file is busy"); 189 } else { 190 err(1, "could not lock the passwd file: "); 191 } 192 } <snip>
18.
vipw.c まとめ
オプション処理.-‐dだけ パスワードファイルの場所を探す パスワードファイルをロックする
19.
pw_tmp() (1/2)
213 int 214 pw_tmp(int mfd) 215 { 216 char buf[8192]; 217 ssize_t nr; 218 const char *p; 219 int ad; 220 221 if (*masterpasswd == '0') master.passwdファイルがあるディ 222 return (-‐1); レクトリに一時ファイルpw.XXXXXX 223 if ((p = strrchr(masterpasswd, '/'))) (Xは乱数に置き換え)を作成. 224 ++p; 225 else 226 p = masterpasswd; 227 if (snprina(tempname, sizeof(tempname), "%.*spw.XXXXXX", 228 (int)(p -‐ masterpasswd), masterpasswd) >= (int)sizeof(tempname)) { 229 errno = ENAMETOOLONG; 230 return (-‐1); 231 } 232 if ((ad = mkstemp(tempname)) == -‐1) 233 return (-‐1);
20.
pw_tmp() (2/2)
234 if (mfd != -‐1) { 235 while ((nr = read(mfd, buf, sizeof(buf))) > 0) master.passwdの中身を 236 if (write(ad, buf, (size_t)nr) != nr) 一時ファイルにコピー 237 break; 238 if (nr != 0) { 239 unlink(tempname); 240 *tempname = '0'; 241 close(ad); 242 return (-‐1); 243 } 244 } 245 return (ad); 246 }
21.
vipw.c まとめ
オプション処理.-‐dだけ パスワードファイルの場所を探す パスワードファイルをロックする パスワードファイルと同じディレク トリに作業用ファイルを作って, 中身をコピーする
22.
pw_edit() (1/4)
288 int 289 pw_edit(int notsetuid) 290 { <snip> 297 if ((editor = getenv("EDITOR")) == NULL) パスワードファイルを編集する 298 editor = _PATH_VI; エディタを設定.EDITOR変数の 299 if (stat(tempname, &st1) == -‐1) 300 return (-‐1); 設定が無ければviを設定 <snip>
23.
pw_edit() (2/4)
104 switch (pw_edit(0)) { 309 switch ((editpid = fork())) { 105 case -‐1: 310 case -‐1: vipw.c 106 pw_fini(); 311 return (-‐1); 107 e rr(1, "pw_edit()"); 312 case 0: <snip> 313 sigacMon(SIGINT, &sa_int, NULL); 113 } 314 sigacMon(SIGQUIT, &sa_quit, NULL); 315 sigprocmask(SIG_SETMASK, &oldsigset, NULL); 316 if (notsetuid) { master.passwdをコピーした一時 317 (void)setgid(getgid()); ファイル(tempname)を引数にし 318 (void)setuid(getuid()); てエディタ(editor)を開く. 319 } 320 errno = 0; 321 execlp(editor, basename(editor), tempname, (char *)NULL); 322 _exit(errno); 323 default: 後述 324 /* parent */ 325 break; 326 }
24.
pw_edit() (3/4)
327 for (;;) { エラーだったらファイルを削除し 328 if (waitpid(editpid, &pstat, WUNTRACED) == -‐1) { て終了する 329 if (errno == EINTR) 330 conMnue; 331 unlink(tempname); 332 editpid = -‐1; 333 break; execlp()が正常終了したら一時 334 } else if (WIFSTOPPED(pstat)) { ファイルを残して終了する 335 raise(WSTOPSIG(pstat)); 336 } else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0) { 337 editpid = -‐1; 338 break; 339 } else { 340 unlink(tempname); 341 editpid = -‐1; 342 break; execlp()が異常終了したら一時 343 } ファイルを削除して終了する 344 } waitpid()でエラーだったり,execlp()が異常終了したらファイルを削除する
25.
pw_edit() (4/4)
345 sigacMon(SIGINT, &sa_int, NULL); 346 sigacMon(SIGQUIT, &sa_quit, NULL); waitpid()でエラーだったりexeclp()で不 347 sigprocmask(SIG_SETMASK, &oldsigset, NULL); 正終了していたらtempnameファイルは 348 if (stat(tempname, &st2) == -‐1) { 349 return (-‐1); 無いのでstat()が-‐1になりreturn(-‐1) 350 } 351 return (st1.st_mMme != st2.st_mMme); execlp()が正常終了したら一時 352 } ファイルを残して終了する 104 switch (pw_edit(0)) { vipw.c EDITORの終了を失敗し 105 case -‐1: たり,execlp()でEDITOR 106 pw_fini(); が不正終了した場合 107 err(1, "pw_edit()"); 108 case 0: 変更がない時 109 pw_fini(); 110 errx(0, "no changes made"); 111 default: 変更がある時 112 break; 113 }
26.
後述のアレ pw_edit()のところで
execlp(editor, basename(editor), tempname, (char *)NULL); ↓ execlp(“vipw” “vipw”, “pw.XXXXX”, (char *)NULL); こうなって,結局のところ # vipw pw.XXXXX な感じになる
27.
そういえば • vipwコマンドに”pw.XXXXX”引数は不正なので
usage() while ((ch = getopt(argc, argv, "d:")) != -‐1) switch (ch) { … default: usage(); } # env EDITOR=vipw vipw つまりこうなる usage: vipw [-‐d directory] vipw: pw_edit(): No such file or directory
28.
EDITORが不正終了したので
327 for (;;) { 328 if (waitpid(editpid, &pstat, WUNTRACED) == -‐1) { 329 if (errno == EINTR) pw_edit() 330 conMnue; 331 unlink(tempname); 332 editpid = -‐1; 333 break; 334 } else if (WIFSTOPPED(pstat)) { 335 raise(WSTOPSIG(pstat)); 336 } else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0) { 337 editpid = -‐1; 338 break; 339 } else { 340 unlink(tempname); 341 editpid = -‐1; 342 break; execlp()が不正終了したら一時 343 } ファイルを削除して終了する 344 }
29.
pw_edit()を振り返って
345 sigacMon(SIGINT, &sa_int, NULL); 346 sigacMon(SIGQUIT, &sa_quit, NULL); execlp()で不正終了していたら 347 sigprocmask(SIG_SETMASK, &oldsigset, NULL); tempnameファイルは無いので 348 if (stat(tempname, &st2) == -‐1) { 349 return (-‐1); stat()が-‐1になりreturn(-‐1) 350 } 351 return (st1.st_mMme != st2.st_mMme); 352 } 104 switch (pw_edit(0)) { vipw.c EDITORの終了を失敗し 105 case -‐1: たり,execlp()でEDITOR 106 pw_fini(); が不正終了した場合 107 err(1, "pw_edit()"); 108 case 0: 109 pw_fini(); 110 errx(0, "no changes made"); 111 default: # env EDITOR=vipw vipw 112 break; usage: vipw [-‐d directory] 113 } vipw: pw_edit(): No such file or directory
30.
vipw.c まとめ
オプション処理.-‐dだけ パスワードファイルの場所を探す パスワードファイルをロックする パスワードファイルと同じディレク トリに作業用ファイルを作って, 中身をコピーする EDITORで指定したコマンドに作業用ファイルを渡したり, コマンドが異常終了したら作業ファイルを消したり, 作業ファイルの更新時間を確認したり, 作業ファイルが消されてたら更新時間を確認できない のでエラーを返したり, する.
31.
(参考) env EDITOR=nano
vipwのとき pw.XXXXX の部分
32.
pw_mkdb() • 省略
33.
まとめ • vipwは内部でexeclp()を使ってEDITORを実行し,引
数に作業用ファイルを渡す • 1つ目のエラーはEDITOR=vipwの時にvipwコマンド が-‐d以外の引数を許容しないエラー • 2つ目のエラーは,1つ目のエラーに起因して作業用 ファイルを消し,その後の処理で作業用ファイルを 見に行こうとするが存在しないので出るエラー # env EDITOR=vipw vipw usage: vipw [-‐d directory] vipw: pw_edit(): No such file or directory
Baixar agora