diff options
Diffstat (limited to 'auth.c')
-rw-r--r-- | auth.c | 180 |
1 files changed, 175 insertions, 5 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.125 2018/01/08 15:21:49 markus Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.126 2018/03/03 03:15:51 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -74,12 +74,14 @@ | |||
74 | #include "authfile.h" | 74 | #include "authfile.h" |
75 | #include "ssherr.h" | 75 | #include "ssherr.h" |
76 | #include "compat.h" | 76 | #include "compat.h" |
77 | #include "channels.h" | ||
77 | 78 | ||
78 | /* import */ | 79 | /* import */ |
79 | extern ServerOptions options; | 80 | extern ServerOptions options; |
80 | extern int use_privsep; | 81 | extern int use_privsep; |
81 | extern Buffer loginmsg; | 82 | extern Buffer loginmsg; |
82 | extern struct passwd *privsep_pw; | 83 | extern struct passwd *privsep_pw; |
84 | extern struct sshauthopt *auth_opts; | ||
83 | 85 | ||
84 | /* Debugging messages */ | 86 | /* Debugging messages */ |
85 | Buffer auth_debug; | 87 | Buffer auth_debug; |
@@ -386,10 +388,8 @@ auth_maxtries_exceeded(Authctxt *authctxt) | |||
386 | * Check whether root logins are disallowed. | 388 | * Check whether root logins are disallowed. |
387 | */ | 389 | */ |
388 | int | 390 | int |
389 | auth_root_allowed(const char *method) | 391 | auth_root_allowed(struct ssh *ssh, const char *method) |
390 | { | 392 | { |
391 | struct ssh *ssh = active_state; /* XXX */ | ||
392 | |||
393 | switch (options.permit_root_login) { | 393 | switch (options.permit_root_login) { |
394 | case PERMIT_YES: | 394 | case PERMIT_YES: |
395 | return 1; | 395 | return 1; |
@@ -400,7 +400,7 @@ auth_root_allowed(const char *method) | |||
400 | return 1; | 400 | return 1; |
401 | break; | 401 | break; |
402 | case PERMIT_FORCED_ONLY: | 402 | case PERMIT_FORCED_ONLY: |
403 | if (forced_command) { | 403 | if (auth_opts->force_command != NULL) { |
404 | logit("Root login accepted for forced command."); | 404 | logit("Root login accepted for forced command."); |
405 | return 1; | 405 | return 1; |
406 | } | 406 | } |
@@ -993,3 +993,173 @@ subprocess(const char *tag, struct passwd *pw, const char *command, | |||
993 | *child = f; | 993 | *child = f; |
994 | return pid; | 994 | return pid; |
995 | } | 995 | } |
996 | |||
997 | /* These functions link key/cert options to the auth framework */ | ||
998 | |||
999 | /* Log sshauthopt options locally and (optionally) for remote transmission */ | ||
1000 | void | ||
1001 | auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) | ||
1002 | { | ||
1003 | int do_env = options.permit_user_env && opts->nenv > 0; | ||
1004 | int do_permitopen = opts->npermitopen > 0 && | ||
1005 | (options.allow_tcp_forwarding & FORWARD_LOCAL) != 0; | ||
1006 | size_t i; | ||
1007 | char msg[1024], tbuf[32]; | ||
1008 | |||
1009 | snprintf(tbuf, sizeof(tbuf), "%d", opts->force_tun_device); | ||
1010 | /* Try to keep this alphabetically sorted */ | ||
1011 | snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s", | ||
1012 | opts->permit_agent_forwarding_flag ? " agent-forwarding" : "", | ||
1013 | opts->force_command == NULL ? "" : " command", | ||
1014 | do_env ? " environment" : "", | ||
1015 | do_permitopen ? " permitopen" : "", | ||
1016 | opts->permit_port_forwarding_flag ? " port-forwarding" : "", | ||
1017 | opts->cert_principals == NULL ? "" : " principals", | ||
1018 | opts->permit_pty_flag ? " pty" : "", | ||
1019 | opts->force_tun_device == -1 ? "" : " tun=", | ||
1020 | opts->force_tun_device == -1 ? "" : tbuf, | ||
1021 | opts->permit_user_rc ? " user-rc" : "", | ||
1022 | opts->permit_x11_forwarding_flag ? " x11-forwarding" : ""); | ||
1023 | |||
1024 | debug("%s: %s", loc, msg); | ||
1025 | if (do_remote) | ||
1026 | auth_debug_add("%s: %s", loc, msg); | ||
1027 | |||
1028 | if (options.permit_user_env) { | ||
1029 | for (i = 0; i < opts->nenv; i++) { | ||
1030 | debug("%s: environment: %s", loc, opts->env[i]); | ||
1031 | if (do_remote) { | ||
1032 | auth_debug_add("%s: environment: %s", | ||
1033 | loc, opts->env[i]); | ||
1034 | } | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | /* Go into a little more details for the local logs. */ | ||
1039 | if (opts->cert_principals != NULL) { | ||
1040 | debug("%s: authorized principals: \"%s\"", | ||
1041 | loc, opts->cert_principals); | ||
1042 | } | ||
1043 | if (opts->force_command != NULL) | ||
1044 | debug("%s: forced command: \"%s\"", loc, opts->force_command); | ||
1045 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) { | ||
1046 | for (i = 0; i < opts->npermitopen; i++) { | ||
1047 | debug("%s: permitted open: %s", | ||
1048 | loc, opts->permitopen[i]); | ||
1049 | } | ||
1050 | } | ||
1051 | } | ||
1052 | |||
1053 | /* Activate a new set of key/cert options; merging with what is there. */ | ||
1054 | int | ||
1055 | auth_activate_options(struct ssh *ssh, struct sshauthopt *opts) | ||
1056 | { | ||
1057 | struct sshauthopt *old = auth_opts; | ||
1058 | const char *emsg = NULL; | ||
1059 | |||
1060 | debug("%s: setting new authentication options", __func__); | ||
1061 | if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) { | ||
1062 | error("Inconsistent authentication options: %s", emsg); | ||
1063 | return -1; | ||
1064 | } | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | /* Disable forwarding, etc for the session */ | ||
1069 | void | ||
1070 | auth_restrict_session(struct ssh *ssh) | ||
1071 | { | ||
1072 | struct sshauthopt *restricted; | ||
1073 | |||
1074 | debug("%s: restricting session", __func__); | ||
1075 | |||
1076 | /* A blank sshauthopt defaults to permitting nothing */ | ||
1077 | restricted = sshauthopt_new(); | ||
1078 | restricted->restricted = 1; | ||
1079 | |||
1080 | if (auth_activate_options(ssh, restricted) != 0) | ||
1081 | fatal("%s: failed to restrict session", __func__); | ||
1082 | sshauthopt_free(restricted); | ||
1083 | } | ||
1084 | |||
1085 | int | ||
1086 | auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw, | ||
1087 | struct sshauthopt *opts, int allow_cert_authority, const char *loc) | ||
1088 | { | ||
1089 | const char *remote_ip = ssh_remote_ipaddr(ssh); | ||
1090 | const char *remote_host = auth_get_canonical_hostname(ssh, | ||
1091 | options.use_dns); | ||
1092 | |||
1093 | /* Consistency checks */ | ||
1094 | if (opts->cert_principals != NULL && !opts->cert_authority) { | ||
1095 | debug("%s: principals on non-CA key", loc); | ||
1096 | auth_debug_add("%s: principals on non-CA key", loc); | ||
1097 | /* deny access */ | ||
1098 | return -1; | ||
1099 | } | ||
1100 | /* cert-authority flag isn't valid in authorized_principals files */ | ||
1101 | if (!allow_cert_authority && opts->cert_authority) { | ||
1102 | debug("%s: cert-authority flag invalid here", loc); | ||
1103 | auth_debug_add("%s: cert-authority flag invalid here", loc); | ||
1104 | /* deny access */ | ||
1105 | return -1; | ||
1106 | } | ||
1107 | |||
1108 | /* Perform from= checks */ | ||
1109 | if (opts->required_from_host_keys != NULL) { | ||
1110 | switch (match_host_and_ip(remote_host, remote_ip, | ||
1111 | opts->required_from_host_keys )) { | ||
1112 | case 1: | ||
1113 | /* Host name matches. */ | ||
1114 | break; | ||
1115 | case -1: | ||
1116 | default: | ||
1117 | debug("%s: invalid from criteria", loc); | ||
1118 | auth_debug_add("%s: invalid from criteria", loc); | ||
1119 | /* FALLTHROUGH */ | ||
1120 | case 0: | ||
1121 | logit("%s: Authentication tried for %.100s with " | ||
1122 | "correct key but not from a permitted " | ||
1123 | "host (host=%.200s, ip=%.200s, required=%.200s).", | ||
1124 | loc, pw->pw_name, remote_host, remote_ip, | ||
1125 | opts->required_from_host_keys); | ||
1126 | auth_debug_add("%s: Your host '%.200s' is not " | ||
1127 | "permitted to use this key for login.", | ||
1128 | loc, remote_host); | ||
1129 | /* deny access */ | ||
1130 | return -1; | ||
1131 | } | ||
1132 | } | ||
1133 | /* Check source-address restriction from certificate */ | ||
1134 | if (opts->required_from_host_cert != NULL) { | ||
1135 | switch (addr_match_cidr_list(remote_ip, | ||
1136 | opts->required_from_host_cert)) { | ||
1137 | case 1: | ||
1138 | /* accepted */ | ||
1139 | break; | ||
1140 | case -1: | ||
1141 | default: | ||
1142 | /* invalid */ | ||
1143 | error("%s: Certificate source-address invalid", | ||
1144 | loc); | ||
1145 | /* FALLTHROUGH */ | ||
1146 | case 0: | ||
1147 | logit("%s: Authentication tried for %.100s with valid " | ||
1148 | "certificate but not from a permitted source " | ||
1149 | "address (%.200s).", loc, pw->pw_name, remote_ip); | ||
1150 | auth_debug_add("%s: Your address '%.200s' is not " | ||
1151 | "permitted to use this certificate for login.", | ||
1152 | loc, remote_ip); | ||
1153 | return -1; | ||
1154 | } | ||
1155 | } | ||
1156 | /* | ||
1157 | * | ||
1158 | * XXX this is spammy. We should report remotely only for keys | ||
1159 | * that are successful in actual auth attempts, and not PK_OK | ||
1160 | * tests. | ||
1161 | */ | ||
1162 | auth_log_authopts(loc, opts, 1); | ||
1163 | |||
1164 | return 0; | ||
1165 | } | ||