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