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.24 2002/05/13 20:44:58 markus Exp $"); 14 15 #include "packet.h" 16 #include "xmalloc.h" 17 #include "match.h" 18 #include "log.h" 19 #include "canohost.h" 20 #include "channels.h" 21 #include "auth-options.h" 22 #include "servconf.h" 23 #include "bufaux.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 (strncasecmp(opts, cp, strlen(cp)) == 0) { 139 char *s; 140 struct envstring *new_envstring; 141 142 opts += strlen(cp); 143 s = xmalloc(strlen(opts) + 1); 144 i = 0; 145 while (*opts) { 146 if (*opts == '"') 147 break; 148 if (*opts == '\\' && opts[1] == '"') { 149 opts += 2; 150 s[i++] = '"'; 151 continue; 152 } 153 s[i++] = *opts++; 154 } 155 if (!*opts) { 156 debug("%.100s, line %lu: missing end quote", 157 file, linenum); 158 auth_debug_add("%.100s, line %lu: missing end quote", 159 file, linenum); 160 xfree(s); 161 goto bad_option; 162 } 163 s[i] = 0; 164 auth_debug_add("Adding to environment: %.900s", s); 165 debug("Adding to environment: %.900s", s); 166 opts++; 167 new_envstring = xmalloc(sizeof(struct envstring)); 168 new_envstring->s = s; 169 new_envstring->next = custom_environment; 170 custom_environment = new_envstring; 171 goto next_option; 172 } 173 cp = "from=\""; 174 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 175 const char *remote_ip = get_remote_ipaddr(); 176 const char *remote_host = get_canonical_hostname( 177 options.verify_reverse_mapping); 178 char *patterns = xmalloc(strlen(opts) + 1); 179 180 opts += strlen(cp); 181 i = 0; 182 while (*opts) { 183 if (*opts == '"') 184 break; 185 if (*opts == '\\' && opts[1] == '"') { 186 opts += 2; 187 patterns[i++] = '"'; 188 continue; 189 } 190 patterns[i++] = *opts++; 191 } 192 if (!*opts) { 193 debug("%.100s, line %lu: missing end quote", 194 file, linenum); 195 auth_debug_add("%.100s, line %lu: missing end quote", 196 file, linenum); 197 xfree(patterns); 198 goto bad_option; 199 } 200 patterns[i] = 0; 201 opts++; 202 if (match_host_and_ip(remote_host, remote_ip, 203 patterns) != 1) { 204 xfree(patterns); 205 log("Authentication tried for %.100s with " 206 "correct key but not from a permitted " 207 "host (host=%.200s, ip=%.200s).", 208 pw->pw_name, remote_host, remote_ip); 209 auth_debug_add("Your host '%.200s' is not " 210 "permitted to use this key for login.", 211 remote_host); 212 /* deny access */ 213 return 0; 214 } 215 xfree(patterns); 216 /* Host name matches. */ 217 goto next_option; 218 } 219 cp = "permitopen=\""; 220 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 221 char host[256], sport[6]; 222 u_short port; 223 char *patterns = xmalloc(strlen(opts) + 1); 224 225 opts += strlen(cp); 226 i = 0; 227 while (*opts) { 228 if (*opts == '"') 229 break; 230 if (*opts == '\\' && opts[1] == '"') { 231 opts += 2; 232 patterns[i++] = '"'; 233 continue; 234 } 235 patterns[i++] = *opts++; 236 } 237 if (!*opts) { 238 debug("%.100s, line %lu: missing end quote", 239 file, linenum); 240 auth_debug_add("%.100s, line %lu: missing end quote", 241 file, linenum); 242 xfree(patterns); 243 goto bad_option; 244 } 245 patterns[i] = 0; 246 opts++; 247 if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 && 248 sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) { 249 debug("%.100s, line %lu: Bad permitopen specification " 250 "<%.100s>", file, linenum, patterns); 251 auth_debug_add("%.100s, line %lu: " 252 "Bad permitopen specification", file, linenum); 253 xfree(patterns); 254 goto bad_option; 255 } 256 if ((port = a2port(sport)) == 0) { 257 debug("%.100s, line %lu: Bad permitopen port <%.100s>", 258 file, linenum, sport); 259 auth_debug_add("%.100s, line %lu: " 260 "Bad permitopen port", file, linenum); 261 xfree(patterns); 262 goto bad_option; 263 } 264 if (options.allow_tcp_forwarding) 265 channel_add_permitted_opens(host, port); 266 xfree(patterns); 267 goto next_option; 268 } 269 next_option: 270 /* 271 * Skip the comma, and move to the next option 272 * (or break out if there are no more). 273 */ 274 if (!*opts) 275 fatal("Bugs in auth-options.c option processing."); 276 if (*opts == ' ' || *opts == '\t') 277 break; /* End of options. */ 278 if (*opts != ',') 279 goto bad_option; 280 opts++; 281 /* Process the next option. */ 282 } 283 284 if (!use_privsep) 285 auth_debug_send(); 286 287 /* grant access */ 288 return 1; 289 290 bad_option: 291 log("Bad options in %.100s file, line %lu: %.50s", 292 file, linenum, opts); 293 auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 294 file, linenum, opts); 295 296 if (!use_privsep) 297 auth_debug_send(); 298 299 /* deny access */ 300 return 0; 301 } 302