OpenSSHのchrootの動作
opensshが接続を受け付けて、chrootする際の挙動に関するメモ
- session.cを見る
do_setusercontext(struct passwd *pw)
- if (getuid() == 0 || geteuid() == 0) ... 実行ユーザーがrootであることのチェック
- if (setlogin(pw->pw_name) < 0)
- if (setgid(pw->pw_gid) < 0) {
- if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
- permanently_set_uid(pw);
- safely_chroot()
# passwdのエントリと現在の実行ユーザー/IDが同一かどうか # rootのまんまでないようにする? if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
ユーティリティ的な関数
- tilde_expand_filename(options.chroot_directory, pw->pw_uid)
- 文字列内のチルダの展開
- chroot_path = percent_expand(tmp, "h", pw->pw_dir, "u", pw->pw_name, (char *)NULL))
- %表記の展開。 %u と %h をサポート
if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { perror("unable to set user context"); exit(1)
safely_chroot()
opensshのchrootの肝。
- if (*path != '/') ... 絶対パスや否かをチェック
- パスの長さのチェック
- 各々のパスコンポーネントがディレクトリとして存在するかどうかをチェックする
- if( st.st_uid != 0 || (st.st_mode & 022) != 0)... パーミッションがrootで755かどうかのチェック
- if (!S_ISDIR(st.st_mode)) ... ディレクトリかどうかのチェック
- chdir(path)
- chroot(path) ... chdirしてからchroot(2)
- chdir(/) ... chrootした後、/にすることでchrootが有効かどうか試している
その他
- if (setpcred(pw->pw_name, (char **)NULL) == -1)
- do_pam_setcred(use_privsep)