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.26 2002/07/30 17:03:55 markus Exp $"); 14 15 #pragma ident "%Z%%M% %I% %E% SMI" 16 17 #include "xmalloc.h" 18 #include "match.h" 19 #include "log.h" 20 #include "canohost.h" 21 #include "channels.h" 22 #include "auth-options.h" 23 #include "servconf.h" 24 #include "misc.h" 25 #include "monitor_wrap.h" 26 #include "auth.h" 27 28 /* Flags set authorized_keys flags */ 29 int no_port_forwarding_flag = 0; 30 int no_agent_forwarding_flag = 0; 31 int no_x11_forwarding_flag = 0; 32 int no_pty_flag = 0; 33 34 /* "command=" option. */ 35 char *forced_command = NULL; 36 37 /* "environment=" options. */ 38 struct envstring *custom_environment = NULL; 39 40 extern ServerOptions options; 41 42 void 43 auth_clear_options(void) 44 { 45 no_agent_forwarding_flag = 0; 46 no_port_forwarding_flag = 0; 47 no_pty_flag = 0; 48 no_x11_forwarding_flag = 0; 49 while (custom_environment) { 50 struct envstring *ce = custom_environment; 51 custom_environment = ce->next; 52 xfree(ce->s); 53 xfree(ce); 54 } 55 if (forced_command) { 56 xfree(forced_command); 57 forced_command = NULL; 58 } 59 channel_clear_permitted_opens(); 60 auth_debug_reset(); 61 } 62 63 /* 64 * return 1 if access is granted, 0 if not. 65 * side effect: sets key option flags 66 */ 67 int 68 auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 69 { 70 const char *cp; 71 int i; 72 73 /* reset options */ 74 auth_clear_options(); 75 76 if (!opts) 77 return 1; 78 79 while (*opts && *opts != ' ' && *opts != '\t') { 80 cp = "no-port-forwarding"; 81 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 82 auth_debug_add("Port forwarding disabled."); 83 no_port_forwarding_flag = 1; 84 opts += strlen(cp); 85 goto next_option; 86 } 87 cp = "no-agent-forwarding"; 88 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 89 auth_debug_add("Agent forwarding disabled."); 90 no_agent_forwarding_flag = 1; 91 opts += strlen(cp); 92 goto next_option; 93 } 94 cp = "no-X11-forwarding"; 95 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 96 auth_debug_add("X11 forwarding disabled."); 97 no_x11_forwarding_flag = 1; 98 opts += strlen(cp); 99 goto next_option; 100 } 101 cp = "no-pty"; 102 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 103 auth_debug_add("Pty allocation disabled."); 104 no_pty_flag = 1; 105 opts += strlen(cp); 106 goto next_option; 107 } 108 cp = "command=\""; 109 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 110 opts += strlen(cp); 111 forced_command = xmalloc(strlen(opts) + 1); 112 i = 0; 113 while (*opts) { 114 if (*opts == '"') 115 break; 116 if (*opts == '\\' && opts[1] == '"') { 117 opts += 2; 118 forced_command[i++] = '"'; 119 continue; 120 } 121 forced_command[i++] = *opts++; 122 } 123 if (!*opts) { 124 debug("%.100s, line %lu: missing end quote", 125 file, linenum); 126 auth_debug_add("%.100s, line %lu: missing end quote", 127 file, linenum); 128 xfree(forced_command); 129 forced_command = NULL; 130 goto bad_option; 131 } 132 forced_command[i] = 0; 133 auth_debug_add("Forced command: %.900s", forced_command); 134 opts++; 135 goto next_option; 136 } 137 cp = "environment=\""; 138 if (options.permit_user_env && 139 strncasecmp(opts, cp, strlen(cp)) == 0) { 140 char *s; 141 struct envstring *new_envstring; 142 143 opts += strlen(cp); 144 s = xmalloc(strlen(opts) + 1); 145 i = 0; 146 while (*opts) { 147 if (*opts == '"') 148 break; 149 if (*opts == '\\' && opts[1] == '"') { 150 opts += 2; 151 s[i++] = '"'; 152 continue; 153 } 154 s[i++] = *opts++; 155 } 156 if (!*opts) { 157 debug("%.100s, line %lu: missing end quote", 158 file, linenum); 159 auth_debug_add("%.100s, line %lu: missing end quote", 160 file, linenum); 161 xfree(s); 162 goto bad_option; 163 } 164 s[i] = 0; 165 auth_debug_add("Adding to environment: %.900s", s); 166 debug("Adding to environment: %.900s", s); 167 opts++; 168 new_envstring = xmalloc(sizeof(struct envstring)); 169 new_envstring->s = s; 170 new_envstring->next = custom_environment; 171 custom_environment = new_envstring; 172 goto next_option; 173 } 174 cp = "from=\""; 175 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 176 const char *remote_ip = get_remote_ipaddr(); 177 const char *remote_host = get_canonical_hostname( 178 options.verify_reverse_mapping); 179 char *patterns = xmalloc(strlen(opts) + 1); 180 181 opts += strlen(cp); 182 i = 0; 183 while (*opts) { 184 if (*opts == '"') 185 break; 186 if (*opts == '\\' && opts[1] == '"') { 187 opts += 2; 188 patterns[i++] = '"'; 189 continue; 190 } 191 patterns[i++] = *opts++; 192 } 193 if (!*opts) { 194 debug("%.100s, line %lu: missing end quote", 195 file, linenum); 196 auth_debug_add("%.100s, line %lu: missing end quote", 197 file, linenum); 198 xfree(patterns); 199 goto bad_option; 200 } 201 patterns[i] = 0; 202 opts++; 203 if (match_host_and_ip(remote_host, remote_ip, 204 patterns) != 1) { 205 xfree(patterns); 206 log("Authentication tried for %.100s with " 207 "correct key but not from a permitted " 208 "host (host=%.200s, ip=%.200s).", 209 pw->pw_name, remote_host, remote_ip); 210 auth_debug_add("Your host '%.200s' is not " 211 "permitted to use this key for login.", 212 remote_host); 213 /* deny access */ 214 return 0; 215 } 216 xfree(patterns); 217 /* Host name matches. */ 218 goto next_option; 219 } 220 cp = "permitopen=\""; 221 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 222 char host[256], sport[6]; 223 u_short port; 224 char *patterns = xmalloc(strlen(opts) + 1); 225 226 opts += strlen(cp); 227 i = 0; 228 while (*opts) { 229 if (*opts == '"') 230 break; 231 if (*opts == '\\' && opts[1] == '"') { 232 opts += 2; 233 patterns[i++] = '"'; 234 continue; 235 } 236 patterns[i++] = *opts++; 237 } 238 if (!*opts) { 239 debug("%.100s, line %lu: missing end quote", 240 file, linenum); 241 auth_debug_add("%.100s, line %lu: missing end quote", 242 file, linenum); 243 xfree(patterns); 244 goto bad_option; 245 } 246 patterns[i] = 0; 247 opts++; 248 if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && 249 sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { 250 debug("%.100s, line %lu: Bad permitopen specification " 251 "<%.100s>", file, linenum, patterns); 252 auth_debug_add("%.100s, line %lu: " 253 "Bad permitopen specification", file, linenum); 254 xfree(patterns); 255 goto bad_option; 256 } 257 if ((port = a2port(sport)) == 0) { 258 debug("%.100s, line %lu: Bad permitopen port <%.100s>", 259 file, linenum, sport); 260 auth_debug_add("%.100s, line %lu: " 261 "Bad permitopen port", file, linenum); 262 xfree(patterns); 263 goto bad_option; 264 } 265 if (options.allow_tcp_forwarding) 266 channel_add_permitted_opens(host, port); 267 xfree(patterns); 268 goto next_option; 269 } 270 next_option: 271 /* 272 * Skip the comma, and move to the next option 273 * (or break out if there are no more). 274 */ 275 if (!*opts) 276 fatal("Bugs in auth-options.c option processing."); 277 if (*opts == ' ' || *opts == '\t') 278 break; /* End of options. */ 279 if (*opts != ',') 280 goto bad_option; 281 opts++; 282 /* Process the next option. */ 283 } 284 285 if (!use_privsep) 286 auth_debug_send(); 287 288 /* grant access */ 289 return 1; 290 291 bad_option: 292 log("Bad options in %.100s file, line %lu: %.50s", 293 file, linenum, opts); 294 auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 295 file, linenum, opts); 296 297 if (!use_privsep) 298 auth_debug_send(); 299 300 /* deny access */ 301 return 0; 302 } 303