Small comma fixes.
[dragonfly.git] / crypto / openssh-4 / auth-options.c
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.33 2005/12/08 18:34:11 reyk Exp $");
14
15 #include "xmalloc.h"
16 #include "match.h"
17 #include "log.h"
18 #include "canohost.h"
19 #include "channels.h"
20 #include "auth-options.h"
21 #include "servconf.h"
22 #include "misc.h"
23 #include "monitor_wrap.h"
24 #include "auth.h"
25
26 /* Flags set authorized_keys flags */
27 int no_port_forwarding_flag = 0;
28 int no_agent_forwarding_flag = 0;
29 int no_x11_forwarding_flag = 0;
30 int no_pty_flag = 0;
31
32 /* "command=" option. */
33 char *forced_command = NULL;
34
35 /* "environment=" options. */
36 struct envstring *custom_environment = NULL;
37
38 /* "tunnel=" option. */
39 int forced_tun_device = -1;
40
41 extern ServerOptions options;
42
43 void
44 auth_clear_options(void)
45 {
46         no_agent_forwarding_flag = 0;
47         no_port_forwarding_flag = 0;
48         no_pty_flag = 0;
49         no_x11_forwarding_flag = 0;
50         while (custom_environment) {
51                 struct envstring *ce = custom_environment;
52                 custom_environment = ce->next;
53                 xfree(ce->s);
54                 xfree(ce);
55         }
56         if (forced_command) {
57                 xfree(forced_command);
58                 forced_command = NULL;
59         }
60         forced_tun_device = -1;
61         channel_clear_permitted_opens();
62         auth_debug_reset();
63 }
64
65 /*
66  * return 1 if access is granted, 0 if not.
67  * side effect: sets key option flags
68  */
69 int
70 auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
71 {
72         const char *cp;
73         int i;
74
75         /* reset options */
76         auth_clear_options();
77
78         if (!opts)
79                 return 1;
80
81         while (*opts && *opts != ' ' && *opts != '\t') {
82                 cp = "no-port-forwarding";
83                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
84                         auth_debug_add("Port forwarding disabled.");
85                         no_port_forwarding_flag = 1;
86                         opts += strlen(cp);
87                         goto next_option;
88                 }
89                 cp = "no-agent-forwarding";
90                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
91                         auth_debug_add("Agent forwarding disabled.");
92                         no_agent_forwarding_flag = 1;
93                         opts += strlen(cp);
94                         goto next_option;
95                 }
96                 cp = "no-X11-forwarding";
97                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
98                         auth_debug_add("X11 forwarding disabled.");
99                         no_x11_forwarding_flag = 1;
100                         opts += strlen(cp);
101                         goto next_option;
102                 }
103                 cp = "no-pty";
104                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
105                         auth_debug_add("Pty allocation disabled.");
106                         no_pty_flag = 1;
107                         opts += strlen(cp);
108                         goto next_option;
109                 }
110                 cp = "command=\"";
111                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
112                         opts += strlen(cp);
113                         forced_command = xmalloc(strlen(opts) + 1);
114                         i = 0;
115                         while (*opts) {
116                                 if (*opts == '"')
117                                         break;
118                                 if (*opts == '\\' && opts[1] == '"') {
119                                         opts += 2;
120                                         forced_command[i++] = '"';
121                                         continue;
122                                 }
123                                 forced_command[i++] = *opts++;
124                         }
125                         if (!*opts) {
126                                 debug("%.100s, line %lu: missing end quote",
127                                     file, linenum);
128                                 auth_debug_add("%.100s, line %lu: missing end quote",
129                                     file, linenum);
130                                 xfree(forced_command);
131                                 forced_command = NULL;
132                                 goto bad_option;
133                         }
134                         forced_command[i] = 0;
135                         auth_debug_add("Forced command: %.900s", forced_command);
136                         opts++;
137                         goto next_option;
138                 }
139                 cp = "environment=\"";
140                 if (options.permit_user_env &&
141                     strncasecmp(opts, cp, strlen(cp)) == 0) {
142                         char *s;
143                         struct envstring *new_envstring;
144
145                         opts += strlen(cp);
146                         s = xmalloc(strlen(opts) + 1);
147                         i = 0;
148                         while (*opts) {
149                                 if (*opts == '"')
150                                         break;
151                                 if (*opts == '\\' && opts[1] == '"') {
152                                         opts += 2;
153                                         s[i++] = '"';
154                                         continue;
155                                 }
156                                 s[i++] = *opts++;
157                         }
158                         if (!*opts) {
159                                 debug("%.100s, line %lu: missing end quote",
160                                     file, linenum);
161                                 auth_debug_add("%.100s, line %lu: missing end quote",
162                                     file, linenum);
163                                 xfree(s);
164                                 goto bad_option;
165                         }
166                         s[i] = 0;
167                         auth_debug_add("Adding to environment: %.900s", s);
168                         debug("Adding to environment: %.900s", s);
169                         opts++;
170                         new_envstring = xmalloc(sizeof(struct envstring));
171                         new_envstring->s = s;
172                         new_envstring->next = custom_environment;
173                         custom_environment = new_envstring;
174                         goto next_option;
175                 }
176                 cp = "from=\"";
177                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
178                         const char *remote_ip = get_remote_ipaddr();
179                         const char *remote_host = get_canonical_hostname(
180                             options.use_dns);
181                         char *patterns = xmalloc(strlen(opts) + 1);
182
183                         opts += strlen(cp);
184                         i = 0;
185                         while (*opts) {
186                                 if (*opts == '"')
187                                         break;
188                                 if (*opts == '\\' && opts[1] == '"') {
189                                         opts += 2;
190                                         patterns[i++] = '"';
191                                         continue;
192                                 }
193                                 patterns[i++] = *opts++;
194                         }
195                         if (!*opts) {
196                                 debug("%.100s, line %lu: missing end quote",
197                                     file, linenum);
198                                 auth_debug_add("%.100s, line %lu: missing end quote",
199                                     file, linenum);
200                                 xfree(patterns);
201                                 goto bad_option;
202                         }
203                         patterns[i] = 0;
204                         opts++;
205                         if (match_host_and_ip(remote_host, remote_ip,
206                             patterns) != 1) {
207                                 xfree(patterns);
208                                 logit("Authentication tried for %.100s with "
209                                     "correct key but not from a permitted "
210                                     "host (host=%.200s, ip=%.200s).",
211                                     pw->pw_name, remote_host, remote_ip);
212                                 auth_debug_add("Your host '%.200s' is not "
213                                     "permitted to use this key for login.",
214                                     remote_host);
215                                 /* deny access */
216                                 return 0;
217                         }
218                         xfree(patterns);
219                         /* Host name matches. */
220                         goto next_option;
221                 }
222                 cp = "permitopen=\"";
223                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
224                         char *host, *p;
225                         u_short port;
226                         char *patterns = xmalloc(strlen(opts) + 1);
227
228                         opts += strlen(cp);
229                         i = 0;
230                         while (*opts) {
231                                 if (*opts == '"')
232                                         break;
233                                 if (*opts == '\\' && opts[1] == '"') {
234                                         opts += 2;
235                                         patterns[i++] = '"';
236                                         continue;
237                                 }
238                                 patterns[i++] = *opts++;
239                         }
240                         if (!*opts) {
241                                 debug("%.100s, line %lu: missing end quote",
242                                     file, linenum);
243                                 auth_debug_add("%.100s, line %lu: missing "
244                                     "end quote", file, linenum);
245                                 xfree(patterns);
246                                 goto bad_option;
247                         }
248                         patterns[i] = 0;
249                         opts++;
250                         p = patterns;
251                         host = hpdelim(&p);
252                         if (host == NULL || strlen(host) >= NI_MAXHOST) {
253                                 debug("%.100s, line %lu: Bad permitopen "
254                                     "specification <%.100s>", file, linenum,
255                                     patterns);
256                                 auth_debug_add("%.100s, line %lu: "
257                                     "Bad permitopen specification", file,
258                                     linenum);
259                                 xfree(patterns);
260                                 goto bad_option;
261                         }
262                         host = cleanhostname(host);
263                         if (p == NULL || (port = a2port(p)) == 0) {
264                                 debug("%.100s, line %lu: Bad permitopen port "
265                                     "<%.100s>", file, linenum, p ? p : "");
266                                 auth_debug_add("%.100s, line %lu: "
267                                     "Bad permitopen port", file, linenum);
268                                 xfree(patterns);
269                                 goto bad_option;
270                         }
271                         if (options.allow_tcp_forwarding)
272                                 channel_add_permitted_opens(host, port);
273                         xfree(patterns);
274                         goto next_option;
275                 }
276                 cp = "tunnel=\"";
277                 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
278                         char *tun = NULL;
279                         opts += strlen(cp);
280                         tun = xmalloc(strlen(opts) + 1);
281                         i = 0;
282                         while (*opts) {
283                                 if (*opts == '"')
284                                         break;
285                                 tun[i++] = *opts++;
286                         }
287                         if (!*opts) {
288                                 debug("%.100s, line %lu: missing end quote",
289                                     file, linenum);
290                                 auth_debug_add("%.100s, line %lu: missing end quote",
291                                     file, linenum);
292                                 xfree(tun);
293                                 forced_tun_device = -1;
294                                 goto bad_option;
295                         }
296                         tun[i] = 0;
297                         forced_tun_device = a2tun(tun, NULL);
298                         xfree(tun);
299                         if (forced_tun_device == SSH_TUNID_ERR) {
300                                 debug("%.100s, line %lu: invalid tun device",
301                                     file, linenum);
302                                 auth_debug_add("%.100s, line %lu: invalid tun device",
303                                     file, linenum);
304                                 forced_tun_device = -1;
305                                 goto bad_option;
306                         }
307                         auth_debug_add("Forced tun device: %d", forced_tun_device);
308                         opts++;
309                         goto next_option;
310                 }
311 next_option:
312                 /*
313                  * Skip the comma, and move to the next option
314                  * (or break out if there are no more).
315                  */
316                 if (!*opts)
317                         fatal("Bugs in auth-options.c option processing.");
318                 if (*opts == ' ' || *opts == '\t')
319                         break;          /* End of options. */
320                 if (*opts != ',')
321                         goto bad_option;
322                 opts++;
323                 /* Process the next option. */
324         }
325
326         if (!use_privsep)
327                 auth_debug_send();
328
329         /* grant access */
330         return 1;
331
332 bad_option:
333         logit("Bad options in %.100s file, line %lu: %.50s",
334             file, linenum, opts);
335         auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
336             file, linenum, opts);
337
338         if (!use_privsep)
339                 auth_debug_send();
340
341         /* deny access */
342         return 0;
343 }