1b66f2d16SKris Kennaway /* 2b66f2d16SKris Kennaway * Author: Tatu Ylonen <ylo@cs.hut.fi> 3b66f2d16SKris Kennaway * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4b66f2d16SKris Kennaway * All rights reserved 5b66f2d16SKris Kennaway * RSA-based authentication. This code determines whether to admit a login 6b66f2d16SKris Kennaway * based on RSA authentication. This file also contains functions to check 7b66f2d16SKris Kennaway * validity of the host key. 8b66f2d16SKris Kennaway * 9b66f2d16SKris Kennaway * As far as I am concerned, the code I have written for this software 10b66f2d16SKris Kennaway * can be used freely for any purpose. Any derived versions of this 11b66f2d16SKris Kennaway * software must be clearly marked as such, and if the derived work is 12b66f2d16SKris Kennaway * incompatible with the protocol description in the RFC file, it must be 13b66f2d16SKris Kennaway * called by a name other than "ssh" or "Secure Shell". 14b66f2d16SKris Kennaway */ 15b66f2d16SKris Kennaway 16b66f2d16SKris Kennaway #include "includes.h" 175b9b2fafSBrian Feldman RCSID("$OpenBSD: auth-options.c,v 1.5 2000/10/09 21:32:34 markus Exp $"); 18b66f2d16SKris Kennaway 19b66f2d16SKris Kennaway #include "ssh.h" 20b66f2d16SKris Kennaway #include "packet.h" 21b66f2d16SKris Kennaway #include "xmalloc.h" 22b66f2d16SKris Kennaway #include "match.h" 23b66f2d16SKris Kennaway 24b66f2d16SKris Kennaway /* Flags set authorized_keys flags */ 25b66f2d16SKris Kennaway int no_port_forwarding_flag = 0; 26b66f2d16SKris Kennaway int no_agent_forwarding_flag = 0; 27b66f2d16SKris Kennaway int no_x11_forwarding_flag = 0; 28b66f2d16SKris Kennaway int no_pty_flag = 0; 29b66f2d16SKris Kennaway 30b66f2d16SKris Kennaway /* "command=" option. */ 31b66f2d16SKris Kennaway char *forced_command = NULL; 32b66f2d16SKris Kennaway 33b66f2d16SKris Kennaway /* "environment=" options. */ 34b66f2d16SKris Kennaway struct envstring *custom_environment = NULL; 35b66f2d16SKris Kennaway 365b9b2fafSBrian Feldman void 375b9b2fafSBrian Feldman auth_clear_options(void) 385b9b2fafSBrian Feldman { 395b9b2fafSBrian Feldman no_agent_forwarding_flag = 0; 405b9b2fafSBrian Feldman no_port_forwarding_flag = 0; 415b9b2fafSBrian Feldman no_pty_flag = 0; 425b9b2fafSBrian Feldman no_x11_forwarding_flag = 0; 435b9b2fafSBrian Feldman while (custom_environment) { 445b9b2fafSBrian Feldman struct envstring *ce = custom_environment; 455b9b2fafSBrian Feldman custom_environment = ce->next; 465b9b2fafSBrian Feldman xfree(ce->s); 475b9b2fafSBrian Feldman xfree(ce); 485b9b2fafSBrian Feldman } 495b9b2fafSBrian Feldman if (forced_command) { 505b9b2fafSBrian Feldman xfree(forced_command); 515b9b2fafSBrian Feldman forced_command = NULL; 525b9b2fafSBrian Feldman } 535b9b2fafSBrian Feldman } 545b9b2fafSBrian Feldman 55b66f2d16SKris Kennaway /* return 1 if access is granted, 0 if not. side effect: sets key option flags */ 56b66f2d16SKris Kennaway int 57b66f2d16SKris Kennaway auth_parse_options(struct passwd *pw, char *options, unsigned long linenum) 58b66f2d16SKris Kennaway { 59b66f2d16SKris Kennaway const char *cp; 60b66f2d16SKris Kennaway if (!options) 61b66f2d16SKris Kennaway return 1; 625b9b2fafSBrian Feldman 635b9b2fafSBrian Feldman /* reset options */ 645b9b2fafSBrian Feldman auth_clear_options(); 655b9b2fafSBrian Feldman 66b66f2d16SKris Kennaway while (*options && *options != ' ' && *options != '\t') { 67b66f2d16SKris Kennaway cp = "no-port-forwarding"; 68b66f2d16SKris Kennaway if (strncmp(options, cp, strlen(cp)) == 0) { 69b66f2d16SKris Kennaway packet_send_debug("Port forwarding disabled."); 70b66f2d16SKris Kennaway no_port_forwarding_flag = 1; 71b66f2d16SKris Kennaway options += strlen(cp); 72b66f2d16SKris Kennaway goto next_option; 73b66f2d16SKris Kennaway } 74b66f2d16SKris Kennaway cp = "no-agent-forwarding"; 75b66f2d16SKris Kennaway if (strncmp(options, cp, strlen(cp)) == 0) { 76b66f2d16SKris Kennaway packet_send_debug("Agent forwarding disabled."); 77b66f2d16SKris Kennaway no_agent_forwarding_flag = 1; 78b66f2d16SKris Kennaway options += strlen(cp); 79b66f2d16SKris Kennaway goto next_option; 80b66f2d16SKris Kennaway } 81b66f2d16SKris Kennaway cp = "no-X11-forwarding"; 82b66f2d16SKris Kennaway if (strncmp(options, cp, strlen(cp)) == 0) { 83b66f2d16SKris Kennaway packet_send_debug("X11 forwarding disabled."); 84b66f2d16SKris Kennaway no_x11_forwarding_flag = 1; 85b66f2d16SKris Kennaway options += strlen(cp); 86b66f2d16SKris Kennaway goto next_option; 87b66f2d16SKris Kennaway } 88b66f2d16SKris Kennaway cp = "no-pty"; 89b66f2d16SKris Kennaway if (strncmp(options, cp, strlen(cp)) == 0) { 90b66f2d16SKris Kennaway packet_send_debug("Pty allocation disabled."); 91b66f2d16SKris Kennaway no_pty_flag = 1; 92b66f2d16SKris Kennaway options += strlen(cp); 93b66f2d16SKris Kennaway goto next_option; 94b66f2d16SKris Kennaway } 95b66f2d16SKris Kennaway cp = "command=\""; 96b66f2d16SKris Kennaway if (strncmp(options, cp, strlen(cp)) == 0) { 97b66f2d16SKris Kennaway int i; 98b66f2d16SKris Kennaway options += strlen(cp); 99b66f2d16SKris Kennaway forced_command = xmalloc(strlen(options) + 1); 100b66f2d16SKris Kennaway i = 0; 101b66f2d16SKris Kennaway while (*options) { 102b66f2d16SKris Kennaway if (*options == '"') 103b66f2d16SKris Kennaway break; 104b66f2d16SKris Kennaway if (*options == '\\' && options[1] == '"') { 105b66f2d16SKris Kennaway options += 2; 106b66f2d16SKris Kennaway forced_command[i++] = '"'; 107b66f2d16SKris Kennaway continue; 108b66f2d16SKris Kennaway } 109b66f2d16SKris Kennaway forced_command[i++] = *options++; 110b66f2d16SKris Kennaway } 111b66f2d16SKris Kennaway if (!*options) { 112b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 113b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum); 114b66f2d16SKris Kennaway packet_send_debug("%.100s, line %lu: missing end quote", 115b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum); 116b66f2d16SKris Kennaway continue; 117b66f2d16SKris Kennaway } 118b66f2d16SKris Kennaway forced_command[i] = 0; 119b66f2d16SKris Kennaway packet_send_debug("Forced command: %.900s", forced_command); 120b66f2d16SKris Kennaway options++; 121b66f2d16SKris Kennaway goto next_option; 122b66f2d16SKris Kennaway } 123b66f2d16SKris Kennaway cp = "environment=\""; 124b66f2d16SKris Kennaway if (strncmp(options, cp, strlen(cp)) == 0) { 125b66f2d16SKris Kennaway int i; 126b66f2d16SKris Kennaway char *s; 127b66f2d16SKris Kennaway struct envstring *new_envstring; 128b66f2d16SKris Kennaway options += strlen(cp); 129b66f2d16SKris Kennaway s = xmalloc(strlen(options) + 1); 130b66f2d16SKris Kennaway i = 0; 131b66f2d16SKris Kennaway while (*options) { 132b66f2d16SKris Kennaway if (*options == '"') 133b66f2d16SKris Kennaway break; 134b66f2d16SKris Kennaway if (*options == '\\' && options[1] == '"') { 135b66f2d16SKris Kennaway options += 2; 136b66f2d16SKris Kennaway s[i++] = '"'; 137b66f2d16SKris Kennaway continue; 138b66f2d16SKris Kennaway } 139b66f2d16SKris Kennaway s[i++] = *options++; 140b66f2d16SKris Kennaway } 141b66f2d16SKris Kennaway if (!*options) { 142b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 143b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum); 144b66f2d16SKris Kennaway packet_send_debug("%.100s, line %lu: missing end quote", 145b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum); 146b66f2d16SKris Kennaway continue; 147b66f2d16SKris Kennaway } 148b66f2d16SKris Kennaway s[i] = 0; 149b66f2d16SKris Kennaway packet_send_debug("Adding to environment: %.900s", s); 150b66f2d16SKris Kennaway debug("Adding to environment: %.900s", s); 151b66f2d16SKris Kennaway options++; 152b66f2d16SKris Kennaway new_envstring = xmalloc(sizeof(struct envstring)); 153b66f2d16SKris Kennaway new_envstring->s = s; 154b66f2d16SKris Kennaway new_envstring->next = custom_environment; 155b66f2d16SKris Kennaway custom_environment = new_envstring; 156b66f2d16SKris Kennaway goto next_option; 157b66f2d16SKris Kennaway } 158b66f2d16SKris Kennaway cp = "from=\""; 159b66f2d16SKris Kennaway if (strncmp(options, cp, strlen(cp)) == 0) { 160b66f2d16SKris Kennaway int mname, mip; 161b66f2d16SKris Kennaway char *patterns = xmalloc(strlen(options) + 1); 162b66f2d16SKris Kennaway int i; 163b66f2d16SKris Kennaway options += strlen(cp); 164b66f2d16SKris Kennaway i = 0; 165b66f2d16SKris Kennaway while (*options) { 166b66f2d16SKris Kennaway if (*options == '"') 167b66f2d16SKris Kennaway break; 168b66f2d16SKris Kennaway if (*options == '\\' && options[1] == '"') { 169b66f2d16SKris Kennaway options += 2; 170b66f2d16SKris Kennaway patterns[i++] = '"'; 171b66f2d16SKris Kennaway continue; 172b66f2d16SKris Kennaway } 173b66f2d16SKris Kennaway patterns[i++] = *options++; 174b66f2d16SKris Kennaway } 175b66f2d16SKris Kennaway if (!*options) { 176b66f2d16SKris Kennaway debug("%.100s, line %lu: missing end quote", 177b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum); 178b66f2d16SKris Kennaway packet_send_debug("%.100s, line %lu: missing end quote", 179b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum); 180b66f2d16SKris Kennaway continue; 181b66f2d16SKris Kennaway } 182b66f2d16SKris Kennaway patterns[i] = 0; 183b66f2d16SKris Kennaway options++; 184b66f2d16SKris Kennaway /* 185b66f2d16SKris Kennaway * Deny access if we get a negative 186b66f2d16SKris Kennaway * match for the hostname or the ip 187b66f2d16SKris Kennaway * or if we get not match at all 188b66f2d16SKris Kennaway */ 189b66f2d16SKris Kennaway mname = match_hostname(get_canonical_hostname(), 190b66f2d16SKris Kennaway patterns, strlen(patterns)); 191b66f2d16SKris Kennaway mip = match_hostname(get_remote_ipaddr(), 192b66f2d16SKris Kennaway patterns, strlen(patterns)); 193b66f2d16SKris Kennaway xfree(patterns); 194b66f2d16SKris Kennaway if (mname == -1 || mip == -1 || 195b66f2d16SKris Kennaway (mname != 1 && mip != 1)) { 196b66f2d16SKris Kennaway log("Authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).", 197b66f2d16SKris Kennaway pw->pw_name, get_canonical_hostname(), 198b66f2d16SKris Kennaway get_remote_ipaddr()); 199b66f2d16SKris Kennaway packet_send_debug("Your host '%.200s' is not permitted to use this key for login.", 200b66f2d16SKris Kennaway get_canonical_hostname()); 201b66f2d16SKris Kennaway /* deny access */ 202b66f2d16SKris Kennaway return 0; 203b66f2d16SKris Kennaway } 204b66f2d16SKris Kennaway /* Host name matches. */ 205b66f2d16SKris Kennaway goto next_option; 206b66f2d16SKris Kennaway } 207b66f2d16SKris Kennaway next_option: 208b66f2d16SKris Kennaway /* 209b66f2d16SKris Kennaway * Skip the comma, and move to the next option 210b66f2d16SKris Kennaway * (or break out if there are no more). 211b66f2d16SKris Kennaway */ 212b66f2d16SKris Kennaway if (!*options) 213b66f2d16SKris Kennaway fatal("Bugs in auth-options.c option processing."); 214b66f2d16SKris Kennaway if (*options == ' ' || *options == '\t') 215b66f2d16SKris Kennaway break; /* End of options. */ 216b66f2d16SKris Kennaway if (*options != ',') 217b66f2d16SKris Kennaway goto bad_option; 218b66f2d16SKris Kennaway options++; 219b66f2d16SKris Kennaway /* Process the next option. */ 220b66f2d16SKris Kennaway } 221b66f2d16SKris Kennaway /* grant access */ 222b66f2d16SKris Kennaway return 1; 223b66f2d16SKris Kennaway 224b66f2d16SKris Kennaway bad_option: 225b66f2d16SKris Kennaway log("Bad options in %.100s file, line %lu: %.50s", 226b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum, options); 227b66f2d16SKris Kennaway packet_send_debug("Bad options in %.100s file, line %lu: %.50s", 228b66f2d16SKris Kennaway SSH_USER_PERMITTED_KEYS, linenum, options); 229b66f2d16SKris Kennaway /* deny access */ 230b66f2d16SKris Kennaway return 0; 231b66f2d16SKris Kennaway } 232