xref: /freebsd/crypto/openssh/auth-options.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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  * RSA-based authentication.  This code determines whether to admit a login
6  * based on RSA authentication.  This file also contains functions to check
7  * validity of the host key.
8  *
9  * As far as I am concerned, the code I have written for this software
10  * can be used freely for any purpose.  Any derived versions of this
11  * software must be clearly marked as such, and if the derived work is
12  * incompatible with the protocol description in the RFC file, it must be
13  * called by a name other than "ssh" or "Secure Shell".
14  */
15 
16 #include "includes.h"
17 RCSID("$OpenBSD: auth-options.c,v 1.4 2000/09/07 21:13:36 markus Exp $");
18 
19 #include "ssh.h"
20 #include "packet.h"
21 #include "xmalloc.h"
22 #include "match.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 /* return 1 if access is granted, 0 if not. side effect: sets key option flags */
37 int
38 auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
39 {
40 	const char *cp;
41 	if (!options)
42 		return 1;
43 	while (*options && *options != ' ' && *options != '\t') {
44 		cp = "no-port-forwarding";
45 		if (strncmp(options, cp, strlen(cp)) == 0) {
46 			packet_send_debug("Port forwarding disabled.");
47 			no_port_forwarding_flag = 1;
48 			options += strlen(cp);
49 			goto next_option;
50 		}
51 		cp = "no-agent-forwarding";
52 		if (strncmp(options, cp, strlen(cp)) == 0) {
53 			packet_send_debug("Agent forwarding disabled.");
54 			no_agent_forwarding_flag = 1;
55 			options += strlen(cp);
56 			goto next_option;
57 		}
58 		cp = "no-X11-forwarding";
59 		if (strncmp(options, cp, strlen(cp)) == 0) {
60 			packet_send_debug("X11 forwarding disabled.");
61 			no_x11_forwarding_flag = 1;
62 			options += strlen(cp);
63 			goto next_option;
64 		}
65 		cp = "no-pty";
66 		if (strncmp(options, cp, strlen(cp)) == 0) {
67 			packet_send_debug("Pty allocation disabled.");
68 			no_pty_flag = 1;
69 			options += strlen(cp);
70 			goto next_option;
71 		}
72 		cp = "command=\"";
73 		if (strncmp(options, cp, strlen(cp)) == 0) {
74 			int i;
75 			options += strlen(cp);
76 			forced_command = xmalloc(strlen(options) + 1);
77 			i = 0;
78 			while (*options) {
79 				if (*options == '"')
80 					break;
81 				if (*options == '\\' && options[1] == '"') {
82 					options += 2;
83 					forced_command[i++] = '"';
84 					continue;
85 				}
86 				forced_command[i++] = *options++;
87 			}
88 			if (!*options) {
89 				debug("%.100s, line %lu: missing end quote",
90 				      SSH_USER_PERMITTED_KEYS, linenum);
91 				packet_send_debug("%.100s, line %lu: missing end quote",
92 						  SSH_USER_PERMITTED_KEYS, linenum);
93 				continue;
94 			}
95 			forced_command[i] = 0;
96 			packet_send_debug("Forced command: %.900s", forced_command);
97 			options++;
98 			goto next_option;
99 		}
100 		cp = "environment=\"";
101 		if (strncmp(options, cp, strlen(cp)) == 0) {
102 			int i;
103 			char *s;
104 			struct envstring *new_envstring;
105 			options += strlen(cp);
106 			s = xmalloc(strlen(options) + 1);
107 			i = 0;
108 			while (*options) {
109 				if (*options == '"')
110 					break;
111 				if (*options == '\\' && options[1] == '"') {
112 					options += 2;
113 					s[i++] = '"';
114 					continue;
115 				}
116 				s[i++] = *options++;
117 			}
118 			if (!*options) {
119 				debug("%.100s, line %lu: missing end quote",
120 				      SSH_USER_PERMITTED_KEYS, linenum);
121 				packet_send_debug("%.100s, line %lu: missing end quote",
122 						  SSH_USER_PERMITTED_KEYS, linenum);
123 				continue;
124 			}
125 			s[i] = 0;
126 			packet_send_debug("Adding to environment: %.900s", s);
127 			debug("Adding to environment: %.900s", s);
128 			options++;
129 			new_envstring = xmalloc(sizeof(struct envstring));
130 			new_envstring->s = s;
131 			new_envstring->next = custom_environment;
132 			custom_environment = new_envstring;
133 			goto next_option;
134 		}
135 		cp = "from=\"";
136 		if (strncmp(options, cp, strlen(cp)) == 0) {
137 			int mname, mip;
138 			char *patterns = xmalloc(strlen(options) + 1);
139 			int i;
140 			options += strlen(cp);
141 			i = 0;
142 			while (*options) {
143 				if (*options == '"')
144 					break;
145 				if (*options == '\\' && options[1] == '"') {
146 					options += 2;
147 					patterns[i++] = '"';
148 					continue;
149 				}
150 				patterns[i++] = *options++;
151 			}
152 			if (!*options) {
153 				debug("%.100s, line %lu: missing end quote",
154 				    SSH_USER_PERMITTED_KEYS, linenum);
155 				packet_send_debug("%.100s, line %lu: missing end quote",
156 				    SSH_USER_PERMITTED_KEYS, linenum);
157 				continue;
158 			}
159 			patterns[i] = 0;
160 			options++;
161 			/*
162 			 * Deny access if we get a negative
163 			 * match for the hostname or the ip
164 			 * or if we get not match at all
165 			 */
166 			mname = match_hostname(get_canonical_hostname(),
167 			    patterns, strlen(patterns));
168 			mip = match_hostname(get_remote_ipaddr(),
169 			    patterns, strlen(patterns));
170 			xfree(patterns);
171 			if (mname == -1 || mip == -1 ||
172 			    (mname != 1 && mip != 1)) {
173 				log("Authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
174 				    pw->pw_name, get_canonical_hostname(),
175 				    get_remote_ipaddr());
176 				packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
177 				get_canonical_hostname());
178 				/* key invalid for this host, reset flags */
179 				no_agent_forwarding_flag = 0;
180 				no_port_forwarding_flag = 0;
181 				no_pty_flag = 0;
182 				no_x11_forwarding_flag = 0;
183 				while (custom_environment) {
184 					struct envstring *ce = custom_environment;
185 					custom_environment = ce->next;
186 					xfree(ce->s);
187 					xfree(ce);
188 				}
189 				if (forced_command) {
190 					xfree(forced_command);
191 					forced_command = NULL;
192 				}
193 				/* deny access */
194 				return 0;
195 			}
196 			/* Host name matches. */
197 			goto next_option;
198 		}
199 next_option:
200 		/*
201 		 * Skip the comma, and move to the next option
202 		 * (or break out if there are no more).
203 		 */
204 		if (!*options)
205 			fatal("Bugs in auth-options.c option processing.");
206 		if (*options == ' ' || *options == '\t')
207 			break;		/* End of options. */
208 		if (*options != ',')
209 			goto bad_option;
210 		options++;
211 		/* Process the next option. */
212 	}
213 	/* grant access */
214 	return 1;
215 
216 bad_option:
217 	log("Bad options in %.100s file, line %lu: %.50s",
218 	    SSH_USER_PERMITTED_KEYS, linenum, options);
219 	packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
220 	    SSH_USER_PERMITTED_KEYS, linenum, options);
221 	/* deny access */
222 	return 0;
223 }
224