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