1 /* 2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * All rights reserved 5 * As far as I am concerned, the code I have written for this software 6 * can be used freely for any purpose. Any derived versions of this 7 * software must be clearly marked as such, and if the derived work is 8 * incompatible with the protocol description in the RFC file, it must be 9 * called by a name other than "ssh" or "Secure Shell". 10 */ 11 12 #include "includes.h" 13 RCSID("$OpenBSD: auth-options.c,v 1.33 2005/12/08 18:34:11 reyk Exp $"); 14 15 #include "xmalloc.h" 16 #include "match.h" 17 #include "log.h" 18 #include "canohost.h" 19 #include "channels.h" 20 #include "auth-options.h" 21 #include "servconf.h" 22 #include "misc.h" 23 #include "monitor_wrap.h" 24 #include "auth.h" 25 26 /* Flags set authorized_keys flags */ 27 int no_port_forwarding_flag = 0; 28 int no_agent_forwarding_flag = 0; 29 int no_x11_forwarding_flag = 0; 30 int no_pty_flag = 0; 31 32 /* "command=" option. */ 33 char *forced_command = NULL; 34 35 /* "environment=" options. */ 36 struct envstring *custom_environment = NULL; 37 38 /* "tunnel=" option. */ 39 int forced_tun_device = -1; 40 41 extern ServerOptions options; 42 43 void 44 auth_clear_options(void) 45 { 46 no_agent_forwarding_flag = 0; 47 no_port_forwarding_flag = 0; 48 no_pty_flag = 0; 49 no_x11_forwarding_flag = 0; 50 while (custom_environment) { 51 struct envstring *ce = custom_environment; 52 custom_environment = ce->next; 53 xfree(ce->s); 54 xfree(ce); 55 } 56 if (forced_command) { 57 xfree(forced_command); 58 forced_command = NULL; 59 } 60 forced_tun_device = -1; 61 channel_clear_permitted_opens(); 62 auth_debug_reset(); 63 } 64 65 /* 66 * return 1 if access is granted, 0 if not. 67 * side effect: sets key option flags 68 */ 69 int 70 auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 71 { 72 const char *cp; 73 int i; 74 75 /* reset options */ 76 auth_clear_options(); 77 78 if (!opts) 79 return 1; 80 81 while (*opts && *opts != ' ' && *opts != '\t') { 82 cp = "no-port-forwarding"; 83 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 84 auth_debug_add("Port forwarding disabled."); 85 no_port_forwarding_flag = 1; 86 opts += strlen(cp); 87 goto next_option; 88 } 89 cp = "no-agent-forwarding"; 90 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 91 auth_debug_add("Agent forwarding disabled."); 92 no_agent_forwarding_flag = 1; 93 opts += strlen(cp); 94 goto next_option; 95 } 96 cp = "no-X11-forwarding"; 97 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 98 auth_debug_add("X11 forwarding disabled."); 99 no_x11_forwarding_flag = 1; 100 opts += strlen(cp); 101 goto next_option; 102 } 103 cp = "no-pty"; 104 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 105 auth_debug_add("Pty allocation disabled."); 106 no_pty_flag = 1; 107 opts += strlen(cp); 108 goto next_option; 109 } 110 cp = "command=\""; 111 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 112 opts += strlen(cp); 113 forced_command = xmalloc(strlen(opts) + 1); 114 i = 0; 115 while (*opts) { 116 if (*opts == '"') 117 break; 118 if (*opts == '\\' && opts[1] == '"') { 119 opts += 2; 120 forced_command[i++] = '"'; 121 continue; 122 } 123 forced_command[i++] = *opts++; 124 } 125 if (!*opts) { 126 debug("%.100s, line %lu: missing end quote", 127 file, linenum); 128 auth_debug_add("%.100s, line %lu: missing end quote", 129 file, linenum); 130 xfree(forced_command); 131 forced_command = NULL; 132 goto bad_option; 133 } 134 forced_command[i] = 0; 135 auth_debug_add("Forced command: %.900s", forced_command); 136 opts++; 137 goto next_option; 138 } 139 cp = "environment=\""; 140 if (options.permit_user_env && 141 strncasecmp(opts, cp, strlen(cp)) == 0) { 142 char *s; 143 struct envstring *new_envstring; 144 145 opts += strlen(cp); 146 s = xmalloc(strlen(opts) + 1); 147 i = 0; 148 while (*opts) { 149 if (*opts == '"') 150 break; 151 if (*opts == '\\' && opts[1] == '"') { 152 opts += 2; 153 s[i++] = '"'; 154 continue; 155 } 156 s[i++] = *opts++; 157 } 158 if (!*opts) { 159 debug("%.100s, line %lu: missing end quote", 160 file, linenum); 161 auth_debug_add("%.100s, line %lu: missing end quote", 162 file, linenum); 163 xfree(s); 164 goto bad_option; 165 } 166 s[i] = 0; 167 auth_debug_add("Adding to environment: %.900s", s); 168 debug("Adding to environment: %.900s", s); 169 opts++; 170 new_envstring = xmalloc(sizeof(struct envstring)); 171 new_envstring->s = s; 172 new_envstring->next = custom_environment; 173 custom_environment = new_envstring; 174 goto next_option; 175 } 176 cp = "from=\""; 177 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 178 const char *remote_ip = get_remote_ipaddr(); 179 const char *remote_host = get_canonical_hostname( 180 options.use_dns); 181 char *patterns = xmalloc(strlen(opts) + 1); 182 183 opts += strlen(cp); 184 i = 0; 185 while (*opts) { 186 if (*opts == '"') 187 break; 188 if (*opts == '\\' && opts[1] == '"') { 189 opts += 2; 190 patterns[i++] = '"'; 191 continue; 192 } 193 patterns[i++] = *opts++; 194 } 195 if (!*opts) { 196 debug("%.100s, line %lu: missing end quote", 197 file, linenum); 198 auth_debug_add("%.100s, line %lu: missing end quote", 199 file, linenum); 200 xfree(patterns); 201 goto bad_option; 202 } 203 patterns[i] = 0; 204 opts++; 205 if (match_host_and_ip(remote_host, remote_ip, 206 patterns) != 1) { 207 xfree(patterns); 208 logit("Authentication tried for %.100s with " 209 "correct key but not from a permitted " 210 "host (host=%.200s, ip=%.200s).", 211 pw->pw_name, remote_host, remote_ip); 212 auth_debug_add("Your host '%.200s' is not " 213 "permitted to use this key for login.", 214 remote_host); 215 /* deny access */ 216 return 0; 217 } 218 xfree(patterns); 219 /* Host name matches. */ 220 goto next_option; 221 } 222 cp = "permitopen=\""; 223 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 224 char *host, *p; 225 u_short port; 226 char *patterns = xmalloc(strlen(opts) + 1); 227 228 opts += strlen(cp); 229 i = 0; 230 while (*opts) { 231 if (*opts == '"') 232 break; 233 if (*opts == '\\' && opts[1] == '"') { 234 opts += 2; 235 patterns[i++] = '"'; 236 continue; 237 } 238 patterns[i++] = *opts++; 239 } 240 if (!*opts) { 241 debug("%.100s, line %lu: missing end quote", 242 file, linenum); 243 auth_debug_add("%.100s, line %lu: missing " 244 "end quote", file, linenum); 245 xfree(patterns); 246 goto bad_option; 247 } 248 patterns[i] = 0; 249 opts++; 250 p = patterns; 251 host = hpdelim(&p); 252 if (host == NULL || strlen(host) >= NI_MAXHOST) { 253 debug("%.100s, line %lu: Bad permitopen " 254 "specification <%.100s>", file, linenum, 255 patterns); 256 auth_debug_add("%.100s, line %lu: " 257 "Bad permitopen specification", file, 258 linenum); 259 xfree(patterns); 260 goto bad_option; 261 } 262 host = cleanhostname(host); 263 if (p == NULL || (port = a2port(p)) == 0) { 264 debug("%.100s, line %lu: Bad permitopen port " 265 "<%.100s>", file, linenum, p ? p : ""); 266 auth_debug_add("%.100s, line %lu: " 267 "Bad permitopen port", file, linenum); 268 xfree(patterns); 269 goto bad_option; 270 } 271 if (options.allow_tcp_forwarding) 272 channel_add_permitted_opens(host, port); 273 xfree(patterns); 274 goto next_option; 275 } 276 cp = "tunnel=\""; 277 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 278 char *tun = NULL; 279 opts += strlen(cp); 280 tun = xmalloc(strlen(opts) + 1); 281 i = 0; 282 while (*opts) { 283 if (*opts == '"') 284 break; 285 tun[i++] = *opts++; 286 } 287 if (!*opts) { 288 debug("%.100s, line %lu: missing end quote", 289 file, linenum); 290 auth_debug_add("%.100s, line %lu: missing end quote", 291 file, linenum); 292 xfree(tun); 293 forced_tun_device = -1; 294 goto bad_option; 295 } 296 tun[i] = 0; 297 forced_tun_device = a2tun(tun, NULL); 298 xfree(tun); 299 if (forced_tun_device == SSH_TUNID_ERR) { 300 debug("%.100s, line %lu: invalid tun device", 301 file, linenum); 302 auth_debug_add("%.100s, line %lu: invalid tun device", 303 file, linenum); 304 forced_tun_device = -1; 305 goto bad_option; 306 } 307 auth_debug_add("Forced tun device: %d", forced_tun_device); 308 opts++; 309 goto next_option; 310 } 311 next_option: 312 /* 313 * Skip the comma, and move to the next option 314 * (or break out if there are no more). 315 */ 316 if (!*opts) 317 fatal("Bugs in auth-options.c option processing."); 318 if (*opts == ' ' || *opts == '\t') 319 break; /* End of options. */ 320 if (*opts != ',') 321 goto bad_option; 322 opts++; 323 /* Process the next option. */ 324 } 325 326 if (!use_privsep) 327 auth_debug_send(); 328 329 /* grant access */ 330 return 1; 331 332 bad_option: 333 logit("Bad options in %.100s file, line %lu: %.50s", 334 file, linenum, opts); 335 auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 336 file, linenum, opts); 337 338 if (!use_privsep) 339 auth_debug_send(); 340 341 /* deny access */ 342 return 0; 343 } 344