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 "auth.h" 26 27 /* Flags set authorized_keys flags */ 28 int no_port_forwarding_flag = 0; 29 int no_agent_forwarding_flag = 0; 30 int no_x11_forwarding_flag = 0; 31 int no_pty_flag = 0; 32 33 /* "command=" option. */ 34 char *forced_command = NULL; 35 36 /* "environment=" options. */ 37 struct envstring *custom_environment = NULL; 38 39 extern ServerOptions options; 40 41 void 42 auth_clear_options(void) 43 { 44 no_agent_forwarding_flag = 0; 45 no_port_forwarding_flag = 0; 46 no_pty_flag = 0; 47 no_x11_forwarding_flag = 0; 48 while (custom_environment) { 49 struct envstring *ce = custom_environment; 50 custom_environment = ce->next; 51 xfree(ce->s); 52 xfree(ce); 53 } 54 if (forced_command) { 55 xfree(forced_command); 56 forced_command = NULL; 57 } 58 channel_clear_permitted_opens(); 59 auth_debug_reset(); 60 } 61 62 /* 63 * return 1 if access is granted, 0 if not. 64 * side effect: sets key option flags 65 */ 66 int 67 auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 68 { 69 const char *cp; 70 int i; 71 72 /* reset options */ 73 auth_clear_options(); 74 75 if (!opts) 76 return 1; 77 78 while (*opts && *opts != ' ' && *opts != '\t') { 79 cp = "no-port-forwarding"; 80 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 81 auth_debug_add("Port forwarding disabled."); 82 no_port_forwarding_flag = 1; 83 opts += strlen(cp); 84 goto next_option; 85 } 86 cp = "no-agent-forwarding"; 87 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 88 auth_debug_add("Agent forwarding disabled."); 89 no_agent_forwarding_flag = 1; 90 opts += strlen(cp); 91 goto next_option; 92 } 93 cp = "no-X11-forwarding"; 94 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 95 auth_debug_add("X11 forwarding disabled."); 96 no_x11_forwarding_flag = 1; 97 opts += strlen(cp); 98 goto next_option; 99 } 100 cp = "no-pty"; 101 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 102 auth_debug_add("Pty allocation disabled."); 103 no_pty_flag = 1; 104 opts += strlen(cp); 105 goto next_option; 106 } 107 cp = "command=\""; 108 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 109 opts += strlen(cp); 110 forced_command = xmalloc(strlen(opts) + 1); 111 i = 0; 112 while (*opts) { 113 if (*opts == '"') 114 break; 115 if (*opts == '\\' && opts[1] == '"') { 116 opts += 2; 117 forced_command[i++] = '"'; 118 continue; 119 } 120 forced_command[i++] = *opts++; 121 } 122 if (!*opts) { 123 debug("%.100s, line %lu: missing end quote", 124 file, linenum); 125 auth_debug_add("%.100s, line %lu: missing end quote", 126 file, linenum); 127 xfree(forced_command); 128 forced_command = NULL; 129 goto bad_option; 130 } 131 forced_command[i] = 0; 132 auth_debug_add("Forced command: %.900s", forced_command); 133 opts++; 134 goto next_option; 135 } 136 cp = "environment=\""; 137 if (options.permit_user_env && 138 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 auth_debug_send(); 285 286 /* grant access */ 287 return 1; 288 289 bad_option: 290 log("Bad options in %.100s file, line %lu: %.50s", 291 file, linenum, opts); 292 auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 293 file, linenum, opts); 294 295 auth_debug_send(); 296 297 /* deny access */ 298 return 0; 299 }