【SSH】SSHログイン時のチェック内容について
背景
前提
- OpenSSH バージョン: V_7_6_P1
- ログインユーザー名: Chiara
- ssh_config にて 厳格モードが有効である
- StrictModes yes ないし、コメントアウトされている
詳細
authorized_key の所有者・権限チェック
- 所有者(以下、いずれかを満たす)
- rootユーザー(ないし、root相当ユーザー)である
- 所有者が、ログインするユーザーになっている
- 権限
- グループ, その他ユーザーに書き込み権限がない
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/auth.c#L467
static FILE * auth_openfile(const char *file, struct passwd *pw, int strict_modes, int log_missing, char *file_type) { /// 一部省略 /// if (strict_modes && safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) { fclose(f); logit("Authentication refused: %s", line); auth_debug_add("Ignored %s: %s", file_type, line); return NULL; } /// 一部省略 /// }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1673
int safe_path_fd(int fd, const char *file, struct passwd *pw, char *err, size_t errlen) { struct stat st; /* check the open file to avoid races */ if (fstat(fd, &st) < 0) { snprintf(err, errlen, "cannot stat file %s: %s", file, strerror(errno)); return -1; } return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1608
int safe_path(const char *name, struct stat *stp, const char *pw_dir, uid_t uid, char *err, size_t errlen) { /// 一部省略 /// if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || (stp->st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for file %s", buf); return -1; } /// 一部省略 /// }
.ssh、ホームディレクトリの所有者・権限チェック
- 所有者(以下、いずれかを満たす)
- rootユーザー(ないし、root相当ユーザー)である
- 所有者が、ログインするユーザーになっている
- 権限
- グループ, その他ユーザーに書き込み権限がない
- チェック範囲
- /home/Chiara/.ssh
- /home/Chiara
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/auth.c#L467
static FILE * auth_openfile(const char *file, struct passwd *pw, int strict_modes, int log_missing, char *file_type) { /// 一部省略 /// if (strict_modes && safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) { fclose(f); logit("Authentication refused: %s", line); auth_debug_add("Ignored %s: %s", file_type, line); return NULL; } /// 一部省略 /// }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1673
int safe_path_fd(int fd, const char *file, struct passwd *pw, char *err, size_t errlen) { struct stat st; /* check the open file to avoid races */ if (fstat(fd, &st) < 0) { snprintf(err, errlen, "cannot stat file %s: %s", file, strerror(errno)); return -1; } return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); }
https://github.com/openssh/openssh-portable/blob/V_7_6_P1/misc.c#L1608
int safe_path(const char *name, struct stat *stp, const char *pw_dir, uid_t uid, char *err, size_t errlen) { /// 一部省略 /// /* for each component of the canonical path, walking upwards */ for (;;) { if ((cp = dirname(buf)) == NULL) { snprintf(err, errlen, "dirname() failed"); return -1; } strlcpy(buf, cp, sizeof(buf)); if (stat(buf, &st) < 0 || (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || (st.st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for directory %s", buf); return -1; } /* If are past the homedir then we can stop */ if (comparehome && strcmp(homedir, buf) == 0) break; /* * dirname should always complete with a "/" path, * but we can be paranoid and check for "." too */ if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) break; } /// 一部省略 /// }
今後について
- authorized_key が rootユーザーでもいいような結果になったが、おそらく間違っていると思われます
- 今後調査をして、正しいものに修正します