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