Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
env EDITOR=vipw vipwしてみた
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Ogata Yasuhiko
March 05, 2013
280
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
env EDITOR=vipw vipwしてみた
Ogata Yasuhiko
March 05, 2013
Featured
See All Featured
We Are The Robots
honzajavorek
0
380
Building AI with AI
inesmontani
PRO
1
1.2k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Speed Design
sergeychernyshev
33
2.1k
sira's awesome portfolio website redesign presentation
elsirapls
0
420
Practical Orchestrator
shlominoach
192
12k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
500
Mind Mapping
helmedeiros
1
360
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
330
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
910
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
280
Are puppies a ranking factor?
jonoalderson
2
3.9k
Transcript
env EDITOR=vipw vipw してみた @yogata
vipw • ユーザ追加・削除・情報変更する • vipw is 神
vipw useradd/adduser メリット Jviが使える 特に無い デメリット 特にない Luserとaddのどっちが 先かわからない
こんなにもすばらしいvipw • 使いたくなってきたはず • でも……viは慣れてないし…… env
EDITOR=XXX vipw
vipw と EDITOR変数 • env EDITOR=nano vipw
vipw と EDITOR変数 • env EDITOR=emacs vipw
vipw と EDITOR変数 ( ^o^) env EDITOR=emacs vipw →
emacsで開く ( ˘⊖˘) 。o( env EDITOR=vipw vipwしたらどうなるんだ) |Terminal.app| ┗(☋` )┓三 ( ◠‿◠ )☛ そこに気づいてしまったか ▂▅▇█▓▒░(’ω’)░▒▓█▇▅▂うわあああああああ
やってみる # env EDITOR=vipw vipw rootになるのを 忘れずに
やってみる
調べる • 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
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': 76 passwd_dir = optarg; 77 break; 78 case '?': 79 default: 80 usage(); 81 } 82 83 argc -‐= opMnd; 84 argv += opMnd; vipwのオプションは-‐dだけ.それ 以外のオプションが来たらusage() する
vipw.c (2/3) 85
86 if (argc != 0) 87 usage(); 88 89 if (pw_init(passwd_dir, NULL) == -‐1) 90 err(1, "pw_init()"); 91 if ((pfd = pw_lock()) == -‐1) { 92 pw_fini(); 93 err(1, "pw_lock()"); 94 } 95 if ((ad = pw_tmp(pfd)) == -‐1) { 96 pw_fini(); 97 err(1, "pw_tmp()"); 98 } 99 (void)close(ad); 100 /* Force umask for parMal writes made in the edit phase */ 101 (void)umask(077); pw_tmp() ? pw_lock() ? pw_init() ?
vipw.c (3/3) 103 for
(;;) { 104 switch (pw_edit(0)) { 105 case -‐1: 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 } 114 if (pw_mkdb(NULL) == 0) { 115 pw_fini(); 116 errx(0, "password list updated"); 117 } 118 prina("re-‐edit the password file? "); 119 fflush(stdout); 120 if ((line = fgetln(stdin, &len)) == NULL) { 121 pw_fini(); 122 err(1, "fgetln()"); 123 } 124 if (len > 0 && (*line == 'N' || *line == 'n')) 125 break; 126 } 127 pw_fini(); 128 exit(0); 129 } pw_edit() ? pw_mkdb() ? パスワードファイルを再構築に失 敗したら,再度ファイルを編集する か確認する
vipw.c まとめ オプション処理.-‐dだけ キニナル
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); 102 } else { 103 if (strlen(dir) >= sizeof(passwd_dir)) { 104 errno = ENAMETOOLONG; 105 return (-‐1); 106 } 107 strcpy(passwd_dir, dir); 108 } 109 -‐dオプションが無ければ master.passwdファイルがあるディ レクトリの初期値として_PATH_ETC を使う(/usr/include/pwd.h)
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 } 123 strcpy(masterpasswd, master); 124 } master.passwdのファイル名を指定す ることができるが,vipw.cからはNULL なので_PATH_MASTERPASSWD (/usr/include/pwd.h)を使う
vipw.c まとめ オプション処理.-‐dだけ パスワードファイルの場所を探す
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); 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> ロックする master.passwdファイルを開いて
vipw.c まとめ オプション処理.-‐dだけ パスワードファイルの場所を探す パスワードファイルをロックする
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') 222 return (-‐1); 223 if ((p = strrchr(masterpasswd, '/'))) 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); master.passwdファイルがあるディ レクトリに一時ファイルpw.XXXXXX (Xは乱数に置き換え)を作成.
pw_tmp() (2/2) 234 if
(mfd != -‐1) { 235 while ((nr = read(mfd, buf, sizeof(buf))) > 0) 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 } master.passwdの中身を 一時ファイルにコピー
vipw.c まとめ オプション処理.-‐dだけ パスワードファイルの場所を探す パスワードファイルをロックする パスワードファイルと同じディレク
トリに作業用ファイルを作って, 中身をコピーする
pw_edit() (1/4) 288 int 289 pw_edit(int
notsetuid) 290 { <snip> 297 if ((editor = getenv("EDITOR")) == NULL) 298 editor = _PATH_VI; 299 if (stat(tempname, &st1) == -‐1) 300 return (-‐1); <snip> パスワードファイルを編集する エディタを設定.EDITOR変数の 設定が無ければviを設定
pw_edit() (2/4) 309 switch
((editpid = fork())) { 310 case -‐1: 311 return (-‐1); 312 case 0: 313 sigacMon(SIGINT, &sa_int, NULL); 314 sigacMon(SIGQUIT, &sa_quit, NULL); 315 sigprocmask(SIG_SETMASK, &oldsigset, NULL); 316 if (notsetuid) { 317 (void)setgid(getgid()); 318 (void)setuid(getuid()); 319 } 320 errno = 0; 321 execlp(editor, basename(editor), tempname, (char *)NULL); 322 _exit(errno); 323 default: 324 /* parent */ 325 break; 326 } master.passwdをコピーした一時 ファイル(tempname)を引数にし てエディタ(editor)を開く. 104 switch (pw_edit(0)) { 105 case -‐1: 106 pw_fini(); 107 err(1, "pw_edit()"); <snip> 113 } vipw.c 後述
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; 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; 343 } 344 } execlp()が正常終了したら一時 ファイルを残して終了する execlp()が異常終了したら一時 ファイルを削除して終了する エラーだったらファイルを削除し て終了する waitpid()でエラーだったり,execlp()が異常終了したらファイルを削除する
pw_edit() (4/4) 345 sigacMon(SIGINT,
&sa_int, NULL); 346 sigacMon(SIGQUIT, &sa_quit, NULL); 347 sigprocmask(SIG_SETMASK, &oldsigset, NULL); 348 if (stat(tempname, &st2) == -‐1) { 349 return (-‐1); 350 } 351 return (st1.st_mMme != st2.st_mMme); 352 } execlp()が正常終了したら一時 ファイルを残して終了する 104 switch (pw_edit(0)) { 105 case -‐1: 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 } 変更がない時 変更がある時 vipw.c waitpid()でエラーだったりexeclp()で不 正終了していたらtempnameファイルは 無いのでstat()が-‐1になりreturn(-‐1) EDITORの終了を失敗し たり,execlp()でEDITOR が不正終了した場合
後述のアレ pw_edit()のところで execlp(editor, basename(editor), tempname, (char *)NULL);
↓ execlp(“vipw” “vipw”, “pw.XXXXX”, (char *)NULL); こうなって,結局のところ # vipw pw.XXXXX な感じになる
そういえば • 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 つまりこうなる
EDITORが不正終了したので 327 for (;;)
{ 328 if (waitpid(editpid, &pstat, WUNTRACED) == -‐1) { 329 if (errno == EINTR) 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; 343 } 344 } execlp()が不正終了したら一時 ファイルを削除して終了する pw_edit()
pw_edit()を振り返って 345 sigacMon(SIGINT, &sa_int,
NULL); 346 sigacMon(SIGQUIT, &sa_quit, NULL); 347 sigprocmask(SIG_SETMASK, &oldsigset, NULL); 348 if (stat(tempname, &st2) == -‐1) { 349 return (-‐1); 350 } 351 return (st1.st_mMme != st2.st_mMme); 352 } 104 switch (pw_edit(0)) { 105 case -‐1: 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 } vipw.c execlp()で不正終了していたら tempnameファイルは無いので stat()が-‐1になりreturn(-‐1) EDITORの終了を失敗し たり,execlp()でEDITOR が不正終了した場合 # env EDITOR=vipw vipw usage: vipw [-‐d directory] vipw: pw_edit(): No such file or directory
vipw.c まとめ オプション処理.-‐dだけ パスワードファイルの場所を探す パスワードファイルをロックする パスワードファイルと同じディレク
トリに作業用ファイルを作って, 中身をコピーする EDITORで指定したコマンドに作業用ファイルを渡したり, コマンドが異常終了したら作業ファイルを消したり, 作業ファイルの更新時間を確認したり, 作業ファイルが消されてたら更新時間を確認できない のでエラーを返したり, する.
(参考) env EDITOR=nano vipwのとき pw.XXXXX の部分
pw_mkdb() • 省略
まとめ • 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