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