]> andersk Git - openssh.git/blame_incremental - readconf.c
- jmc@cvs.openbsd.org 2009/12/29 18:03:32
[openssh.git] / readconf.c
... / ...
CommitLineData
1/* $OpenBSD: readconf.c,v 1.181 2009/12/29 16:38:41 stevesk 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 * Functions for reading the configuration files.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 */
14
15#include "includes.h"
16
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/socket.h>
20
21#include <netinet/in.h>
22
23#include <ctype.h>
24#include <errno.h>
25#include <netdb.h>
26#include <signal.h>
27#include <stdarg.h>
28#include <stdio.h>
29#include <string.h>
30#include <unistd.h>
31
32#include "xmalloc.h"
33#include "ssh.h"
34#include "compat.h"
35#include "cipher.h"
36#include "pathnames.h"
37#include "log.h"
38#include "key.h"
39#include "readconf.h"
40#include "match.h"
41#include "misc.h"
42#include "buffer.h"
43#include "kex.h"
44#include "mac.h"
45
46/* Format of the configuration file:
47
48 # Configuration data is parsed as follows:
49 # 1. command line options
50 # 2. user-specific file
51 # 3. system-wide file
52 # Any configuration value is only changed the first time it is set.
53 # Thus, host-specific definitions should be at the beginning of the
54 # configuration file, and defaults at the end.
55
56 # Host-specific declarations. These may override anything above. A single
57 # host may match multiple declarations; these are processed in the order
58 # that they are given in.
59
60 Host *.ngs.fi ngs.fi
61 User foo
62
63 Host fake.com
64 HostName another.host.name.real.org
65 User blaah
66 Port 34289
67 ForwardX11 no
68 ForwardAgent no
69
70 Host books.com
71 RemoteForward 9999 shadows.cs.hut.fi:9999
72 Cipher 3des
73
74 Host fascist.blob.com
75 Port 23123
76 User tylonen
77 PasswordAuthentication no
78
79 Host puukko.hut.fi
80 User t35124p
81 ProxyCommand ssh-proxy %h %p
82
83 Host *.fr
84 PublicKeyAuthentication no
85
86 Host *.su
87 Cipher none
88 PasswordAuthentication no
89
90 Host vpn.fake.com
91 Tunnel yes
92 TunnelDevice 3
93
94 # Defaults for various options
95 Host *
96 ForwardAgent no
97 ForwardX11 no
98 PasswordAuthentication yes
99 RSAAuthentication yes
100 RhostsRSAAuthentication yes
101 StrictHostKeyChecking yes
102 TcpKeepAlive no
103 IdentityFile ~/.ssh/identity
104 Port 22
105 EscapeChar ~
106
107*/
108
109/* Keyword tokens. */
110
111typedef enum {
112 oBadOption,
113 oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
114 oExitOnForwardFailure,
115 oPasswordAuthentication, oRSAAuthentication,
116 oChallengeResponseAuthentication, oXAuthLocation,
117 oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
118 oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
119 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
120 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
121 oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
122 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
123 oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
124 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
125 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
126 oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
127 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
128 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
129 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
130 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
131 oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
132 oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
133 oVisualHostKey, oUseRoaming, oRDomain,
134 oZeroKnowledgePasswordAuthentication, oDeprecated, oUnsupported
135} OpCodes;
136
137/* Textual representations of the tokens. */
138
139static struct {
140 const char *name;
141 OpCodes opcode;
142} keywords[] = {
143 { "forwardagent", oForwardAgent },
144 { "forwardx11", oForwardX11 },
145 { "forwardx11trusted", oForwardX11Trusted },
146 { "exitonforwardfailure", oExitOnForwardFailure },
147 { "xauthlocation", oXAuthLocation },
148 { "gatewayports", oGatewayPorts },
149 { "useprivilegedport", oUsePrivilegedPort },
150 { "rhostsauthentication", oDeprecated },
151 { "passwordauthentication", oPasswordAuthentication },
152 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
153 { "kbdinteractivedevices", oKbdInteractiveDevices },
154 { "rsaauthentication", oRSAAuthentication },
155 { "pubkeyauthentication", oPubkeyAuthentication },
156 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
157 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
158 { "hostbasedauthentication", oHostbasedAuthentication },
159 { "challengeresponseauthentication", oChallengeResponseAuthentication },
160 { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
161 { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
162 { "kerberosauthentication", oUnsupported },
163 { "kerberostgtpassing", oUnsupported },
164 { "afstokenpassing", oUnsupported },
165#if defined(GSSAPI)
166 { "gssapiauthentication", oGssAuthentication },
167 { "gssapidelegatecredentials", oGssDelegateCreds },
168#else
169 { "gssapiauthentication", oUnsupported },
170 { "gssapidelegatecredentials", oUnsupported },
171#endif
172 { "fallbacktorsh", oDeprecated },
173 { "usersh", oDeprecated },
174 { "identityfile", oIdentityFile },
175 { "identityfile2", oIdentityFile }, /* obsolete */
176 { "identitiesonly", oIdentitiesOnly },
177 { "hostname", oHostName },
178 { "hostkeyalias", oHostKeyAlias },
179 { "proxycommand", oProxyCommand },
180 { "port", oPort },
181 { "cipher", oCipher },
182 { "ciphers", oCiphers },
183 { "macs", oMacs },
184 { "protocol", oProtocol },
185 { "remoteforward", oRemoteForward },
186 { "localforward", oLocalForward },
187 { "user", oUser },
188 { "host", oHost },
189 { "escapechar", oEscapeChar },
190 { "globalknownhostsfile", oGlobalKnownHostsFile },
191 { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, /* obsolete */
192 { "userknownhostsfile", oUserKnownHostsFile },
193 { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */
194 { "connectionattempts", oConnectionAttempts },
195 { "batchmode", oBatchMode },
196 { "checkhostip", oCheckHostIP },
197 { "stricthostkeychecking", oStrictHostKeyChecking },
198 { "compression", oCompression },
199 { "compressionlevel", oCompressionLevel },
200 { "tcpkeepalive", oTCPKeepAlive },
201 { "keepalive", oTCPKeepAlive }, /* obsolete */
202 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
203 { "loglevel", oLogLevel },
204 { "dynamicforward", oDynamicForward },
205 { "preferredauthentications", oPreferredAuthentications },
206 { "hostkeyalgorithms", oHostKeyAlgorithms },
207 { "bindaddress", oBindAddress },
208#ifdef SMARTCARD
209 { "smartcarddevice", oSmartcardDevice },
210#else
211 { "smartcarddevice", oUnsupported },
212#endif
213 { "clearallforwardings", oClearAllForwardings },
214 { "enablesshkeysign", oEnableSSHKeysign },
215 { "verifyhostkeydns", oVerifyHostKeyDNS },
216 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
217 { "rekeylimit", oRekeyLimit },
218 { "connecttimeout", oConnectTimeout },
219 { "addressfamily", oAddressFamily },
220 { "serveraliveinterval", oServerAliveInterval },
221 { "serveralivecountmax", oServerAliveCountMax },
222 { "sendenv", oSendEnv },
223 { "controlpath", oControlPath },
224 { "controlmaster", oControlMaster },
225 { "hashknownhosts", oHashKnownHosts },
226 { "tunnel", oTunnel },
227 { "tunneldevice", oTunnelDevice },
228 { "localcommand", oLocalCommand },
229 { "permitlocalcommand", oPermitLocalCommand },
230 { "visualhostkey", oVisualHostKey },
231 { "useroaming", oUseRoaming },
232 { "routingdomain", oRDomain },
233#ifdef JPAKE
234 { "zeroknowledgepasswordauthentication",
235 oZeroKnowledgePasswordAuthentication },
236#else
237 { "zeroknowledgepasswordauthentication", oUnsupported },
238#endif
239
240 { NULL, oBadOption }
241};
242
243/*
244 * Adds a local TCP/IP port forward to options. Never returns if there is an
245 * error.
246 */
247
248void
249add_local_forward(Options *options, const Forward *newfwd)
250{
251 Forward *fwd;
252#ifndef NO_IPPORT_RESERVED_CONCEPT
253 extern uid_t original_real_uid;
254 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
255 fatal("Privileged ports can only be forwarded by root.");
256#endif
257 if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
258 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
259 fwd = &options->local_forwards[options->num_local_forwards++];
260
261 fwd->listen_host = newfwd->listen_host;
262 fwd->listen_port = newfwd->listen_port;
263 fwd->connect_host = newfwd->connect_host;
264 fwd->connect_port = newfwd->connect_port;
265}
266
267/*
268 * Adds a remote TCP/IP port forward to options. Never returns if there is
269 * an error.
270 */
271
272void
273add_remote_forward(Options *options, const Forward *newfwd)
274{
275 Forward *fwd;
276 if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
277 fatal("Too many remote forwards (max %d).",
278 SSH_MAX_FORWARDS_PER_DIRECTION);
279 fwd = &options->remote_forwards[options->num_remote_forwards++];
280
281 fwd->listen_host = newfwd->listen_host;
282 fwd->listen_port = newfwd->listen_port;
283 fwd->connect_host = newfwd->connect_host;
284 fwd->connect_port = newfwd->connect_port;
285}
286
287static void
288clear_forwardings(Options *options)
289{
290 int i;
291
292 for (i = 0; i < options->num_local_forwards; i++) {
293 if (options->local_forwards[i].listen_host != NULL)
294 xfree(options->local_forwards[i].listen_host);
295 xfree(options->local_forwards[i].connect_host);
296 }
297 options->num_local_forwards = 0;
298 for (i = 0; i < options->num_remote_forwards; i++) {
299 if (options->remote_forwards[i].listen_host != NULL)
300 xfree(options->remote_forwards[i].listen_host);
301 xfree(options->remote_forwards[i].connect_host);
302 }
303 options->num_remote_forwards = 0;
304 options->tun_open = SSH_TUNMODE_NO;
305}
306
307/*
308 * Returns the number of the token pointed to by cp or oBadOption.
309 */
310
311static OpCodes
312parse_token(const char *cp, const char *filename, int linenum)
313{
314 u_int i;
315
316 for (i = 0; keywords[i].name; i++)
317 if (strcasecmp(cp, keywords[i].name) == 0)
318 return keywords[i].opcode;
319
320 error("%s: line %d: Bad configuration option: %s",
321 filename, linenum, cp);
322 return oBadOption;
323}
324
325/*
326 * Processes a single option line as used in the configuration files. This
327 * only sets those values that have not already been set.
328 */
329#define WHITESPACE " \t\r\n"
330
331int
332process_config_line(Options *options, const char *host,
333 char *line, const char *filename, int linenum,
334 int *activep)
335{
336 char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
337 int opcode, *intptr, value, value2, scale;
338 LogLevel *log_level_ptr;
339 long long orig, val64;
340 size_t len;
341 Forward fwd;
342
343 /* Strip trailing whitespace */
344 for (len = strlen(line) - 1; len > 0; len--) {
345 if (strchr(WHITESPACE, line[len]) == NULL)
346 break;
347 line[len] = '\0';
348 }
349
350 s = line;
351 /* Get the keyword. (Each line is supposed to begin with a keyword). */
352 if ((keyword = strdelim(&s)) == NULL)
353 return 0;
354 /* Ignore leading whitespace. */
355 if (*keyword == '\0')
356 keyword = strdelim(&s);
357 if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
358 return 0;
359
360 opcode = parse_token(keyword, filename, linenum);
361
362 switch (opcode) {
363 case oBadOption:
364 /* don't panic, but count bad options */
365 return -1;
366 /* NOTREACHED */
367 case oConnectTimeout:
368 intptr = &options->connection_timeout;
369parse_time:
370 arg = strdelim(&s);
371 if (!arg || *arg == '\0')
372 fatal("%s line %d: missing time value.",
373 filename, linenum);
374 if ((value = convtime(arg)) == -1)
375 fatal("%s line %d: invalid time value.",
376 filename, linenum);
377 if (*activep && *intptr == -1)
378 *intptr = value;
379 break;
380
381 case oForwardAgent:
382 intptr = &options->forward_agent;
383parse_flag:
384 arg = strdelim(&s);
385 if (!arg || *arg == '\0')
386 fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
387 value = 0; /* To avoid compiler warning... */
388 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
389 value = 1;
390 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
391 value = 0;
392 else
393 fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
394 if (*activep && *intptr == -1)
395 *intptr = value;
396 break;
397
398 case oForwardX11:
399 intptr = &options->forward_x11;
400 goto parse_flag;
401
402 case oForwardX11Trusted:
403 intptr = &options->forward_x11_trusted;
404 goto parse_flag;
405
406 case oGatewayPorts:
407 intptr = &options->gateway_ports;
408 goto parse_flag;
409
410 case oExitOnForwardFailure:
411 intptr = &options->exit_on_forward_failure;
412 goto parse_flag;
413
414 case oUsePrivilegedPort:
415 intptr = &options->use_privileged_port;
416 goto parse_flag;
417
418 case oPasswordAuthentication:
419 intptr = &options->password_authentication;
420 goto parse_flag;
421
422 case oZeroKnowledgePasswordAuthentication:
423 intptr = &options->zero_knowledge_password_authentication;
424 goto parse_flag;
425
426 case oKbdInteractiveAuthentication:
427 intptr = &options->kbd_interactive_authentication;
428 goto parse_flag;
429
430 case oKbdInteractiveDevices:
431 charptr = &options->kbd_interactive_devices;
432 goto parse_string;
433
434 case oPubkeyAuthentication:
435 intptr = &options->pubkey_authentication;
436 goto parse_flag;
437
438 case oRSAAuthentication:
439 intptr = &options->rsa_authentication;
440 goto parse_flag;
441
442 case oRhostsRSAAuthentication:
443 intptr = &options->rhosts_rsa_authentication;
444 goto parse_flag;
445
446 case oHostbasedAuthentication:
447 intptr = &options->hostbased_authentication;
448 goto parse_flag;
449
450 case oChallengeResponseAuthentication:
451 intptr = &options->challenge_response_authentication;
452 goto parse_flag;
453
454 case oGssAuthentication:
455 intptr = &options->gss_authentication;
456 goto parse_flag;
457
458 case oGssDelegateCreds:
459 intptr = &options->gss_deleg_creds;
460 goto parse_flag;
461
462 case oBatchMode:
463 intptr = &options->batch_mode;
464 goto parse_flag;
465
466 case oCheckHostIP:
467 intptr = &options->check_host_ip;
468 goto parse_flag;
469
470 case oVerifyHostKeyDNS:
471 intptr = &options->verify_host_key_dns;
472 goto parse_yesnoask;
473
474 case oStrictHostKeyChecking:
475 intptr = &options->strict_host_key_checking;
476parse_yesnoask:
477 arg = strdelim(&s);
478 if (!arg || *arg == '\0')
479 fatal("%.200s line %d: Missing yes/no/ask argument.",
480 filename, linenum);
481 value = 0; /* To avoid compiler warning... */
482 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
483 value = 1;
484 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
485 value = 0;
486 else if (strcmp(arg, "ask") == 0)
487 value = 2;
488 else
489 fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
490 if (*activep && *intptr == -1)
491 *intptr = value;
492 break;
493
494 case oCompression:
495 intptr = &options->compression;
496 goto parse_flag;
497
498 case oTCPKeepAlive:
499 intptr = &options->tcp_keep_alive;
500 goto parse_flag;
501
502 case oNoHostAuthenticationForLocalhost:
503 intptr = &options->no_host_authentication_for_localhost;
504 goto parse_flag;
505
506 case oNumberOfPasswordPrompts:
507 intptr = &options->number_of_password_prompts;
508 goto parse_int;
509
510 case oCompressionLevel:
511 intptr = &options->compression_level;
512 goto parse_int;
513
514 case oRekeyLimit:
515 arg = strdelim(&s);
516 if (!arg || *arg == '\0')
517 fatal("%.200s line %d: Missing argument.", filename, linenum);
518 if (arg[0] < '0' || arg[0] > '9')
519 fatal("%.200s line %d: Bad number.", filename, linenum);
520 orig = val64 = strtoll(arg, &endofnumber, 10);
521 if (arg == endofnumber)
522 fatal("%.200s line %d: Bad number.", filename, linenum);
523 switch (toupper(*endofnumber)) {
524 case '\0':
525 scale = 1;
526 break;
527 case 'K':
528 scale = 1<<10;
529 break;
530 case 'M':
531 scale = 1<<20;
532 break;
533 case 'G':
534 scale = 1<<30;
535 break;
536 default:
537 fatal("%.200s line %d: Invalid RekeyLimit suffix",
538 filename, linenum);
539 }
540 val64 *= scale;
541 /* detect integer wrap and too-large limits */
542 if ((val64 / scale) != orig || val64 > UINT_MAX)
543 fatal("%.200s line %d: RekeyLimit too large",
544 filename, linenum);
545 if (val64 < 16)
546 fatal("%.200s line %d: RekeyLimit too small",
547 filename, linenum);
548 if (*activep && options->rekey_limit == -1)
549 options->rekey_limit = (u_int32_t)val64;
550 break;
551
552 case oIdentityFile:
553 arg = strdelim(&s);
554 if (!arg || *arg == '\0')
555 fatal("%.200s line %d: Missing argument.", filename, linenum);
556 if (*activep) {
557 intptr = &options->num_identity_files;
558 if (*intptr >= SSH_MAX_IDENTITY_FILES)
559 fatal("%.200s line %d: Too many identity files specified (max %d).",
560 filename, linenum, SSH_MAX_IDENTITY_FILES);
561 charptr = &options->identity_files[*intptr];
562 *charptr = xstrdup(arg);
563 *intptr = *intptr + 1;
564 }
565 break;
566
567 case oXAuthLocation:
568 charptr=&options->xauth_location;
569 goto parse_string;
570
571 case oUser:
572 charptr = &options->user;
573parse_string:
574 arg = strdelim(&s);
575 if (!arg || *arg == '\0')
576 fatal("%.200s line %d: Missing argument.", filename, linenum);
577 if (*activep && *charptr == NULL)
578 *charptr = xstrdup(arg);
579 break;
580
581 case oGlobalKnownHostsFile:
582 charptr = &options->system_hostfile;
583 goto parse_string;
584
585 case oUserKnownHostsFile:
586 charptr = &options->user_hostfile;
587 goto parse_string;
588
589 case oGlobalKnownHostsFile2:
590 charptr = &options->system_hostfile2;
591 goto parse_string;
592
593 case oUserKnownHostsFile2:
594 charptr = &options->user_hostfile2;
595 goto parse_string;
596
597 case oHostName:
598 charptr = &options->hostname;
599 goto parse_string;
600
601 case oHostKeyAlias:
602 charptr = &options->host_key_alias;
603 goto parse_string;
604
605 case oPreferredAuthentications:
606 charptr = &options->preferred_authentications;
607 goto parse_string;
608
609 case oBindAddress:
610 charptr = &options->bind_address;
611 goto parse_string;
612
613 case oSmartcardDevice:
614 charptr = &options->smartcard_device;
615 goto parse_string;
616
617 case oProxyCommand:
618 charptr = &options->proxy_command;
619parse_command:
620 if (s == NULL)
621 fatal("%.200s line %d: Missing argument.", filename, linenum);
622 len = strspn(s, WHITESPACE "=");
623 if (*activep && *charptr == NULL)
624 *charptr = xstrdup(s + len);
625 return 0;
626
627 case oPort:
628 intptr = &options->port;
629parse_int:
630 arg = strdelim(&s);
631 if (!arg || *arg == '\0')
632 fatal("%.200s line %d: Missing argument.", filename, linenum);
633 if (arg[0] < '0' || arg[0] > '9')
634 fatal("%.200s line %d: Bad number.", filename, linenum);
635
636 /* Octal, decimal, or hex format? */
637 value = strtol(arg, &endofnumber, 0);
638 if (arg == endofnumber)
639 fatal("%.200s line %d: Bad number.", filename, linenum);
640 if (*activep && *intptr == -1)
641 *intptr = value;
642 break;
643
644 case oConnectionAttempts:
645 intptr = &options->connection_attempts;
646 goto parse_int;
647
648 case oCipher:
649 intptr = &options->cipher;
650 arg = strdelim(&s);
651 if (!arg || *arg == '\0')
652 fatal("%.200s line %d: Missing argument.", filename, linenum);
653 value = cipher_number(arg);
654 if (value == -1)
655 fatal("%.200s line %d: Bad cipher '%s'.",
656 filename, linenum, arg ? arg : "<NONE>");
657 if (*activep && *intptr == -1)
658 *intptr = value;
659 break;
660
661 case oCiphers:
662 arg = strdelim(&s);
663 if (!arg || *arg == '\0')
664 fatal("%.200s line %d: Missing argument.", filename, linenum);
665 if (!ciphers_valid(arg))
666 fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
667 filename, linenum, arg ? arg : "<NONE>");
668 if (*activep && options->ciphers == NULL)
669 options->ciphers = xstrdup(arg);
670 break;
671
672 case oMacs:
673 arg = strdelim(&s);
674 if (!arg || *arg == '\0')
675 fatal("%.200s line %d: Missing argument.", filename, linenum);
676 if (!mac_valid(arg))
677 fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
678 filename, linenum, arg ? arg : "<NONE>");
679 if (*activep && options->macs == NULL)
680 options->macs = xstrdup(arg);
681 break;
682
683 case oHostKeyAlgorithms:
684 arg = strdelim(&s);
685 if (!arg || *arg == '\0')
686 fatal("%.200s line %d: Missing argument.", filename, linenum);
687 if (!key_names_valid2(arg))
688 fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
689 filename, linenum, arg ? arg : "<NONE>");
690 if (*activep && options->hostkeyalgorithms == NULL)
691 options->hostkeyalgorithms = xstrdup(arg);
692 break;
693
694 case oProtocol:
695 intptr = &options->protocol;
696 arg = strdelim(&s);
697 if (!arg || *arg == '\0')
698 fatal("%.200s line %d: Missing argument.", filename, linenum);
699 value = proto_spec(arg);
700 if (value == SSH_PROTO_UNKNOWN)
701 fatal("%.200s line %d: Bad protocol spec '%s'.",
702 filename, linenum, arg ? arg : "<NONE>");
703 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
704 *intptr = value;
705 break;
706
707 case oLogLevel:
708 log_level_ptr = &options->log_level;
709 arg = strdelim(&s);
710 value = log_level_number(arg);
711 if (value == SYSLOG_LEVEL_NOT_SET)
712 fatal("%.200s line %d: unsupported log level '%s'",
713 filename, linenum, arg ? arg : "<NONE>");
714 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
715 *log_level_ptr = (LogLevel) value;
716 break;
717
718 case oLocalForward:
719 case oRemoteForward:
720 case oDynamicForward:
721 arg = strdelim(&s);
722 if (arg == NULL || *arg == '\0')
723 fatal("%.200s line %d: Missing port argument.",
724 filename, linenum);
725
726 if (opcode == oLocalForward ||
727 opcode == oRemoteForward) {
728 arg2 = strdelim(&s);
729 if (arg2 == NULL || *arg2 == '\0')
730 fatal("%.200s line %d: Missing target argument.",
731 filename, linenum);
732
733 /* construct a string for parse_forward */
734 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
735 } else if (opcode == oDynamicForward) {
736 strlcpy(fwdarg, arg, sizeof(fwdarg));
737 }
738
739 if (parse_forward(&fwd, fwdarg,
740 opcode == oDynamicForward ? 1 : 0,
741 opcode == oRemoteForward ? 1 : 0) == 0)
742 fatal("%.200s line %d: Bad forwarding specification.",
743 filename, linenum);
744
745 if (*activep) {
746 if (opcode == oLocalForward ||
747 opcode == oDynamicForward)
748 add_local_forward(options, &fwd);
749 else if (opcode == oRemoteForward)
750 add_remote_forward(options, &fwd);
751 }
752 break;
753
754 case oClearAllForwardings:
755 intptr = &options->clear_forwardings;
756 goto parse_flag;
757
758 case oHost:
759 *activep = 0;
760 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
761 if (match_pattern(host, arg)) {
762 debug("Applying options for %.100s", arg);
763 *activep = 1;
764 break;
765 }
766 /* Avoid garbage check below, as strdelim is done. */
767 return 0;
768
769 case oEscapeChar:
770 intptr = &options->escape_char;
771 arg = strdelim(&s);
772 if (!arg || *arg == '\0')
773 fatal("%.200s line %d: Missing argument.", filename, linenum);
774 if (arg[0] == '^' && arg[2] == 0 &&
775 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
776 value = (u_char) arg[1] & 31;
777 else if (strlen(arg) == 1)
778 value = (u_char) arg[0];
779 else if (strcmp(arg, "none") == 0)
780 value = SSH_ESCAPECHAR_NONE;
781 else {
782 fatal("%.200s line %d: Bad escape character.",
783 filename, linenum);
784 /* NOTREACHED */
785 value = 0; /* Avoid compiler warning. */
786 }
787 if (*activep && *intptr == -1)
788 *intptr = value;
789 break;
790
791 case oAddressFamily:
792 arg = strdelim(&s);
793 if (!arg || *arg == '\0')
794 fatal("%s line %d: missing address family.",
795 filename, linenum);
796 intptr = &options->address_family;
797 if (strcasecmp(arg, "inet") == 0)
798 value = AF_INET;
799 else if (strcasecmp(arg, "inet6") == 0)
800 value = AF_INET6;
801 else if (strcasecmp(arg, "any") == 0)
802 value = AF_UNSPEC;
803 else
804 fatal("Unsupported AddressFamily \"%s\"", arg);
805 if (*activep && *intptr == -1)
806 *intptr = value;
807 break;
808
809 case oEnableSSHKeysign:
810 intptr = &options->enable_ssh_keysign;
811 goto parse_flag;
812
813 case oIdentitiesOnly:
814 intptr = &options->identities_only;
815 goto parse_flag;
816
817 case oServerAliveInterval:
818 intptr = &options->server_alive_interval;
819 goto parse_time;
820
821 case oServerAliveCountMax:
822 intptr = &options->server_alive_count_max;
823 goto parse_int;
824
825 case oSendEnv:
826 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
827 if (strchr(arg, '=') != NULL)
828 fatal("%s line %d: Invalid environment name.",
829 filename, linenum);
830 if (!*activep)
831 continue;
832 if (options->num_send_env >= MAX_SEND_ENV)
833 fatal("%s line %d: too many send env.",
834 filename, linenum);
835 options->send_env[options->num_send_env++] =
836 xstrdup(arg);
837 }
838 break;
839
840 case oControlPath:
841 charptr = &options->control_path;
842 goto parse_string;
843
844 case oControlMaster:
845 intptr = &options->control_master;
846 arg = strdelim(&s);
847 if (!arg || *arg == '\0')
848 fatal("%.200s line %d: Missing ControlMaster argument.",
849 filename, linenum);
850 value = 0; /* To avoid compiler warning... */
851 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
852 value = SSHCTL_MASTER_YES;
853 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
854 value = SSHCTL_MASTER_NO;
855 else if (strcmp(arg, "auto") == 0)
856 value = SSHCTL_MASTER_AUTO;
857 else if (strcmp(arg, "ask") == 0)
858 value = SSHCTL_MASTER_ASK;
859 else if (strcmp(arg, "autoask") == 0)
860 value = SSHCTL_MASTER_AUTO_ASK;
861 else
862 fatal("%.200s line %d: Bad ControlMaster argument.",
863 filename, linenum);
864 if (*activep && *intptr == -1)
865 *intptr = value;
866 break;
867
868 case oHashKnownHosts:
869 intptr = &options->hash_known_hosts;
870 goto parse_flag;
871
872 case oTunnel:
873 intptr = &options->tun_open;
874 arg = strdelim(&s);
875 if (!arg || *arg == '\0')
876 fatal("%s line %d: Missing yes/point-to-point/"
877 "ethernet/no argument.", filename, linenum);
878 value = 0; /* silence compiler */
879 if (strcasecmp(arg, "ethernet") == 0)
880 value = SSH_TUNMODE_ETHERNET;
881 else if (strcasecmp(arg, "point-to-point") == 0)
882 value = SSH_TUNMODE_POINTOPOINT;
883 else if (strcasecmp(arg, "yes") == 0)
884 value = SSH_TUNMODE_DEFAULT;
885 else if (strcasecmp(arg, "no") == 0)
886 value = SSH_TUNMODE_NO;
887 else
888 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
889 "no argument: %s", filename, linenum, arg);
890 if (*activep)
891 *intptr = value;
892 break;
893
894 case oTunnelDevice:
895 arg = strdelim(&s);
896 if (!arg || *arg == '\0')
897 fatal("%.200s line %d: Missing argument.", filename, linenum);
898 value = a2tun(arg, &value2);
899 if (value == SSH_TUNID_ERR)
900 fatal("%.200s line %d: Bad tun device.", filename, linenum);
901 if (*activep) {
902 options->tun_local = value;
903 options->tun_remote = value2;
904 }
905 break;
906
907 case oLocalCommand:
908 charptr = &options->local_command;
909 goto parse_command;
910
911 case oPermitLocalCommand:
912 intptr = &options->permit_local_command;
913 goto parse_flag;
914
915 case oVisualHostKey:
916 intptr = &options->visual_host_key;
917 goto parse_flag;
918
919 case oUseRoaming:
920 intptr = &options->use_roaming;
921 goto parse_flag;
922
923 case oRDomain:
924 arg = strdelim(&s);
925 if (!arg || *arg == '\0')
926 fatal("%.200s line %d: Missing argument.",
927 filename, linenum);
928 value = a2rdomain(arg);
929 if (value == -1)
930 fatal("%.200s line %d: Bad rdomain.",
931 filename, linenum);
932 if (*activep)
933 options->rdomain = value;
934 break;
935
936 case oDeprecated:
937 debug("%s line %d: Deprecated option \"%s\"",
938 filename, linenum, keyword);
939 return 0;
940
941 case oUnsupported:
942 error("%s line %d: Unsupported option \"%s\"",
943 filename, linenum, keyword);
944 return 0;
945
946 default:
947 fatal("process_config_line: Unimplemented opcode %d", opcode);
948 }
949
950 /* Check that there is no garbage at end of line. */
951 if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
952 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
953 filename, linenum, arg);
954 }
955 return 0;
956}
957
958
959/*
960 * Reads the config file and modifies the options accordingly. Options
961 * should already be initialized before this call. This never returns if
962 * there is an error. If the file does not exist, this returns 0.
963 */
964
965int
966read_config_file(const char *filename, const char *host, Options *options,
967 int checkperm)
968{
969 FILE *f;
970 char line[1024];
971 int active, linenum;
972 int bad_options = 0;
973
974 if ((f = fopen(filename, "r")) == NULL)
975 return 0;
976
977 if (checkperm) {
978 struct stat sb;
979
980 if (fstat(fileno(f), &sb) == -1)
981 fatal("fstat %s: %s", filename, strerror(errno));
982 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
983 (sb.st_mode & 022) != 0))
984 fatal("Bad owner or permissions on %s", filename);
985 }
986
987 debug("Reading configuration data %.200s", filename);
988
989 /*
990 * Mark that we are now processing the options. This flag is turned
991 * on/off by Host specifications.
992 */
993 active = 1;
994 linenum = 0;
995 while (fgets(line, sizeof(line), f)) {
996 /* Update line number counter. */
997 linenum++;
998 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
999 bad_options++;
1000 }
1001 fclose(f);
1002 if (bad_options > 0)
1003 fatal("%s: terminating, %d bad configuration options",
1004 filename, bad_options);
1005 return 1;
1006}
1007
1008/*
1009 * Initializes options to special values that indicate that they have not yet
1010 * been set. Read_config_file will only set options with this value. Options
1011 * are processed in the following order: command line, user config file,
1012 * system config file. Last, fill_default_options is called.
1013 */
1014
1015void
1016initialize_options(Options * options)
1017{
1018 memset(options, 'X', sizeof(*options));
1019 options->forward_agent = -1;
1020 options->forward_x11 = -1;
1021 options->forward_x11_trusted = -1;
1022 options->exit_on_forward_failure = -1;
1023 options->xauth_location = NULL;
1024 options->gateway_ports = -1;
1025 options->use_privileged_port = -1;
1026 options->rsa_authentication = -1;
1027 options->pubkey_authentication = -1;
1028 options->challenge_response_authentication = -1;
1029 options->gss_authentication = -1;
1030 options->gss_deleg_creds = -1;
1031 options->password_authentication = -1;
1032 options->kbd_interactive_authentication = -1;
1033 options->kbd_interactive_devices = NULL;
1034 options->rhosts_rsa_authentication = -1;
1035 options->hostbased_authentication = -1;
1036 options->batch_mode = -1;
1037 options->check_host_ip = -1;
1038 options->strict_host_key_checking = -1;
1039 options->compression = -1;
1040 options->tcp_keep_alive = -1;
1041 options->compression_level = -1;
1042 options->port = -1;
1043 options->address_family = -1;
1044 options->connection_attempts = -1;
1045 options->connection_timeout = -1;
1046 options->number_of_password_prompts = -1;
1047 options->cipher = -1;
1048 options->ciphers = NULL;
1049 options->macs = NULL;
1050 options->hostkeyalgorithms = NULL;
1051 options->protocol = SSH_PROTO_UNKNOWN;
1052 options->num_identity_files = 0;
1053 options->hostname = NULL;
1054 options->host_key_alias = NULL;
1055 options->proxy_command = NULL;
1056 options->user = NULL;
1057 options->escape_char = -1;
1058 options->system_hostfile = NULL;
1059 options->user_hostfile = NULL;
1060 options->system_hostfile2 = NULL;
1061 options->user_hostfile2 = NULL;
1062 options->num_local_forwards = 0;
1063 options->num_remote_forwards = 0;
1064 options->clear_forwardings = -1;
1065 options->log_level = SYSLOG_LEVEL_NOT_SET;
1066 options->preferred_authentications = NULL;
1067 options->bind_address = NULL;
1068 options->smartcard_device = NULL;
1069 options->enable_ssh_keysign = - 1;
1070 options->no_host_authentication_for_localhost = - 1;
1071 options->identities_only = - 1;
1072 options->rekey_limit = - 1;
1073 options->verify_host_key_dns = -1;
1074 options->server_alive_interval = -1;
1075 options->server_alive_count_max = -1;
1076 options->num_send_env = 0;
1077 options->control_path = NULL;
1078 options->control_master = -1;
1079 options->hash_known_hosts = -1;
1080 options->tun_open = -1;
1081 options->tun_local = -1;
1082 options->tun_remote = -1;
1083 options->local_command = NULL;
1084 options->permit_local_command = -1;
1085 options->use_roaming = -1;
1086 options->rdomain = -1;
1087 options->visual_host_key = -1;
1088 options->zero_knowledge_password_authentication = -1;
1089}
1090
1091/*
1092 * Called after processing other sources of option data, this fills those
1093 * options for which no value has been specified with their default values.
1094 */
1095
1096void
1097fill_default_options(Options * options)
1098{
1099 int len;
1100
1101 if (options->forward_agent == -1)
1102 options->forward_agent = 0;
1103 if (options->forward_x11 == -1)
1104 options->forward_x11 = 0;
1105 if (options->forward_x11_trusted == -1)
1106 options->forward_x11_trusted = 0;
1107 if (options->exit_on_forward_failure == -1)
1108 options->exit_on_forward_failure = 0;
1109 if (options->xauth_location == NULL)
1110 options->xauth_location = _PATH_XAUTH;
1111 if (options->gateway_ports == -1)
1112 options->gateway_ports = 0;
1113 if (options->use_privileged_port == -1)
1114 options->use_privileged_port = 0;
1115 if (options->rsa_authentication == -1)
1116 options->rsa_authentication = 1;
1117 if (options->pubkey_authentication == -1)
1118 options->pubkey_authentication = 1;
1119 if (options->challenge_response_authentication == -1)
1120 options->challenge_response_authentication = 1;
1121 if (options->gss_authentication == -1)
1122 options->gss_authentication = 0;
1123 if (options->gss_deleg_creds == -1)
1124 options->gss_deleg_creds = 0;
1125 if (options->password_authentication == -1)
1126 options->password_authentication = 1;
1127 if (options->kbd_interactive_authentication == -1)
1128 options->kbd_interactive_authentication = 1;
1129 if (options->rhosts_rsa_authentication == -1)
1130 options->rhosts_rsa_authentication = 0;
1131 if (options->hostbased_authentication == -1)
1132 options->hostbased_authentication = 0;
1133 if (options->batch_mode == -1)
1134 options->batch_mode = 0;
1135 if (options->check_host_ip == -1)
1136 options->check_host_ip = 1;
1137 if (options->strict_host_key_checking == -1)
1138 options->strict_host_key_checking = 2; /* 2 is default */
1139 if (options->compression == -1)
1140 options->compression = 0;
1141 if (options->tcp_keep_alive == -1)
1142 options->tcp_keep_alive = 1;
1143 if (options->compression_level == -1)
1144 options->compression_level = 6;
1145 if (options->port == -1)
1146 options->port = 0; /* Filled in ssh_connect. */
1147 if (options->address_family == -1)
1148 options->address_family = AF_UNSPEC;
1149 if (options->connection_attempts == -1)
1150 options->connection_attempts = 1;
1151 if (options->number_of_password_prompts == -1)
1152 options->number_of_password_prompts = 3;
1153 /* Selected in ssh_login(). */
1154 if (options->cipher == -1)
1155 options->cipher = SSH_CIPHER_NOT_SET;
1156 /* options->ciphers, default set in myproposals.h */
1157 /* options->macs, default set in myproposals.h */
1158 /* options->hostkeyalgorithms, default set in myproposals.h */
1159 if (options->protocol == SSH_PROTO_UNKNOWN)
1160 options->protocol = SSH_PROTO_2;
1161 if (options->num_identity_files == 0) {
1162 if (options->protocol & SSH_PROTO_1) {
1163 len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1164 options->identity_files[options->num_identity_files] =
1165 xmalloc(len);
1166 snprintf(options->identity_files[options->num_identity_files++],
1167 len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1168 }
1169 if (options->protocol & SSH_PROTO_2) {
1170 len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1171 options->identity_files[options->num_identity_files] =
1172 xmalloc(len);
1173 snprintf(options->identity_files[options->num_identity_files++],
1174 len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1175
1176 len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1177 options->identity_files[options->num_identity_files] =
1178 xmalloc(len);
1179 snprintf(options->identity_files[options->num_identity_files++],
1180 len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1181 }
1182 }
1183 if (options->escape_char == -1)
1184 options->escape_char = '~';
1185 if (options->system_hostfile == NULL)
1186 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1187 if (options->user_hostfile == NULL)
1188 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1189 if (options->system_hostfile2 == NULL)
1190 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1191 if (options->user_hostfile2 == NULL)
1192 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1193 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1194 options->log_level = SYSLOG_LEVEL_INFO;
1195 if (options->clear_forwardings == 1)
1196 clear_forwardings(options);
1197 if (options->no_host_authentication_for_localhost == - 1)
1198 options->no_host_authentication_for_localhost = 0;
1199 if (options->identities_only == -1)
1200 options->identities_only = 0;
1201 if (options->enable_ssh_keysign == -1)
1202 options->enable_ssh_keysign = 0;
1203 if (options->rekey_limit == -1)
1204 options->rekey_limit = 0;
1205 if (options->verify_host_key_dns == -1)
1206 options->verify_host_key_dns = 0;
1207 if (options->server_alive_interval == -1)
1208 options->server_alive_interval = 0;
1209 if (options->server_alive_count_max == -1)
1210 options->server_alive_count_max = 3;
1211 if (options->control_master == -1)
1212 options->control_master = 0;
1213 if (options->hash_known_hosts == -1)
1214 options->hash_known_hosts = 0;
1215 if (options->tun_open == -1)
1216 options->tun_open = SSH_TUNMODE_NO;
1217 if (options->tun_local == -1)
1218 options->tun_local = SSH_TUNID_ANY;
1219 if (options->tun_remote == -1)
1220 options->tun_remote = SSH_TUNID_ANY;
1221 if (options->permit_local_command == -1)
1222 options->permit_local_command = 0;
1223 if (options->use_roaming == -1)
1224 options->use_roaming = 1;
1225 if (options->visual_host_key == -1)
1226 options->visual_host_key = 0;
1227 if (options->zero_knowledge_password_authentication == -1)
1228 options->zero_knowledge_password_authentication = 0;
1229 /* options->local_command should not be set by default */
1230 /* options->proxy_command should not be set by default */
1231 /* options->user will be set in the main program if appropriate */
1232 /* options->hostname will be set in the main program if appropriate */
1233 /* options->host_key_alias should not be set by default */
1234 /* options->preferred_authentications will be set in ssh */
1235 /* options->rdomain should not be set by default */
1236}
1237
1238/*
1239 * parse_forward
1240 * parses a string containing a port forwarding specification of the form:
1241 * dynamicfwd == 0
1242 * [listenhost:]listenport:connecthost:connectport
1243 * dynamicfwd == 1
1244 * [listenhost:]listenport
1245 * returns number of arguments parsed or zero on error
1246 */
1247int
1248parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1249{
1250 int i;
1251 char *p, *cp, *fwdarg[4];
1252
1253 memset(fwd, '\0', sizeof(*fwd));
1254
1255 cp = p = xstrdup(fwdspec);
1256
1257 /* skip leading spaces */
1258 while (isspace(*cp))
1259 cp++;
1260
1261 for (i = 0; i < 4; ++i)
1262 if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1263 break;
1264
1265 /* Check for trailing garbage */
1266 if (cp != NULL)
1267 i = 0; /* failure */
1268
1269 switch (i) {
1270 case 1:
1271 fwd->listen_host = NULL;
1272 fwd->listen_port = a2port(fwdarg[0]);
1273 fwd->connect_host = xstrdup("socks");
1274 break;
1275
1276 case 2:
1277 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1278 fwd->listen_port = a2port(fwdarg[1]);
1279 fwd->connect_host = xstrdup("socks");
1280 break;
1281
1282 case 3:
1283 fwd->listen_host = NULL;
1284 fwd->listen_port = a2port(fwdarg[0]);
1285 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1286 fwd->connect_port = a2port(fwdarg[2]);
1287 break;
1288
1289 case 4:
1290 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1291 fwd->listen_port = a2port(fwdarg[1]);
1292 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1293 fwd->connect_port = a2port(fwdarg[3]);
1294 break;
1295 default:
1296 i = 0; /* failure */
1297 }
1298
1299 xfree(p);
1300
1301 if (dynamicfwd) {
1302 if (!(i == 1 || i == 2))
1303 goto fail_free;
1304 } else {
1305 if (!(i == 3 || i == 4))
1306 goto fail_free;
1307 if (fwd->connect_port <= 0)
1308 goto fail_free;
1309 }
1310
1311 if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1312 goto fail_free;
1313
1314 if (fwd->connect_host != NULL &&
1315 strlen(fwd->connect_host) >= NI_MAXHOST)
1316 goto fail_free;
1317 if (fwd->listen_host != NULL &&
1318 strlen(fwd->listen_host) >= NI_MAXHOST)
1319 goto fail_free;
1320
1321
1322 return (i);
1323
1324 fail_free:
1325 if (fwd->connect_host != NULL) {
1326 xfree(fwd->connect_host);
1327 fwd->connect_host = NULL;
1328 }
1329 if (fwd->listen_host != NULL) {
1330 xfree(fwd->listen_host);
1331 fwd->listen_host = NULL;
1332 }
1333 return (0);
1334}
This page took 0.051911 seconds and 5 git commands to generate.