Bug Summary

File:src/usr.bin/ssh/ssh/../readconf.c
Warning:line 1663, column 5
Value stored to 'p' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name readconf.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.bin/ssh/ssh/.. -D WITH_OPENSSL -D WITH_ZLIB -D WITH_DSA -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/ssh/ssh/../readconf.c
1/* $OpenBSD: readconf.c,v 1.384 2024/01/11 01:45:36 djm 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 <sys/types.h>
16#include <sys/stat.h>
17#include <sys/socket.h>
18#include <sys/wait.h>
19#include <sys/un.h>
20
21#include <net/if.h>
22#include <netinet/in.h>
23#include <netinet/ip.h>
24
25#include <ctype.h>
26#include <errno(*__errno()).h>
27#include <fcntl.h>
28#include <glob.h>
29#include <ifaddrs.h>
30#include <netdb.h>
31#include <paths.h>
32#include <pwd.h>
33#include <signal.h>
34#include <stdio.h>
35#include <string.h>
36#include <stdarg.h>
37#include <unistd.h>
38#include <limits.h>
39#include <util.h>
40#include <vis.h>
41
42#include "xmalloc.h"
43#include "ssh.h"
44#include "ssherr.h"
45#include "cipher.h"
46#include "pathnames.h"
47#include "log.h"
48#include "sshkey.h"
49#include "misc.h"
50#include "readconf.h"
51#include "match.h"
52#include "kex.h"
53#include "mac.h"
54#include "uidswap.h"
55#include "myproposal.h"
56#include "digest.h"
57
58/* Format of the configuration file:
59
60 # Configuration data is parsed as follows:
61 # 1. command line options
62 # 2. user-specific file
63 # 3. system-wide file
64 # Any configuration value is only changed the first time it is set.
65 # Thus, host-specific definitions should be at the beginning of the
66 # configuration file, and defaults at the end.
67
68 # Host-specific declarations. These may override anything above. A single
69 # host may match multiple declarations; these are processed in the order
70 # that they are given in.
71
72 Host *.ngs.fi ngs.fi
73 User foo
74
75 Host fake.com
76 Hostname another.host.name.real.org
77 User blaah
78 Port 34289
79 ForwardX11 no
80 ForwardAgent no
81
82 Host books.com
83 RemoteForward 9999 shadows.cs.hut.fi:9999
84 Ciphers 3des-cbc
85
86 Host fascist.blob.com
87 Port 23123
88 User tylonen
89 PasswordAuthentication no
90
91 Host puukko.hut.fi
92 User t35124p
93 ProxyCommand ssh-proxy %h %p
94
95 Host *.fr
96 PublicKeyAuthentication no
97
98 Host *.su
99 Ciphers aes128-ctr
100 PasswordAuthentication no
101
102 Host vpn.fake.com
103 Tunnel yes
104 TunnelDevice 3
105
106 # Defaults for various options
107 Host *
108 ForwardAgent no
109 ForwardX11 no
110 PasswordAuthentication yes
111 StrictHostKeyChecking yes
112 TcpKeepAlive no
113 IdentityFile ~/.ssh/identity
114 Port 22
115 EscapeChar ~
116
117*/
118
119static int read_config_file_depth(const char *filename, struct passwd *pw,
120 const char *host, const char *original_host, Options *options,
121 int flags, int *activep, int *want_final_pass, int depth);
122static int process_config_line_depth(Options *options, struct passwd *pw,
123 const char *host, const char *original_host, char *line,
124 const char *filename, int linenum, int *activep, int flags,
125 int *want_final_pass, int depth);
126
127/* Keyword tokens. */
128
129typedef enum {
130 oBadOption,
131 oHost, oMatch, oInclude, oTag,
132 oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
133 oGatewayPorts, oExitOnForwardFailure,
134 oPasswordAuthentication,
135 oXAuthLocation,
136 oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
137 oPermitRemoteOpen,
138 oCertificateFile, oAddKeysToAgent, oIdentityAgent,
139 oUser, oEscapeChar, oProxyCommand,
140 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
141 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
142 oTCPKeepAlive, oNumberOfPasswordPrompts,
143 oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
144 oPubkeyAuthentication,
145 oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
146 oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
147 oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
148 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
149 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
150 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
151 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
152 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
153 oHashKnownHosts,
154 oTunnel, oTunnelDevice,
155 oLocalCommand, oPermitLocalCommand, oRemoteCommand,
156 oVisualHostKey,
157 oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
158 oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
159 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
160 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
161 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
162 oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
163 oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
164 oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
165 oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout,
166 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
167} OpCodes;
168
169/* Textual representations of the tokens. */
170
171static struct {
172 const char *name;
173 OpCodes opcode;
174} keywords[] = {
175 /* Deprecated options */
176 { "protocol", oIgnore }, /* NB. silently ignored */
177 { "cipher", oDeprecated },
178 { "fallbacktorsh", oDeprecated },
179 { "globalknownhostsfile2", oDeprecated },
180 { "rhostsauthentication", oDeprecated },
181 { "userknownhostsfile2", oDeprecated },
182 { "useroaming", oDeprecated },
183 { "usersh", oDeprecated },
184 { "useprivilegedport", oDeprecated },
185
186 /* Unsupported options */
187 { "afstokenpassing", oUnsupported },
188 { "kerberosauthentication", oUnsupported },
189 { "kerberostgtpassing", oUnsupported },
190 { "rsaauthentication", oUnsupported },
191 { "rhostsrsaauthentication", oUnsupported },
192 { "compressionlevel", oUnsupported },
193
194 /* Sometimes-unsupported options */
195#if defined(GSSAPI)
196 { "gssapiauthentication", oGssAuthentication },
197 { "gssapidelegatecredentials", oGssDelegateCreds },
198# else
199 { "gssapiauthentication", oUnsupported },
200 { "gssapidelegatecredentials", oUnsupported },
201#endif
202#ifdef ENABLE_PKCS111
203 { "pkcs11provider", oPKCS11Provider },
204 { "smartcarddevice", oPKCS11Provider },
205# else
206 { "smartcarddevice", oUnsupported },
207 { "pkcs11provider", oUnsupported },
208#endif
209
210 { "forwardagent", oForwardAgent },
211 { "forwardx11", oForwardX11 },
212 { "forwardx11trusted", oForwardX11Trusted },
213 { "forwardx11timeout", oForwardX11Timeout },
214 { "exitonforwardfailure", oExitOnForwardFailure },
215 { "xauthlocation", oXAuthLocation },
216 { "gatewayports", oGatewayPorts },
217 { "passwordauthentication", oPasswordAuthentication },
218 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
219 { "kbdinteractivedevices", oKbdInteractiveDevices },
220 { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
221 { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
222 { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */
223 { "pubkeyauthentication", oPubkeyAuthentication },
224 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
225 { "hostbasedauthentication", oHostbasedAuthentication },
226 { "identityfile", oIdentityFile },
227 { "identityfile2", oIdentityFile }, /* obsolete */
228 { "identitiesonly", oIdentitiesOnly },
229 { "certificatefile", oCertificateFile },
230 { "addkeystoagent", oAddKeysToAgent },
231 { "identityagent", oIdentityAgent },
232 { "hostname", oHostname },
233 { "hostkeyalias", oHostKeyAlias },
234 { "proxycommand", oProxyCommand },
235 { "port", oPort },
236 { "ciphers", oCiphers },
237 { "macs", oMacs },
238 { "remoteforward", oRemoteForward },
239 { "localforward", oLocalForward },
240 { "permitremoteopen", oPermitRemoteOpen },
241 { "user", oUser },
242 { "host", oHost },
243 { "match", oMatch },
244 { "tag", oTag },
245 { "escapechar", oEscapeChar },
246 { "globalknownhostsfile", oGlobalKnownHostsFile },
247 { "userknownhostsfile", oUserKnownHostsFile },
248 { "connectionattempts", oConnectionAttempts },
249 { "batchmode", oBatchMode },
250 { "checkhostip", oCheckHostIP },
251 { "stricthostkeychecking", oStrictHostKeyChecking },
252 { "compression", oCompression },
253 { "tcpkeepalive", oTCPKeepAlive },
254 { "keepalive", oTCPKeepAlive }, /* obsolete */
255 { "numberofpasswordprompts", oNumberOfPasswordPrompts },
256 { "syslogfacility", oLogFacility },
257 { "loglevel", oLogLevel },
258 { "logverbose", oLogVerbose },
259 { "dynamicforward", oDynamicForward },
260 { "preferredauthentications", oPreferredAuthentications },
261 { "hostkeyalgorithms", oHostKeyAlgorithms },
262 { "casignaturealgorithms", oCASignatureAlgorithms },
263 { "bindaddress", oBindAddress },
264 { "bindinterface", oBindInterface },
265 { "clearallforwardings", oClearAllForwardings },
266 { "enablesshkeysign", oEnableSSHKeysign },
267 { "verifyhostkeydns", oVerifyHostKeyDNS },
268 { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
269 { "rekeylimit", oRekeyLimit },
270 { "connecttimeout", oConnectTimeout },
271 { "addressfamily", oAddressFamily },
272 { "serveraliveinterval", oServerAliveInterval },
273 { "serveralivecountmax", oServerAliveCountMax },
274 { "sendenv", oSendEnv },
275 { "setenv", oSetEnv },
276 { "controlpath", oControlPath },
277 { "controlmaster", oControlMaster },
278 { "controlpersist", oControlPersist },
279 { "hashknownhosts", oHashKnownHosts },
280 { "include", oInclude },
281 { "tunnel", oTunnel },
282 { "tunneldevice", oTunnelDevice },
283 { "localcommand", oLocalCommand },
284 { "permitlocalcommand", oPermitLocalCommand },
285 { "remotecommand", oRemoteCommand },
286 { "visualhostkey", oVisualHostKey },
287 { "kexalgorithms", oKexAlgorithms },
288 { "ipqos", oIPQoS },
289 { "requesttty", oRequestTTY },
290 { "sessiontype", oSessionType },
291 { "stdinnull", oStdinNull },
292 { "forkafterauthentication", oForkAfterAuthentication },
293 { "proxyusefdpass", oProxyUseFdpass },
294 { "canonicaldomains", oCanonicalDomains },
295 { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
296 { "canonicalizehostname", oCanonicalizeHostname },
297 { "canonicalizemaxdots", oCanonicalizeMaxDots },
298 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
299 { "streamlocalbindmask", oStreamLocalBindMask },
300 { "streamlocalbindunlink", oStreamLocalBindUnlink },
301 { "revokedhostkeys", oRevokedHostKeys },
302 { "fingerprinthash", oFingerprintHash },
303 { "updatehostkeys", oUpdateHostkeys },
304 { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
305 { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
306 { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
307 { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
308 { "ignoreunknown", oIgnoreUnknown },
309 { "proxyjump", oProxyJump },
310 { "securitykeyprovider", oSecurityKeyProvider },
311 { "knownhostscommand", oKnownHostsCommand },
312 { "requiredrsasize", oRequiredRSASize },
313 { "enableescapecommandline", oEnableEscapeCommandline },
314 { "obscurekeystroketiming", oObscureKeystrokeTiming },
315 { "channeltimeout", oChannelTimeout },
316
317 { NULL((void *)0), oBadOption }
318};
319
320static const char *lookup_opcode_name(OpCodes code);
321
322const char *
323kex_default_pk_alg(void)
324{
325 static char *pkalgs;
326
327 if (pkalgs == NULL((void *)0)) {
328 char *all_key;
329
330 all_key = sshkey_alg_list(0, 0, 1, ',');
331 pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG"ssh-ed25519-cert-v01@openssh.com," "ecdsa-sha2-nistp256-cert-v01@openssh.com,"
"ecdsa-sha2-nistp384-cert-v01@openssh.com," "ecdsa-sha2-nistp521-cert-v01@openssh.com,"
"sk-ssh-ed25519-cert-v01@openssh.com," "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,"
"rsa-sha2-512-cert-v01@openssh.com," "rsa-sha2-256-cert-v01@openssh.com,"
"ssh-ed25519," "ecdsa-sha2-nistp256," "ecdsa-sha2-nistp384,"
"ecdsa-sha2-nistp521," "sk-ssh-ed25519@openssh.com," "sk-ecdsa-sha2-nistp256@openssh.com,"
"rsa-sha2-512," "rsa-sha2-256"
, all_key);
332 free(all_key);
333 }
334 return pkalgs;
335}
336
337char *
338ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
339 const char *user, const char *jumphost)
340{
341 struct ssh_digest_ctx *md;
342 u_char conn_hash[SSH_DIGEST_MAX_LENGTH64];
343
344 if ((md = ssh_digest_start(SSH_DIGEST_SHA11)) == NULL((void *)0) ||
345 ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
346 ssh_digest_update(md, host, strlen(host)) < 0 ||
347 ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
348 ssh_digest_update(md, user, strlen(user)) < 0 ||
349 ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 ||
350 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
351 fatal_f("mux digest failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 351
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "mux digest failed")
;
352 ssh_digest_free(md);
353 return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA11));
354}
355
356/*
357 * Adds a local TCP/IP port forward to options. Never returns if there is an
358 * error.
359 */
360
361void
362add_local_forward(Options *options, const struct Forward *newfwd)
363{
364 struct Forward *fwd;
365 int i;
366
367 /* Don't add duplicates */
368 for (i = 0; i < options->num_local_forwards; i++) {
369 if (forward_equals(newfwd, options->local_forwards + i))
370 return;
371 }
372 options->local_forwards = xreallocarray(options->local_forwards,
373 options->num_local_forwards + 1,
374 sizeof(*options->local_forwards));
375 fwd = &options->local_forwards[options->num_local_forwards++];
376
377 fwd->listen_host = newfwd->listen_host;
378 fwd->listen_port = newfwd->listen_port;
379 fwd->listen_path = newfwd->listen_path;
380 fwd->connect_host = newfwd->connect_host;
381 fwd->connect_port = newfwd->connect_port;
382 fwd->connect_path = newfwd->connect_path;
383}
384
385/*
386 * Adds a remote TCP/IP port forward to options. Never returns if there is
387 * an error.
388 */
389
390void
391add_remote_forward(Options *options, const struct Forward *newfwd)
392{
393 struct Forward *fwd;
394 int i;
395
396 /* Don't add duplicates */
397 for (i = 0; i < options->num_remote_forwards; i++) {
398 if (forward_equals(newfwd, options->remote_forwards + i))
399 return;
400 }
401 options->remote_forwards = xreallocarray(options->remote_forwards,
402 options->num_remote_forwards + 1,
403 sizeof(*options->remote_forwards));
404 fwd = &options->remote_forwards[options->num_remote_forwards++];
405
406 fwd->listen_host = newfwd->listen_host;
407 fwd->listen_port = newfwd->listen_port;
408 fwd->listen_path = newfwd->listen_path;
409 fwd->connect_host = newfwd->connect_host;
410 fwd->connect_port = newfwd->connect_port;
411 fwd->connect_path = newfwd->connect_path;
412 fwd->handle = newfwd->handle;
413 fwd->allocated_port = 0;
414}
415
416static void
417clear_forwardings(Options *options)
418{
419 int i;
420
421 for (i = 0; i < options->num_local_forwards; i++) {
422 free(options->local_forwards[i].listen_host);
423 free(options->local_forwards[i].listen_path);
424 free(options->local_forwards[i].connect_host);
425 free(options->local_forwards[i].connect_path);
426 }
427 if (options->num_local_forwards > 0) {
428 free(options->local_forwards);
429 options->local_forwards = NULL((void *)0);
430 }
431 options->num_local_forwards = 0;
432 for (i = 0; i < options->num_remote_forwards; i++) {
433 free(options->remote_forwards[i].listen_host);
434 free(options->remote_forwards[i].listen_path);
435 free(options->remote_forwards[i].connect_host);
436 free(options->remote_forwards[i].connect_path);
437 }
438 if (options->num_remote_forwards > 0) {
439 free(options->remote_forwards);
440 options->remote_forwards = NULL((void *)0);
441 }
442 options->num_remote_forwards = 0;
443 options->tun_open = SSH_TUNMODE_NO0x00;
444}
445
446void
447add_certificate_file(Options *options, const char *path, int userprovided)
448{
449 int i;
450
451 if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES100)
452 fatal("Too many certificate files specified (max %d)",sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 453
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Too many certificate files specified (max %d)"
, 100)
453 SSH_MAX_CERTIFICATE_FILES)sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 453
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Too many certificate files specified (max %d)"
, 100)
;
454
455 /* Avoid registering duplicates */
456 for (i = 0; i < options->num_certificate_files; i++) {
457 if (options->certificate_file_userprovided[i] == userprovided &&
458 strcmp(options->certificate_files[i], path) == 0) {
459 debug2_f("ignoring duplicate key %s", path)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 459
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "ignoring duplicate key %s"
, path)
;
460 return;
461 }
462 }
463
464 options->certificate_file_userprovided[options->num_certificate_files] =
465 userprovided;
466 options->certificate_files[options->num_certificate_files++] =
467 xstrdup(path);
468}
469
470void
471add_identity_file(Options *options, const char *dir, const char *filename,
472 int userprovided)
473{
474 char *path;
475 int i;
476
477 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES100)
478 fatal("Too many identity files specified (max %d)",sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 479
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Too many identity files specified (max %d)"
, 100)
479 SSH_MAX_IDENTITY_FILES)sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 479
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Too many identity files specified (max %d)"
, 100)
;
480
481 if (dir == NULL((void *)0)) /* no dir, filename is absolute */
482 path = xstrdup(filename);
483 else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX1024)
484 fatal("Identity file path %s too long", path)sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 484
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Identity file path %s too long"
, path)
;
485
486 /* Avoid registering duplicates */
487 for (i = 0; i < options->num_identity_files; i++) {
488 if (options->identity_file_userprovided[i] == userprovided &&
489 strcmp(options->identity_files[i], path) == 0) {
490 debug2_f("ignoring duplicate key %s", path)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 490
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "ignoring duplicate key %s"
, path)
;
491 free(path);
492 return;
493 }
494 }
495
496 options->identity_file_userprovided[options->num_identity_files] =
497 userprovided;
498 options->identity_files[options->num_identity_files++] = path;
499}
500
501int
502default_ssh_port(void)
503{
504 static int port;
505 struct servent *sp;
506
507 if (port == 0) {
508 sp = getservbyname(SSH_SERVICE_NAME"ssh", "tcp");
509 port = sp ? ntohs(sp->s_port)(__uint16_t)(__builtin_constant_p(sp->s_port) ? (__uint16_t
)(((__uint16_t)(sp->s_port) & 0xffU) << 8 | ((__uint16_t
)(sp->s_port) & 0xff00U) >> 8) : __swap16md(sp->
s_port))
: SSH_DEFAULT_PORT22;
510 }
511 return port;
512}
513
514/*
515 * Execute a command in a shell.
516 * Return its exit status or -1 on abnormal exit.
517 */
518static int
519execute_in_shell(const char *cmd)
520{
521 char *shell;
522 pid_t pid;
523 int status;
524
525 if ((shell = getenv("SHELL")) == NULL((void *)0))
526 shell = _PATH_BSHELL"/bin/sh";
527
528 if (access(shell, X_OK0x01) == -1) {
529 fatal("Shell \"%s\" is not executable: %s",sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 530
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Shell \"%s\" is not executable: %s"
, shell, strerror((*__errno())))
530 shell, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 530
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Shell \"%s\" is not executable: %s"
, shell, strerror((*__errno())))
;
531 }
532
533 debug("Executing command: '%.500s'", cmd)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 533
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Executing command: '%.500s'"
, cmd)
;
534
535 /* Fork and execute the command. */
536 if ((pid = fork()) == 0) {
537 char *argv[4];
538
539 if (stdfd_devnull(1, 1, 0) == -1)
540 fatal_f("stdfd_devnull failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 540
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "stdfd_devnull failed")
;
541 closefrom(STDERR_FILENO2 + 1);
542
543 argv[0] = shell;
544 argv[1] = "-c";
545 argv[2] = xstrdup(cmd);
546 argv[3] = NULL((void *)0);
547
548 execv(argv[0], argv);
549 error("Unable to execute '%.100s': %s", cmd, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 549
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unable to execute '%.100s': %s"
, cmd, strerror((*__errno())))
;
550 /* Die with signal to make this error apparent to parent. */
551 ssh_signal(SIGTERM15, SIG_DFL(void (*)(int))0);
552 kill(getpid(), SIGTERM15);
553 _exit(1);
554 }
555 /* Parent. */
556 if (pid == -1)
557 fatal_f("fork: %.100s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 557
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "fork: %.100s", strerror
((*__errno())))
;
558
559 while (waitpid(pid, &status, 0) == -1) {
560 if (errno(*__errno()) != EINTR4 && errno(*__errno()) != EAGAIN35)
561 fatal_f("waitpid: %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 561
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "waitpid: %s", strerror
((*__errno())))
;
562 }
563 if (!WIFEXITED(status)(((status) & 0177) == 0)) {
564 error("command '%.100s' exited abnormally", cmd)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 564
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "command '%.100s' exited abnormally"
, cmd)
;
565 return -1;
566 }
567 debug3("command returned status %d", WEXITSTATUS(status))sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 567
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "command returned status %d"
, (int)(((unsigned)(status) >> 8) & 0xff))
;
568 return WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff);
569}
570
571/*
572 * Check whether a local network interface address appears in CIDR pattern-
573 * list 'addrlist'. Returns 1 if matched or 0 otherwise.
574 */
575static int
576check_match_ifaddrs(const char *addrlist)
577{
578 struct ifaddrs *ifa, *ifaddrs = NULL((void *)0);
579 int r, found = 0;
580 char addr[NI_MAXHOST256];
581 socklen_t salen;
582
583 if (getifaddrs(&ifaddrs) != 0) {
584 error("match localnetwork: getifaddrs failed: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 585
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "match localnetwork: getifaddrs failed: %s"
, strerror((*__errno())))
585 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 585
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "match localnetwork: getifaddrs failed: %s"
, strerror((*__errno())))
;
586 return 0;
587 }
588 for (ifa = ifaddrs; ifa != NULL((void *)0); ifa = ifa->ifa_next) {
589 if (ifa->ifa_addr == NULL((void *)0) || ifa->ifa_name == NULL((void *)0) ||
590 (ifa->ifa_flags & IFF_UP0x1) == 0)
591 continue;
592 switch (ifa->ifa_addr->sa_family) {
593 case AF_INET2:
594 salen = sizeof(struct sockaddr_in);
595 break;
596 case AF_INET624:
597 salen = sizeof(struct sockaddr_in6);
598 break;
599 case AF_LINK18:
600 /* ignore */
601 continue;
602 default:
603 debug2_f("interface %s: unsupported address family %d",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 604
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "interface %s: unsupported address family %d"
, ifa->ifa_name, ifa->ifa_addr->sa_family)
604 ifa->ifa_name, ifa->ifa_addr->sa_family)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 604
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "interface %s: unsupported address family %d"
, ifa->ifa_name, ifa->ifa_addr->sa_family)
;
605 continue;
606 }
607 if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr),
608 NULL((void *)0), 0, NI_NUMERICHOST1)) != 0) {
609 debug2_f("interface %s getnameinfo failed: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 610
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "interface %s getnameinfo failed: %s"
, ifa->ifa_name, gai_strerror(r))
610 ifa->ifa_name, gai_strerror(r))sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 610
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "interface %s getnameinfo failed: %s"
, ifa->ifa_name, gai_strerror(r))
;
611 continue;
612 }
613 debug3_f("interface %s addr %s", ifa->ifa_name, addr)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 613
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "interface %s addr %s"
, ifa->ifa_name, addr)
;
614 if (addr_match_cidr_list(addr, addrlist) == 1) {
615 debug3_f("matched interface %s: address %s in %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 616
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "matched interface %s: address %s in %s"
, ifa->ifa_name, addr, addrlist)
616 ifa->ifa_name, addr, addrlist)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 616
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "matched interface %s: address %s in %s"
, ifa->ifa_name, addr, addrlist)
;
617 found = 1;
618 break;
619 }
620 }
621 freeifaddrs(ifaddrs);
622 return found;
623}
624
625/*
626 * Parse and execute a Match directive.
627 */
628static int
629match_cfg_line(Options *options, char **condition, struct passwd *pw,
630 const char *host_arg, const char *original_host, int final_pass,
631 int *want_final_pass, const char *filename, int linenum)
632{
633 char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
634 const char *ruser;
635 int r, port, this_result, result = 1, attributes = 0, negate;
636 char thishost[NI_MAXHOST256], shorthost[NI_MAXHOST256], portstr[NI_MAXSERV32];
637 char uidstr[32];
638
639 /*
640 * Configuration is likely to be incomplete at this point so we
641 * must be prepared to use default values.
642 */
643 port = options->port <= 0 ? default_ssh_port() : options->port;
644 ruser = options->user == NULL((void *)0) ? pw->pw_name : options->user;
645 if (final_pass) {
646 host = xstrdup(options->hostname);
647 } else if (options->hostname != NULL((void *)0)) {
648 /* NB. Please keep in sync with ssh.c:main() */
649 host = percent_expand(options->hostname,
650 "h", host_arg, (char *)NULL((void *)0));
651 } else {
652 host = xstrdup(host_arg);
653 }
654
655 debug2("checking match for '%s' host %s originally %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 656
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "checking match for '%s' host %s originally %s"
, cp, host, original_host)
656 cp, host, original_host)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 656
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "checking match for '%s' host %s originally %s"
, cp, host, original_host)
;
657 while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
658 /* Terminate on comment */
659 if (*attrib == '#') {
660 cp = NULL((void *)0); /* mark all arguments consumed */
661 break;
662 }
663 arg = criteria = NULL((void *)0);
664 this_result = 1;
665 if ((negate = (attrib[0] == '!')))
666 attrib++;
667 /* Criterion "all" has no argument and must appear alone */
668 if (strcasecmp(attrib, "all") == 0) {
669 if (attributes > 1 || ((arg = strdelim(&cp)) != NULL((void *)0) &&
670 *arg != '\0' && *arg != '#')) {
671 error("%.200s line %d: '%s' cannot be combined "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 673
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: '%s' cannot be combined "
"with other Match attributes", filename, linenum, oattrib)
672 "with other Match attributes",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 673
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: '%s' cannot be combined "
"with other Match attributes", filename, linenum, oattrib)
673 filename, linenum, oattrib)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 673
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: '%s' cannot be combined "
"with other Match attributes", filename, linenum, oattrib)
;
674 result = -1;
675 goto out;
676 }
677 if (arg != NULL((void *)0) && *arg == '#')
678 cp = NULL((void *)0); /* mark all arguments consumed */
679 if (result)
680 result = negate ? 0 : 1;
681 goto out;
682 }
683 attributes++;
684 /* criteria "final" and "canonical" have no argument */
685 if (strcasecmp(attrib, "canonical") == 0 ||
686 strcasecmp(attrib, "final") == 0) {
687 /*
688 * If the config requests "Match final" then remember
689 * this so we can perform a second pass later.
690 */
691 if (strcasecmp(attrib, "final") == 0 &&
692 want_final_pass != NULL((void *)0))
693 *want_final_pass = 1;
694 r = !!final_pass; /* force bitmask member to boolean */
695 if (r == (negate ? 1 : 0))
696 this_result = result = 0;
697 debug3("%.200s line %d: %smatched '%s'",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 699
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s'"
, filename, linenum, this_result ? "" : "not ", oattrib)
698 filename, linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 699
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s'"
, filename, linenum, this_result ? "" : "not ", oattrib)
699 this_result ? "" : "not ", oattrib)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 699
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s'"
, filename, linenum, this_result ? "" : "not ", oattrib)
;
700 continue;
701 }
702 /* All other criteria require an argument */
703 if ((arg = strdelim(&cp)) == NULL((void *)0) ||
704 *arg == '\0' || *arg == '#') {
705 error("Missing Match criteria for %s", attrib)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 705
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Missing Match criteria for %s"
, attrib)
;
706 result = -1;
707 goto out;
708 }
709 if (strcasecmp(attrib, "host") == 0) {
710 criteria = xstrdup(host);
711 r = match_hostname(host, arg) == 1;
712 if (r == (negate ? 1 : 0))
713 this_result = result = 0;
714 } else if (strcasecmp(attrib, "originalhost") == 0) {
715 criteria = xstrdup(original_host);
716 r = match_hostname(original_host, arg) == 1;
717 if (r == (negate ? 1 : 0))
718 this_result = result = 0;
719 } else if (strcasecmp(attrib, "user") == 0) {
720 criteria = xstrdup(ruser);
721 r = match_pattern_list(ruser, arg, 0) == 1;
722 if (r == (negate ? 1 : 0))
723 this_result = result = 0;
724 } else if (strcasecmp(attrib, "localuser") == 0) {
725 criteria = xstrdup(pw->pw_name);
726 r = match_pattern_list(pw->pw_name, arg, 0) == 1;
727 if (r == (negate ? 1 : 0))
728 this_result = result = 0;
729 } else if (strcasecmp(attrib, "localnetwork") == 0) {
730 if (addr_match_cidr_list(NULL((void *)0), arg) == -1) {
731 /* Error already printed */
732 result = -1;
733 goto out;
734 }
735 r = check_match_ifaddrs(arg) == 1;
736 if (r == (negate ? 1 : 0))
737 this_result = result = 0;
738 } else if (strcasecmp(attrib, "tagged") == 0) {
739 criteria = xstrdup(options->tag == NULL((void *)0) ? "" :
740 options->tag);
741 r = match_pattern_list(criteria, arg, 0) == 1;
742 if (r == (negate ? 1 : 0))
743 this_result = result = 0;
744 } else if (strcasecmp(attrib, "exec") == 0) {
745 char *conn_hash_hex, *keyalias, *jmphost;
746
747 if (gethostname(thishost, sizeof(thishost)) == -1)
748 fatal("gethostname: %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 748
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "gethostname: %s", strerror
((*__errno())))
;
749 jmphost = option_clear_or_none(options->jump_host) ?
750 "" : options->jump_host;
751 strlcpy(shorthost, thishost, sizeof(shorthost));
752 shorthost[strcspn(thishost, ".")] = '\0';
753 snprintf(portstr, sizeof(portstr), "%d", port);
754 snprintf(uidstr, sizeof(uidstr), "%llu",
755 (unsigned long long)pw->pw_uid);
756 conn_hash_hex = ssh_connection_hash(thishost, host,
757 portstr, ruser, jmphost);
758 keyalias = options->host_key_alias ?
759 options->host_key_alias : host;
760
761 cmd = percent_expand(arg,
762 "C", conn_hash_hex,
763 "L", shorthost,
764 "d", pw->pw_dir,
765 "h", host,
766 "k", keyalias,
767 "l", thishost,
768 "n", original_host,
769 "p", portstr,
770 "r", ruser,
771 "u", pw->pw_name,
772 "i", uidstr,
773 "j", jmphost,
774 (char *)NULL((void *)0));
775 free(conn_hash_hex);
776 if (result != 1) {
777 /* skip execution if prior predicate failed */
778 debug3("%.200s line %d: skipped exec "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 779
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: skipped exec "
"\"%.100s\"", filename, linenum, cmd)
779 "\"%.100s\"", filename, linenum, cmd)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 779
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: skipped exec "
"\"%.100s\"", filename, linenum, cmd)
;
780 free(cmd);
781 continue;
782 }
783 r = execute_in_shell(cmd);
784 if (r == -1) {
785 fatal("%.200s line %d: match exec "sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 787
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%.200s line %d: match exec "
"'%.100s' error", filename, linenum, cmd)
786 "'%.100s' error", filename,sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 787
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%.200s line %d: match exec "
"'%.100s' error", filename, linenum, cmd)
787 linenum, cmd)sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 787
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%.200s line %d: match exec "
"'%.100s' error", filename, linenum, cmd)
;
788 }
789 criteria = xstrdup(cmd);
790 free(cmd);
791 /* Force exit status to boolean */
792 r = r == 0;
793 if (r == (negate ? 1 : 0))
794 this_result = result = 0;
795 } else {
796 error("Unsupported Match attribute %s", attrib)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 796
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Unsupported Match attribute %s"
, attrib)
;
797 result = -1;
798 goto out;
799 }
800 debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 804
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s%s%.100s%s' "
, filename, linenum, this_result ? "": "not ", oattrib, criteria
== ((void *)0) ? "" : " \"", criteria == ((void *)0) ? "" : criteria
, criteria == ((void *)0) ? "" : "\"")
801 filename, linenum, this_result ? "": "not ", oattrib,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 804
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s%s%.100s%s' "
, filename, linenum, this_result ? "": "not ", oattrib, criteria
== ((void *)0) ? "" : " \"", criteria == ((void *)0) ? "" : criteria
, criteria == ((void *)0) ? "" : "\"")
802 criteria == NULL ? "" : " \"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 804
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s%s%.100s%s' "
, filename, linenum, this_result ? "": "not ", oattrib, criteria
== ((void *)0) ? "" : " \"", criteria == ((void *)0) ? "" : criteria
, criteria == ((void *)0) ? "" : "\"")
803 criteria == NULL ? "" : criteria,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 804
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s%s%.100s%s' "
, filename, linenum, this_result ? "": "not ", oattrib, criteria
== ((void *)0) ? "" : " \"", criteria == ((void *)0) ? "" : criteria
, criteria == ((void *)0) ? "" : "\"")
804 criteria == NULL ? "" : "\"")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 804
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: %smatched '%s%s%.100s%s' "
, filename, linenum, this_result ? "": "not ", oattrib, criteria
== ((void *)0) ? "" : " \"", criteria == ((void *)0) ? "" : criteria
, criteria == ((void *)0) ? "" : "\"")
;
805 free(criteria);
806 }
807 if (attributes == 0) {
808 error("One or more attributes required for Match")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 808
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "One or more attributes required for Match"
)
;
809 result = -1;
810 goto out;
811 }
812 out:
813 if (result != -1)
814 debug2("match %sfound", result ? "" : "not ")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 814
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "match %sfound", result
? "" : "not ")
;
815 *condition = cp;
816 free(host);
817 return result;
818}
819
820/* Remove environment variable by pattern */
821static void
822rm_env(Options *options, const char *arg, const char *filename, int linenum)
823{
824 u_int i, j, onum_send_env = options->num_send_env;
825
826 /* Remove an environment variable */
827 for (i = 0; i < options->num_send_env; ) {
828 if (!match_pattern(options->send_env[i], arg + 1)) {
829 i++;
830 continue;
831 }
832 debug3("%s line %d: removing environment %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 833
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%s line %d: removing environment %s"
, filename, linenum, options->send_env[i])
833 filename, linenum, options->send_env[i])sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 833
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%s line %d: removing environment %s"
, filename, linenum, options->send_env[i])
;
834 free(options->send_env[i]);
835 options->send_env[i] = NULL((void *)0);
836 for (j = i; j < options->num_send_env - 1; j++) {
837 options->send_env[j] = options->send_env[j + 1];
838 options->send_env[j + 1] = NULL((void *)0);
839 }
840 options->num_send_env--;
841 /* NB. don't increment i */
842 }
843 if (onum_send_env != options->num_send_env) {
844 options->send_env = xrecallocarray(options->send_env,
845 onum_send_env, options->num_send_env,
846 sizeof(*options->send_env));
847 }
848}
849
850/*
851 * Returns the number of the token pointed to by cp or oBadOption.
852 */
853static OpCodes
854parse_token(const char *cp, const char *filename, int linenum,
855 const char *ignored_unknown)
856{
857 int i;
858
859 for (i = 0; keywords[i].name; i++)
860 if (strcmp(cp, keywords[i].name) == 0)
861 return keywords[i].opcode;
862 if (ignored_unknown != NULL((void *)0) &&
863 match_pattern_list(cp, ignored_unknown, 1) == 1)
864 return oIgnoredUnknownOption;
865 error("%s: line %d: Bad configuration option: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 866
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s: line %d: Bad configuration option: %s"
, filename, linenum, cp)
866 filename, linenum, cp)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 866
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s: line %d: Bad configuration option: %s"
, filename, linenum, cp)
;
867 return oBadOption;
868}
869
870/* Multistate option parsing */
871struct multistate {
872 char *key;
873 int value;
874};
875static const struct multistate multistate_flag[] = {
876 { "true", 1 },
877 { "false", 0 },
878 { "yes", 1 },
879 { "no", 0 },
880 { NULL((void *)0), -1 }
881};
882static const struct multistate multistate_yesnoask[] = {
883 { "true", 1 },
884 { "false", 0 },
885 { "yes", 1 },
886 { "no", 0 },
887 { "ask", 2 },
888 { NULL((void *)0), -1 }
889};
890static const struct multistate multistate_strict_hostkey[] = {
891 { "true", SSH_STRICT_HOSTKEY_YES2 },
892 { "false", SSH_STRICT_HOSTKEY_OFF0 },
893 { "yes", SSH_STRICT_HOSTKEY_YES2 },
894 { "no", SSH_STRICT_HOSTKEY_OFF0 },
895 { "ask", SSH_STRICT_HOSTKEY_ASK3 },
896 { "off", SSH_STRICT_HOSTKEY_OFF0 },
897 { "accept-new", SSH_STRICT_HOSTKEY_NEW1 },
898 { NULL((void *)0), -1 }
899};
900static const struct multistate multistate_yesnoaskconfirm[] = {
901 { "true", 1 },
902 { "false", 0 },
903 { "yes", 1 },
904 { "no", 0 },
905 { "ask", 2 },
906 { "confirm", 3 },
907 { NULL((void *)0), -1 }
908};
909static const struct multistate multistate_addressfamily[] = {
910 { "inet", AF_INET2 },
911 { "inet6", AF_INET624 },
912 { "any", AF_UNSPEC0 },
913 { NULL((void *)0), -1 }
914};
915static const struct multistate multistate_controlmaster[] = {
916 { "true", SSHCTL_MASTER_YES1 },
917 { "yes", SSHCTL_MASTER_YES1 },
918 { "false", SSHCTL_MASTER_NO0 },
919 { "no", SSHCTL_MASTER_NO0 },
920 { "auto", SSHCTL_MASTER_AUTO2 },
921 { "ask", SSHCTL_MASTER_ASK3 },
922 { "autoask", SSHCTL_MASTER_AUTO_ASK4 },
923 { NULL((void *)0), -1 }
924};
925static const struct multistate multistate_tunnel[] = {
926 { "ethernet", SSH_TUNMODE_ETHERNET0x02 },
927 { "point-to-point", SSH_TUNMODE_POINTOPOINT0x01 },
928 { "true", SSH_TUNMODE_DEFAULT0x01 },
929 { "yes", SSH_TUNMODE_DEFAULT0x01 },
930 { "false", SSH_TUNMODE_NO0x00 },
931 { "no", SSH_TUNMODE_NO0x00 },
932 { NULL((void *)0), -1 }
933};
934static const struct multistate multistate_requesttty[] = {
935 { "true", REQUEST_TTY_YES2 },
936 { "yes", REQUEST_TTY_YES2 },
937 { "false", REQUEST_TTY_NO1 },
938 { "no", REQUEST_TTY_NO1 },
939 { "force", REQUEST_TTY_FORCE3 },
940 { "auto", REQUEST_TTY_AUTO0 },
941 { NULL((void *)0), -1 }
942};
943static const struct multistate multistate_sessiontype[] = {
944 { "none", SESSION_TYPE_NONE0 },
945 { "subsystem", SESSION_TYPE_SUBSYSTEM1 },
946 { "default", SESSION_TYPE_DEFAULT2 },
947 { NULL((void *)0), -1 }
948};
949static const struct multistate multistate_canonicalizehostname[] = {
950 { "true", SSH_CANONICALISE_YES1 },
951 { "false", SSH_CANONICALISE_NO0 },
952 { "yes", SSH_CANONICALISE_YES1 },
953 { "no", SSH_CANONICALISE_NO0 },
954 { "always", SSH_CANONICALISE_ALWAYS2 },
955 { NULL((void *)0), -1 }
956};
957static const struct multistate multistate_pubkey_auth[] = {
958 { "true", SSH_PUBKEY_AUTH_ALL0x03 },
959 { "false", SSH_PUBKEY_AUTH_NO0x00 },
960 { "yes", SSH_PUBKEY_AUTH_ALL0x03 },
961 { "no", SSH_PUBKEY_AUTH_NO0x00 },
962 { "unbound", SSH_PUBKEY_AUTH_UNBOUND0x01 },
963 { "host-bound", SSH_PUBKEY_AUTH_HBOUND0x02 },
964 { NULL((void *)0), -1 }
965};
966static const struct multistate multistate_compression[] = {
967#ifdef WITH_ZLIB1
968 { "yes", COMP_ZLIB1 },
969#endif
970 { "no", COMP_NONE0 },
971 { NULL((void *)0), -1 }
972};
973
974static int
975parse_multistate_value(const char *arg, const char *filename, int linenum,
976 const struct multistate *multistate_ptr)
977{
978 int i;
979
980 if (!arg || *arg == '\0') {
981 error("%s line %d: missing argument.", filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 981
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: missing argument."
, filename, linenum)
;
982 return -1;
983 }
984 for (i = 0; multistate_ptr[i].key != NULL((void *)0); i++) {
985 if (strcasecmp(arg, multistate_ptr[i].key) == 0)
986 return multistate_ptr[i].value;
987 }
988 return -1;
989}
990
991/*
992 * Processes a single option line as used in the configuration files. This
993 * only sets those values that have not already been set.
994 */
995int
996process_config_line(Options *options, struct passwd *pw, const char *host,
997 const char *original_host, char *line, const char *filename,
998 int linenum, int *activep, int flags)
999{
1000 return process_config_line_depth(options, pw, host, original_host,
1001 line, filename, linenum, activep, flags, NULL((void *)0), 0);
1002}
1003
1004#define WHITESPACE" \t\r\n" " \t\r\n"
1005static int
1006process_config_line_depth(Options *options, struct passwd *pw, const char *host,
1007 const char *original_host, char *line, const char *filename,
1008 int linenum, int *activep, int flags, int *want_final_pass, int depth)
1009{
1010 char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
1011 char **cpptr, ***cppptr, fwdarg[256];
1012 u_int i, *uintptr, uvalue, max_entries = 0;
1013 int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
1014 int remotefwd, dynamicfwd, ca_only = 0;
1015 LogLevel *log_level_ptr;
1016 SyslogFacility *log_facility_ptr;
1017 long long val64;
1018 size_t len;
1019 struct Forward fwd;
1020 const struct multistate *multistate_ptr;
1021 struct allowed_cname *cname;
1022 glob_t gl;
1023 const char *errstr;
1024 char **oav = NULL((void *)0), **av;
1025 int oac = 0, ac;
1026 int ret = -1;
1027
1028 if (activep == NULL((void *)0)) { /* We are processing a command line directive */
1029 cmdline = 1;
1030 activep = &cmdline;
1031 }
1032
1033 /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1034 if ((len = strlen(line)) == 0)
1035 return 0;
1036 for (len--; len > 0; len--) {
1037 if (strchr(WHITESPACE" \t\r\n" "\f", line[len]) == NULL((void *)0))
1038 break;
1039 line[len] = '\0';
1040 }
1041
1042 str = line;
1043 /* Get the keyword. (Each line is supposed to begin with a keyword). */
1044 if ((keyword = strdelim(&str)) == NULL((void *)0))
1045 return 0;
1046 /* Ignore leading whitespace. */
1047 if (*keyword == '\0')
1048 keyword = strdelim(&str);
1049 if (keyword == NULL((void *)0) || !*keyword || *keyword == '\n' || *keyword == '#')
1050 return 0;
1051 /* Match lowercase keyword */
1052 lowercase(keyword);
1053
1054 /* Prepare to parse remainder of line */
1055 if (str != NULL((void *)0))
1056 str += strspn(str, WHITESPACE" \t\r\n");
1057 if (str == NULL((void *)0) || *str == '\0') {
1058 error("%s line %d: no argument after keyword \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1059
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: no argument after keyword \"%s\""
, filename, linenum, keyword)
1059 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1059
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: no argument after keyword \"%s\""
, filename, linenum, keyword)
;
1060 return -1;
1061 }
1062 opcode = parse_token(keyword, filename, linenum,
1063 options->ignored_unknown);
1064 if (argv_split(str, &oac, &oav, 1) != 0) {
1065 error("%s line %d: invalid quotes", filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1065
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: invalid quotes"
, filename, linenum)
;
1066 return -1;
1067 }
1068 ac = oac;
1069 av = oav;
1070
1071 switch (opcode) {
1072 case oBadOption:
1073 /* don't panic, but count bad options */
1074 goto out;
1075 case oIgnore:
1076 argv_consume(&ac);
1077 break;
1078 case oIgnoredUnknownOption:
1079 debug("%s line %d: Ignored unknown option \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1080
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s line %d: Ignored unknown option \"%s\""
, filename, linenum, keyword)
1080 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1080
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s line %d: Ignored unknown option \"%s\""
, filename, linenum, keyword)
;
1081 argv_consume(&ac);
1082 break;
1083 case oConnectTimeout:
1084 intptr = &options->connection_timeout;
1085parse_time:
1086 arg = argv_next(&ac, &av);
1087 if (!arg || *arg == '\0') {
1088 error("%s line %d: missing time value.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1089
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: missing time value."
, filename, linenum)
1089 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1089
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: missing time value."
, filename, linenum)
;
1090 goto out;
1091 }
1092 if (strcmp(arg, "none") == 0)
1093 value = -1;
1094 else if ((value = convtime(arg)) == -1) {
1095 error("%s line %d: invalid time value.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1096
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: invalid time value."
, filename, linenum)
1096 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1096
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: invalid time value."
, filename, linenum)
;
1097 goto out;
1098 }
1099 if (*activep && *intptr == -1)
1100 *intptr = value;
1101 break;
1102
1103 case oForwardAgent:
1104 intptr = &options->forward_agent;
1105
1106 arg = argv_next(&ac, &av);
1107 if (!arg || *arg == '\0') {
1108 error("%s line %d: missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1109
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: missing argument."
, filename, linenum)
1109 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1109
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: missing argument."
, filename, linenum)
;
1110 goto out;
1111 }
1112
1113 value = -1;
1114 multistate_ptr = multistate_flag;
1115 for (i = 0; multistate_ptr[i].key != NULL((void *)0); i++) {
1116 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1117 value = multistate_ptr[i].value;
1118 break;
1119 }
1120 }
1121 if (value != -1) {
1122 if (*activep && *intptr == -1)
1123 *intptr = value;
1124 break;
1125 }
1126 /* ForwardAgent wasn't 'yes' or 'no', assume a path */
1127 if (*activep && *intptr == -1)
1128 *intptr = 1;
1129
1130 charptr = &options->forward_agent_sock_path;
1131 goto parse_agent_path;
1132
1133 case oForwardX11:
1134 intptr = &options->forward_x11;
1135 parse_flag:
1136 multistate_ptr = multistate_flag;
1137 parse_multistate:
1138 arg = argv_next(&ac, &av);
1139 if ((value = parse_multistate_value(arg, filename, linenum,
1140 multistate_ptr)) == -1) {
1141 error("%s line %d: unsupported option \"%s\".",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1142
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported option \"%s\"."
, filename, linenum, arg)
1142 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1142
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported option \"%s\"."
, filename, linenum, arg)
;
1143 goto out;
1144 }
1145 if (*activep && *intptr == -1)
1146 *intptr = value;
1147 break;
1148
1149 case oForwardX11Trusted:
1150 intptr = &options->forward_x11_trusted;
1151 goto parse_flag;
1152
1153 case oForwardX11Timeout:
1154 intptr = &options->forward_x11_timeout;
1155 goto parse_time;
1156
1157 case oGatewayPorts:
1158 intptr = &options->fwd_opts.gateway_ports;
1159 goto parse_flag;
1160
1161 case oExitOnForwardFailure:
1162 intptr = &options->exit_on_forward_failure;
1163 goto parse_flag;
1164
1165 case oPasswordAuthentication:
1166 intptr = &options->password_authentication;
1167 goto parse_flag;
1168
1169 case oKbdInteractiveAuthentication:
1170 intptr = &options->kbd_interactive_authentication;
1171 goto parse_flag;
1172
1173 case oKbdInteractiveDevices:
1174 charptr = &options->kbd_interactive_devices;
1175 goto parse_string;
1176
1177 case oPubkeyAuthentication:
1178 multistate_ptr = multistate_pubkey_auth;
1179 intptr = &options->pubkey_authentication;
1180 goto parse_multistate;
1181
1182 case oHostbasedAuthentication:
1183 intptr = &options->hostbased_authentication;
1184 goto parse_flag;
1185
1186 case oGssAuthentication:
1187 intptr = &options->gss_authentication;
1188 goto parse_flag;
1189
1190 case oGssDelegateCreds:
1191 intptr = &options->gss_deleg_creds;
1192 goto parse_flag;
1193
1194 case oBatchMode:
1195 intptr = &options->batch_mode;
1196 goto parse_flag;
1197
1198 case oCheckHostIP:
1199 intptr = &options->check_host_ip;
1200 goto parse_flag;
1201
1202 case oVerifyHostKeyDNS:
1203 intptr = &options->verify_host_key_dns;
1204 multistate_ptr = multistate_yesnoask;
1205 goto parse_multistate;
1206
1207 case oStrictHostKeyChecking:
1208 intptr = &options->strict_host_key_checking;
1209 multistate_ptr = multistate_strict_hostkey;
1210 goto parse_multistate;
1211
1212 case oCompression:
1213 intptr = &options->compression;
1214 multistate_ptr = multistate_compression;
1215 goto parse_multistate;
1216
1217 case oTCPKeepAlive:
1218 intptr = &options->tcp_keep_alive;
1219 goto parse_flag;
1220
1221 case oNoHostAuthenticationForLocalhost:
1222 intptr = &options->no_host_authentication_for_localhost;
1223 goto parse_flag;
1224
1225 case oNumberOfPasswordPrompts:
1226 intptr = &options->number_of_password_prompts;
1227 goto parse_int;
1228
1229 case oRekeyLimit:
1230 arg = argv_next(&ac, &av);
1231 if (!arg || *arg == '\0') {
1232 error("%.200s line %d: Missing argument.", filename,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1233
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1233 linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1233
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1234 goto out;
1235 }
1236 if (strcmp(arg, "default") == 0) {
1237 val64 = 0;
1238 } else {
1239 if (scan_scaled(arg, &val64) == -1) {
1240 error("%.200s line %d: Bad number '%s': %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1241
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad number '%s': %s"
, filename, linenum, arg, strerror((*__errno())))
1241 filename, linenum, arg, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1241
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad number '%s': %s"
, filename, linenum, arg, strerror((*__errno())))
;
1242 goto out;
1243 }
1244 if (val64 != 0 && val64 < 16) {
1245 error("%.200s line %d: RekeyLimit too small",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1246
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: RekeyLimit too small"
, filename, linenum)
1246 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1246
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: RekeyLimit too small"
, filename, linenum)
;
1247 goto out;
1248 }
1249 }
1250 if (*activep && options->rekey_limit == -1)
1251 options->rekey_limit = val64;
1252 if (ac != 0) { /* optional rekey interval present */
1253 if (strcmp(av[0], "none") == 0) {
1254 (void)argv_next(&ac, &av); /* discard */
1255 break;
1256 }
1257 intptr = &options->rekey_interval;
1258 goto parse_time;
1259 }
1260 break;
1261
1262 case oIdentityFile:
1263 arg = argv_next(&ac, &av);
1264 if (!arg || *arg == '\0') {
1265 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1266
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1266 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1266
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1267 goto out;
1268 }
1269 if (*activep) {
1270 intptr = &options->num_identity_files;
1271 if (*intptr >= SSH_MAX_IDENTITY_FILES100) {
1272 error("%.200s line %d: Too many identity files "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1274
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Too many identity files "
"specified (max %d).", filename, linenum, 100)
1273 "specified (max %d).", filename, linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1274
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Too many identity files "
"specified (max %d).", filename, linenum, 100)
1274 SSH_MAX_IDENTITY_FILES)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1274
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Too many identity files "
"specified (max %d).", filename, linenum, 100)
;
1275 goto out;
1276 }
1277 add_identity_file(options, NULL((void *)0),
1278 arg, flags & SSHCONF_USERCONF2);
1279 }
1280 break;
1281
1282 case oCertificateFile:
1283 arg = argv_next(&ac, &av);
1284 if (!arg || *arg == '\0') {
1285 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1286
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1286 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1286
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1287 goto out;
1288 }
1289 if (*activep) {
1290 intptr = &options->num_certificate_files;
1291 if (*intptr >= SSH_MAX_CERTIFICATE_FILES100) {
1292 error("%.200s line %d: Too many certificate "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1295
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Too many certificate "
"files specified (max %d).", filename, linenum, 100)
1293 "files specified (max %d).",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1295
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Too many certificate "
"files specified (max %d).", filename, linenum, 100)
1294 filename, linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1295
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Too many certificate "
"files specified (max %d).", filename, linenum, 100)
1295 SSH_MAX_CERTIFICATE_FILES)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1295
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Too many certificate "
"files specified (max %d).", filename, linenum, 100)
;
1296 goto out;
1297 }
1298 add_certificate_file(options, arg,
1299 flags & SSHCONF_USERCONF2);
1300 }
1301 break;
1302
1303 case oXAuthLocation:
1304 charptr=&options->xauth_location;
1305 goto parse_string;
1306
1307 case oUser:
1308 charptr = &options->user;
1309parse_string:
1310 arg = argv_next(&ac, &av);
1311 if (!arg || *arg == '\0') {
1312 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1313
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1313 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1313
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1314 goto out;
1315 }
1316 if (*activep && *charptr == NULL((void *)0))
1317 *charptr = xstrdup(arg);
1318 break;
1319
1320 case oGlobalKnownHostsFile:
1321 cpptr = (char **)&options->system_hostfiles;
1322 uintptr = &options->num_system_hostfiles;
1323 max_entries = SSH_MAX_HOSTS_FILES32;
1324parse_char_array:
1325 i = 0;
1326 value = *uintptr == 0; /* was array empty when we started? */
1327 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
1328 if (*arg == '\0') {
1329 error("%s line %d: keyword %s empty argument",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1330
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
1330 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1330
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
;
1331 goto out;
1332 }
1333 /* Allow "none" only in first position */
1334 if (strcasecmp(arg, "none") == 0) {
1335 if (i > 0 || ac > 0) {
1336 error("%s line %d: keyword %s \"none\" "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1338
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
1337 "argument must appear alone.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1338
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
1338 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1338
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
;
1339 goto out;
1340 }
1341 }
1342 i++;
1343 if (*activep && value) {
1344 if ((*uintptr) >= max_entries) {
1345 error("%s line %d: too many %s "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1347
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: too many %s "
"entries.", filename, linenum, keyword)
1346 "entries.", filename, linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1347
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: too many %s "
"entries.", filename, linenum, keyword)
1347 keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1347
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: too many %s "
"entries.", filename, linenum, keyword)
;
1348 goto out;
1349 }
1350 cpptr[(*uintptr)++] = xstrdup(arg);
1351 }
1352 }
1353 break;
1354
1355 case oUserKnownHostsFile:
1356 cpptr = (char **)&options->user_hostfiles;
1357 uintptr = &options->num_user_hostfiles;
1358 max_entries = SSH_MAX_HOSTS_FILES32;
1359 goto parse_char_array;
1360
1361 case oHostname:
1362 charptr = &options->hostname;
1363 goto parse_string;
1364
1365 case oTag:
1366 charptr = &options->tag;
1367 goto parse_string;
1368
1369 case oHostKeyAlias:
1370 charptr = &options->host_key_alias;
1371 goto parse_string;
1372
1373 case oPreferredAuthentications:
1374 charptr = &options->preferred_authentications;
1375 goto parse_string;
1376
1377 case oBindAddress:
1378 charptr = &options->bind_address;
1379 goto parse_string;
1380
1381 case oBindInterface:
1382 charptr = &options->bind_interface;
1383 goto parse_string;
1384
1385 case oPKCS11Provider:
1386 charptr = &options->pkcs11_provider;
1387 goto parse_string;
1388
1389 case oSecurityKeyProvider:
1390 charptr = &options->sk_provider;
1391 goto parse_string;
1392
1393 case oKnownHostsCommand:
1394 charptr = &options->known_hosts_command;
1395 goto parse_command;
1396
1397 case oProxyCommand:
1398 charptr = &options->proxy_command;
1399 /* Ignore ProxyCommand if ProxyJump already specified */
1400 if (options->jump_host != NULL((void *)0))
1401 charptr = &options->jump_host; /* Skip below */
1402parse_command:
1403 if (str == NULL((void *)0)) {
1404 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1405
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1405 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1405
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1406 goto out;
1407 }
1408 len = strspn(str, WHITESPACE" \t\r\n" "=");
1409 if (*activep && *charptr == NULL((void *)0))
1410 *charptr = xstrdup(str + len);
1411 argv_consume(&ac);
1412 break;
1413
1414 case oProxyJump:
1415 if (str == NULL((void *)0)) {
1416 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1417
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1417 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1417
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1418 goto out;
1419 }
1420 len = strspn(str, WHITESPACE" \t\r\n" "=");
1421 /* XXX use argv? */
1422 if (parse_jump(str + len, options, *activep) == -1) {
1423 error("%.200s line %d: Invalid ProxyJump \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1424
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid ProxyJump \"%s\""
, filename, linenum, str + len)
1424 filename, linenum, str + len)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1424
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid ProxyJump \"%s\""
, filename, linenum, str + len)
;
1425 goto out;
1426 }
1427 argv_consume(&ac);
1428 break;
1429
1430 case oPort:
1431 arg = argv_next(&ac, &av);
1432 if (!arg || *arg == '\0') {
1433 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1434
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1434 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1434
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1435 goto out;
1436 }
1437 value = a2port(arg);
1438 if (value <= 0) {
1439 error("%.200s line %d: Bad port '%s'.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1440
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad port '%s'."
, filename, linenum, arg)
1440 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1440
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad port '%s'."
, filename, linenum, arg)
;
1441 goto out;
1442 }
1443 if (*activep && options->port == -1)
1444 options->port = value;
1445 break;
1446
1447 case oConnectionAttempts:
1448 intptr = &options->connection_attempts;
1449parse_int:
1450 arg = argv_next(&ac, &av);
1451 if ((errstr = atoi_err(arg, &value)) != NULL((void *)0)) {
1452 error("%s line %d: integer value %s.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1453
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: integer value %s."
, filename, linenum, errstr)
1453 filename, linenum, errstr)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1453
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: integer value %s."
, filename, linenum, errstr)
;
1454 goto out;
1455 }
1456 if (*activep && *intptr == -1)
1457 *intptr = value;
1458 break;
1459
1460 case oCiphers:
1461 arg = argv_next(&ac, &av);
1462 if (!arg || *arg == '\0') {
1463 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1464
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1464 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1464
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1465 goto out;
1466 }
1467 if (*arg != '-' &&
1468 !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1469 error("%.200s line %d: Bad SSH2 cipher spec '%s'.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1470
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad SSH2 cipher spec '%s'."
, filename, linenum, arg ? arg : "<NONE>")
1470 filename, linenum, arg ? arg : "<NONE>")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1470
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad SSH2 cipher spec '%s'."
, filename, linenum, arg ? arg : "<NONE>")
;
1471 goto out;
1472 }
1473 if (*activep && options->ciphers == NULL((void *)0))
1474 options->ciphers = xstrdup(arg);
1475 break;
1476
1477 case oMacs:
1478 arg = argv_next(&ac, &av);
1479 if (!arg || *arg == '\0') {
1480 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1481
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1481 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1481
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1482 goto out;
1483 }
1484 if (*arg != '-' &&
1485 !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1486 error("%.200s line %d: Bad SSH2 MAC spec '%s'.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1487
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad SSH2 MAC spec '%s'."
, filename, linenum, arg ? arg : "<NONE>")
1487 filename, linenum, arg ? arg : "<NONE>")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1487
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad SSH2 MAC spec '%s'."
, filename, linenum, arg ? arg : "<NONE>")
;
1488 goto out;
1489 }
1490 if (*activep && options->macs == NULL((void *)0))
1491 options->macs = xstrdup(arg);
1492 break;
1493
1494 case oKexAlgorithms:
1495 arg = argv_next(&ac, &av);
1496 if (!arg || *arg == '\0') {
1497 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1498
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1498 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1498
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1499 goto out;
1500 }
1501 if (*arg != '-' &&
1502 !kex_names_valid(*arg == '+' || *arg == '^' ?
1503 arg + 1 : arg)) {
1504 error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1505
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad SSH2 KexAlgorithms '%s'."
, filename, linenum, arg ? arg : "<NONE>")
1505 filename, linenum, arg ? arg : "<NONE>")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1505
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad SSH2 KexAlgorithms '%s'."
, filename, linenum, arg ? arg : "<NONE>")
;
1506 goto out;
1507 }
1508 if (*activep && options->kex_algorithms == NULL((void *)0))
1509 options->kex_algorithms = xstrdup(arg);
1510 break;
1511
1512 case oHostKeyAlgorithms:
1513 charptr = &options->hostkeyalgorithms;
1514 ca_only = 0;
1515parse_pubkey_algos:
1516 arg = argv_next(&ac, &av);
1517 if (!arg || *arg == '\0') {
1518 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1519
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1519 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1519
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1520 goto out;
1521 }
1522 if (*arg != '-' &&
1523 !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1524 arg + 1 : arg, 1, ca_only)) {
1525 error("%s line %d: Bad key types '%s'.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1526
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Bad key types '%s'."
, filename, linenum, arg ? arg : "<NONE>")
1526 filename, linenum, arg ? arg : "<NONE>")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1526
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Bad key types '%s'."
, filename, linenum, arg ? arg : "<NONE>")
;
1527 goto out;
1528 }
1529 if (*activep && *charptr == NULL((void *)0))
1530 *charptr = xstrdup(arg);
1531 break;
1532
1533 case oCASignatureAlgorithms:
1534 charptr = &options->ca_sign_algorithms;
1535 ca_only = 1;
1536 goto parse_pubkey_algos;
1537
1538 case oLogLevel:
1539 log_level_ptr = &options->log_level;
1540 arg = argv_next(&ac, &av);
1541 value = log_level_number(arg);
1542 if (value == SYSLOG_LEVEL_NOT_SET) {
1543 error("%.200s line %d: unsupported log level '%s'",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1544
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: unsupported log level '%s'"
, filename, linenum, arg ? arg : "<NONE>")
1544 filename, linenum, arg ? arg : "<NONE>")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1544
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: unsupported log level '%s'"
, filename, linenum, arg ? arg : "<NONE>")
;
1545 goto out;
1546 }
1547 if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1548 *log_level_ptr = (LogLevel) value;
1549 break;
1550
1551 case oLogFacility:
1552 log_facility_ptr = &options->log_facility;
1553 arg = argv_next(&ac, &av);
1554 value = log_facility_number(arg);
1555 if (value == SYSLOG_FACILITY_NOT_SET) {
1556 error("%.200s line %d: unsupported log facility '%s'",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1557
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: unsupported log facility '%s'"
, filename, linenum, arg ? arg : "<NONE>")
1557 filename, linenum, arg ? arg : "<NONE>")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1557
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: unsupported log facility '%s'"
, filename, linenum, arg ? arg : "<NONE>")
;
1558 goto out;
1559 }
1560 if (*log_facility_ptr == -1)
1561 *log_facility_ptr = (SyslogFacility) value;
1562 break;
1563
1564 case oLogVerbose:
1565 cppptr = &options->log_verbose;
1566 uintptr = &options->num_log_verbose;
1567 i = 0;
1568 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
1569 if (*arg == '\0') {
1570 error("%s line %d: keyword %s empty argument",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1571
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
1571 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1571
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
;
1572 goto out;
1573 }
1574 /* Allow "none" only in first position */
1575 if (strcasecmp(arg, "none") == 0) {
1576 if (i > 0 || ac > 0) {
1577 error("%s line %d: keyword %s \"none\" "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1579
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
1578 "argument must appear alone.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1579
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
1579 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1579
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
;
1580 goto out;
1581 }
1582 }
1583 i++;
1584 if (*activep && *uintptr == 0) {
1585 *cppptr = xrecallocarray(*cppptr, *uintptr,
1586 *uintptr + 1, sizeof(**cppptr));
1587 (*cppptr)[(*uintptr)++] = xstrdup(arg);
1588 }
1589 }
1590 break;
1591
1592 case oLocalForward:
1593 case oRemoteForward:
1594 case oDynamicForward:
1595 arg = argv_next(&ac, &av);
1596 if (!arg || *arg == '\0') {
1597 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1598
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1598 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1598
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1599 goto out;
1600 }
1601
1602 remotefwd = (opcode == oRemoteForward);
1603 dynamicfwd = (opcode == oDynamicForward);
1604
1605 if (!dynamicfwd) {
1606 arg2 = argv_next(&ac, &av);
1607 if (arg2 == NULL((void *)0) || *arg2 == '\0') {
1608 if (remotefwd)
1609 dynamicfwd = 1;
1610 else {
1611 error("%.200s line %d: Missing target "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1612
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing target "
"argument.", filename, linenum)
1612 "argument.", filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1612
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing target "
"argument.", filename, linenum)
;
1613 goto out;
1614 }
1615 } else {
1616 /* construct a string for parse_forward */
1617 snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1618 arg2);
1619 }
1620 }
1621 if (dynamicfwd)
1622 strlcpy(fwdarg, arg, sizeof(fwdarg));
1623
1624 if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1625 error("%.200s line %d: Bad forwarding specification.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1626
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad forwarding specification."
, filename, linenum)
1626 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1626
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad forwarding specification."
, filename, linenum)
;
1627 goto out;
1628 }
1629
1630 if (*activep) {
1631 if (remotefwd) {
1632 add_remote_forward(options, &fwd);
1633 } else {
1634 add_local_forward(options, &fwd);
1635 }
1636 }
1637 break;
1638
1639 case oPermitRemoteOpen:
1640 uintptr = &options->num_permitted_remote_opens;
1641 cppptr = &options->permitted_remote_opens;
1642 uvalue = *uintptr; /* modified later */
1643 i = 0;
1644 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
1645 arg2 = xstrdup(arg);
1646 /* Allow any/none only in first position */
1647 if (strcasecmp(arg, "none") == 0 ||
1648 strcasecmp(arg, "any") == 0) {
1649 if (i > 0 || ac > 0) {
1650 error("%s line %d: keyword %s \"%s\" "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1652
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"%s\" "
"argument must appear alone.", filename, linenum, keyword, arg
)
1651 "argument must appear alone.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1652
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"%s\" "
"argument must appear alone.", filename, linenum, keyword, arg
)
1652 filename, linenum, keyword, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1652
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"%s\" "
"argument must appear alone.", filename, linenum, keyword, arg
)
;
1653 free(arg2);
1654 goto out;
1655 }
1656 } else {
1657 p = hpdelim(&arg);
1658 if (p == NULL((void *)0)) {
1659 fatal("%s line %d: missing host in %s",sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1661
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: missing host in %s"
, filename, linenum, lookup_opcode_name(opcode))
1660 filename, linenum,sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1661
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: missing host in %s"
, filename, linenum, lookup_opcode_name(opcode))
1661 lookup_opcode_name(opcode))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1661
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: missing host in %s"
, filename, linenum, lookup_opcode_name(opcode))
;
1662 }
1663 p = cleanhostname(p);
Value stored to 'p' is never read
1664 /*
1665 * don't want to use permitopen_port to avoid
1666 * dependency on channels.[ch] here.
1667 */
1668 if (arg == NULL((void *)0) || (strcmp(arg, "*") != 0 &&
1669 a2port(arg) <= 0)) {
1670 fatal("%s line %d: bad port number "sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1672
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: bad port number "
"in %s", filename, linenum, lookup_opcode_name(opcode))
1671 "in %s", filename, linenum,sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1672
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: bad port number "
"in %s", filename, linenum, lookup_opcode_name(opcode))
1672 lookup_opcode_name(opcode))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1672
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: bad port number "
"in %s", filename, linenum, lookup_opcode_name(opcode))
;
1673 }
1674 }
1675 if (*activep && uvalue == 0) {
1676 opt_array_append(filename, linenum,
1677 lookup_opcode_name(opcode),
1678 cppptr, uintptr, arg2);
1679 }
1680 free(arg2);
1681 i++;
1682 }
1683 if (i == 0)
1684 fatal("%s line %d: missing %s specification",sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1685
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: missing %s specification"
, filename, linenum, lookup_opcode_name(opcode))
1685 filename, linenum, lookup_opcode_name(opcode))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1685
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: missing %s specification"
, filename, linenum, lookup_opcode_name(opcode))
;
1686 break;
1687
1688 case oClearAllForwardings:
1689 intptr = &options->clear_forwardings;
1690 goto parse_flag;
1691
1692 case oHost:
1693 if (cmdline) {
1694 error("Host directive not supported as a command-line "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1695
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Host directive not supported as a command-line "
"option")
1695 "option")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1695
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Host directive not supported as a command-line "
"option")
;
1696 goto out;
1697 }
1698 *activep = 0;
1699 arg2 = NULL((void *)0);
1700 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
1701 if (*arg == '\0') {
1702 error("%s line %d: keyword %s empty argument",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1703
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
1703 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1703
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
;
1704 goto out;
1705 }
1706 if ((flags & SSHCONF_NEVERMATCH8) != 0) {
1707 argv_consume(&ac);
1708 break;
1709 }
1710 negated = *arg == '!';
1711 if (negated)
1712 arg++;
1713 if (match_pattern(host, arg)) {
1714 if (negated) {
1715 debug("%.200s line %d: Skipping Host "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1718
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: Skipping Host "
"block because of negated match " "for %.100s", filename, linenum
, arg)
1716 "block because of negated match "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1718
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: Skipping Host "
"block because of negated match " "for %.100s", filename, linenum
, arg)
1717 "for %.100s", filename, linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1718
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: Skipping Host "
"block because of negated match " "for %.100s", filename, linenum
, arg)
1718 arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1718
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: Skipping Host "
"block because of negated match " "for %.100s", filename, linenum
, arg)
;
1719 *activep = 0;
1720 argv_consume(&ac);
1721 break;
1722 }
1723 if (!*activep)
1724 arg2 = arg; /* logged below */
1725 *activep = 1;
1726 }
1727 }
1728 if (*activep)
1729 debug("%.200s line %d: Applying options for %.100s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1730
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: Applying options for %.100s"
, filename, linenum, arg2)
1730 filename, linenum, arg2)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1730
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: Applying options for %.100s"
, filename, linenum, arg2)
;
1731 break;
1732
1733 case oMatch:
1734 if (cmdline) {
1735 error("Host directive not supported as a command-line "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1736
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Host directive not supported as a command-line "
"option")
1736 "option")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1736
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Host directive not supported as a command-line "
"option")
;
1737 goto out;
1738 }
1739 value = match_cfg_line(options, &str, pw, host, original_host,
1740 flags & SSHCONF_FINAL4, want_final_pass,
1741 filename, linenum);
1742 if (value < 0) {
1743 error("%.200s line %d: Bad Match condition", filename,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1744
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad Match condition"
, filename, linenum)
1744 linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1744
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad Match condition"
, filename, linenum)
;
1745 goto out;
1746 }
1747 *activep = (flags & SSHCONF_NEVERMATCH8) ? 0 : value;
1748 /*
1749 * If match_cfg_line() didn't consume all its arguments then
1750 * arrange for the extra arguments check below to fail.
1751 */
1752
1753 if (str == NULL((void *)0) || *str == '\0')
1754 argv_consume(&ac);
1755 break;
1756
1757 case oEscapeChar:
1758 intptr = &options->escape_char;
1759 arg = argv_next(&ac, &av);
1760 if (!arg || *arg == '\0') {
1761 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1762
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1762 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1762
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1763 goto out;
1764 }
1765 if (strcmp(arg, "none") == 0)
1766 value = SSH_ESCAPECHAR_NONE-2;
1767 else if (arg[1] == '\0')
1768 value = (u_char) arg[0];
1769 else if (arg[0] == '^' && arg[2] == 0 &&
1770 (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1771 value = (u_char) arg[1] & 31;
1772 else {
1773 error("%.200s line %d: Bad escape character.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1774
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad escape character."
, filename, linenum)
1774 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1774
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad escape character."
, filename, linenum)
;
1775 goto out;
1776 }
1777 if (*activep && *intptr == -1)
1778 *intptr = value;
1779 break;
1780
1781 case oAddressFamily:
1782 intptr = &options->address_family;
1783 multistate_ptr = multistate_addressfamily;
1784 goto parse_multistate;
1785
1786 case oEnableSSHKeysign:
1787 intptr = &options->enable_ssh_keysign;
1788 goto parse_flag;
1789
1790 case oIdentitiesOnly:
1791 intptr = &options->identities_only;
1792 goto parse_flag;
1793
1794 case oServerAliveInterval:
1795 intptr = &options->server_alive_interval;
1796 goto parse_time;
1797
1798 case oServerAliveCountMax:
1799 intptr = &options->server_alive_count_max;
1800 goto parse_int;
1801
1802 case oSendEnv:
1803 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
1804 if (*arg == '\0' || strchr(arg, '=') != NULL((void *)0)) {
1805 error("%s line %d: Invalid environment name.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1806
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Invalid environment name."
, filename, linenum)
1806 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1806
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Invalid environment name."
, filename, linenum)
;
1807 goto out;
1808 }
1809 if (!*activep)
1810 continue;
1811 if (*arg == '-') {
1812 /* Removing an env var */
1813 rm_env(options, arg, filename, linenum);
1814 continue;
1815 }
1816 opt_array_append(filename, linenum,
1817 lookup_opcode_name(opcode),
1818 &options->send_env, &options->num_send_env, arg);
1819 }
1820 break;
1821
1822 case oSetEnv:
1823 value = options->num_setenv;
1824 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
1825 if (strchr(arg, '=') == NULL((void *)0)) {
1826 error("%s line %d: Invalid SetEnv.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1827
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Invalid SetEnv."
, filename, linenum)
1827 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1827
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Invalid SetEnv."
, filename, linenum)
;
1828 goto out;
1829 }
1830 if (!*activep || value != 0)
1831 continue;
1832 if (lookup_setenv_in_list(arg, options->setenv,
1833 options->num_setenv) != NULL((void *)0)) {
1834 debug2("%s line %d: ignoring duplicate env "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1835
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "%s line %d: ignoring duplicate env "
"name \"%.64s\"", filename, linenum, arg)
1835 "name \"%.64s\"", filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1835
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "%s line %d: ignoring duplicate env "
"name \"%.64s\"", filename, linenum, arg)
;
1836 continue;
1837 }
1838 opt_array_append(filename, linenum,
1839 lookup_opcode_name(opcode),
1840 &options->setenv, &options->num_setenv, arg);
1841 }
1842 break;
1843
1844 case oControlPath:
1845 charptr = &options->control_path;
1846 goto parse_string;
1847
1848 case oControlMaster:
1849 intptr = &options->control_master;
1850 multistate_ptr = multistate_controlmaster;
1851 goto parse_multistate;
1852
1853 case oControlPersist:
1854 /* no/false/yes/true, or a time spec */
1855 intptr = &options->control_persist;
1856 arg = argv_next(&ac, &av);
1857 if (!arg || *arg == '\0') {
1858 error("%.200s line %d: Missing ControlPersist"sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1859
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing ControlPersist"
" argument.", filename, linenum)
1859 " argument.", filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1859
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing ControlPersist"
" argument.", filename, linenum)
;
1860 goto out;
1861 }
1862 value = 0;
1863 value2 = 0; /* timeout */
1864 if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1865 value = 0;
1866 else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1867 value = 1;
1868 else if ((value2 = convtime(arg)) >= 0)
1869 value = 1;
1870 else {
1871 error("%.200s line %d: Bad ControlPersist argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1872
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad ControlPersist argument."
, filename, linenum)
1872 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1872
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad ControlPersist argument."
, filename, linenum)
;
1873 goto out;
1874 }
1875 if (*activep && *intptr == -1) {
1876 *intptr = value;
1877 options->control_persist_timeout = value2;
1878 }
1879 break;
1880
1881 case oHashKnownHosts:
1882 intptr = &options->hash_known_hosts;
1883 goto parse_flag;
1884
1885 case oTunnel:
1886 intptr = &options->tun_open;
1887 multistate_ptr = multistate_tunnel;
1888 goto parse_multistate;
1889
1890 case oTunnelDevice:
1891 arg = argv_next(&ac, &av);
1892 if (!arg || *arg == '\0') {
1893 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1894
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
1894 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1894
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
1895 goto out;
1896 }
1897 value = a2tun(arg, &value2);
1898 if (value == SSH_TUNID_ERR(0x7fffffff - 1)) {
1899 error("%.200s line %d: Bad tun device.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1900
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad tun device."
, filename, linenum)
1900 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1900
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad tun device."
, filename, linenum)
;
1901 goto out;
1902 }
1903 if (*activep && options->tun_local == -1) {
1904 options->tun_local = value;
1905 options->tun_remote = value2;
1906 }
1907 break;
1908
1909 case oLocalCommand:
1910 charptr = &options->local_command;
1911 goto parse_command;
1912
1913 case oPermitLocalCommand:
1914 intptr = &options->permit_local_command;
1915 goto parse_flag;
1916
1917 case oRemoteCommand:
1918 charptr = &options->remote_command;
1919 goto parse_command;
1920
1921 case oVisualHostKey:
1922 intptr = &options->visual_host_key;
1923 goto parse_flag;
1924
1925 case oInclude:
1926 if (cmdline) {
1927 error("Include directive not supported as a "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1928
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Include directive not supported as a "
"command-line option")
1928 "command-line option")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1928
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Include directive not supported as a "
"command-line option")
;
1929 goto out;
1930 }
1931 value = 0;
1932 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
1933 if (*arg == '\0') {
1934 error("%s line %d: keyword %s empty argument",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1935
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
1935 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1935
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
;
1936 goto out;
1937 }
1938 /*
1939 * Ensure all paths are anchored. User configuration
1940 * files may begin with '~/' but system configurations
1941 * must not. If the path is relative, then treat it
1942 * as living in ~/.ssh for user configurations or
1943 * /etc/ssh for system ones.
1944 */
1945 if (*arg == '~' && (flags & SSHCONF_USERCONF2) == 0) {
1946 error("%.200s line %d: bad include path %s.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1947
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: bad include path %s."
, filename, linenum, arg)
1947 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1947
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: bad include path %s."
, filename, linenum, arg)
;
1948 goto out;
1949 }
1950 if (!path_absolute(arg) && *arg != '~') {
1951 xasprintf(&arg2, "%s/%s",
1952 (flags & SSHCONF_USERCONF2) ?
1953 "~/" _PATH_SSH_USER_DIR".ssh" : SSHDIR"/etc" "/ssh", arg);
1954 } else
1955 arg2 = xstrdup(arg);
1956 memset(&gl, 0, sizeof(gl));
1957 r = glob(arg2, GLOB_TILDE0x0800, NULL((void *)0), &gl);
1958 if (r == GLOB_NOMATCH(-3)) {
1959 debug("%.200s line %d: include %s matched no "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1960
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: include %s matched no "
"files",filename, linenum, arg2)
1960 "files",filename, linenum, arg2)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1960
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%.200s line %d: include %s matched no "
"files",filename, linenum, arg2)
;
1961 free(arg2);
1962 continue;
1963 } else if (r != 0) {
1964 error("%.200s line %d: glob failed for %s.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1965
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: glob failed for %s."
, filename, linenum, arg2)
1965 filename, linenum, arg2)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1965
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: glob failed for %s."
, filename, linenum, arg2)
;
1966 goto out;
1967 }
1968 free(arg2);
1969 oactive = *activep;
1970 for (i = 0; i < gl.gl_pathc; i++) {
1971 debug3("%.200s line %d: Including file %s "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1974
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: Including file %s "
"depth %d%s", filename, linenum, gl.gl_pathv[i], depth, oactive
? "" : " (parse only)")
1972 "depth %d%s", filename, linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1974
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: Including file %s "
"depth %d%s", filename, linenum, gl.gl_pathv[i], depth, oactive
? "" : " (parse only)")
1973 gl.gl_pathv[i], depth,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1974
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: Including file %s "
"depth %d%s", filename, linenum, gl.gl_pathv[i], depth, oactive
? "" : " (parse only)")
1974 oactive ? "" : " (parse only)")sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1974
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%.200s line %d: Including file %s "
"depth %d%s", filename, linenum, gl.gl_pathv[i], depth, oactive
? "" : " (parse only)")
;
1975 r = read_config_file_depth(gl.gl_pathv[i],
1976 pw, host, original_host, options,
1977 flags | SSHCONF_CHECKPERM1 |
1978 (oactive ? 0 : SSHCONF_NEVERMATCH8),
1979 activep, want_final_pass, depth + 1);
1980 if (r != 1 && errno(*__errno()) != ENOENT2) {
1981 error("Can't open user config file "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1983
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Can't open user config file "
"%.100s: %.100s", gl.gl_pathv[i], strerror((*__errno())))
1982 "%.100s: %.100s", gl.gl_pathv[i],sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1983
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Can't open user config file "
"%.100s: %.100s", gl.gl_pathv[i], strerror((*__errno())))
1983 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 1983
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Can't open user config file "
"%.100s: %.100s", gl.gl_pathv[i], strerror((*__errno())))
;
1984 globfree(&gl);
1985 goto out;
1986 }
1987 /*
1988 * don't let Match in includes clobber the
1989 * containing file's Match state.
1990 */
1991 *activep = oactive;
1992 if (r != 1)
1993 value = -1;
1994 }
1995 globfree(&gl);
1996 }
1997 if (value != 0)
1998 ret = value;
1999 break;
2000
2001 case oIPQoS:
2002 arg = argv_next(&ac, &av);
2003 if ((value = parse_ipqos(arg)) == -1) {
2004 error("%s line %d: Bad IPQoS value: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2005
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Bad IPQoS value: %s"
, filename, linenum, arg)
2005 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2005
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Bad IPQoS value: %s"
, filename, linenum, arg)
;
2006 goto out;
2007 }
2008 arg = argv_next(&ac, &av);
2009 if (arg == NULL((void *)0))
2010 value2 = value;
2011 else if ((value2 = parse_ipqos(arg)) == -1) {
2012 error("%s line %d: Bad IPQoS value: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2013
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Bad IPQoS value: %s"
, filename, linenum, arg)
2013 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2013
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Bad IPQoS value: %s"
, filename, linenum, arg)
;
2014 goto out;
2015 }
2016 if (*activep && options->ip_qos_interactive == -1) {
2017 options->ip_qos_interactive = value;
2018 options->ip_qos_bulk = value2;
2019 }
2020 break;
2021
2022 case oRequestTTY:
2023 intptr = &options->request_tty;
2024 multistate_ptr = multistate_requesttty;
2025 goto parse_multistate;
2026
2027 case oSessionType:
2028 intptr = &options->session_type;
2029 multistate_ptr = multistate_sessiontype;
2030 goto parse_multistate;
2031
2032 case oStdinNull:
2033 intptr = &options->stdin_null;
2034 goto parse_flag;
2035
2036 case oForkAfterAuthentication:
2037 intptr = &options->fork_after_authentication;
2038 goto parse_flag;
2039
2040 case oIgnoreUnknown:
2041 charptr = &options->ignored_unknown;
2042 goto parse_string;
2043
2044 case oProxyUseFdpass:
2045 intptr = &options->proxy_use_fdpass;
2046 goto parse_flag;
2047
2048 case oCanonicalDomains:
2049 value = options->num_canonical_domains != 0;
2050 i = 0;
2051 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
2052 if (*arg == '\0') {
2053 error("%s line %d: keyword %s empty argument",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2054
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
2054 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2054
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s empty argument"
, filename, linenum, keyword)
;
2055 goto out;
2056 }
2057 /* Allow "none" only in first position */
2058 if (strcasecmp(arg, "none") == 0) {
2059 if (i > 0 || ac > 0) {
2060 error("%s line %d: keyword %s \"none\" "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2062
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
2061 "argument must appear alone.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2062
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
2062 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2062
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
;
2063 goto out;
2064 }
2065 }
2066 i++;
2067 if (!valid_domain(arg, 1, &errstr)) {
2068 error("%s line %d: %s", filename, linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2069
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: %s", filename
, linenum, errstr)
2069 errstr)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2069
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: %s", filename
, linenum, errstr)
;
2070 goto out;
2071 }
2072 if (!*activep || value)
2073 continue;
2074 if (options->num_canonical_domains >=
2075 MAX_CANON_DOMAINS32) {
2076 error("%s line %d: too many hostname suffixes.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2077
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: too many hostname suffixes."
, filename, linenum)
2077 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2077
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: too many hostname suffixes."
, filename, linenum)
;
2078 goto out;
2079 }
2080 options->canonical_domains[
2081 options->num_canonical_domains++] = xstrdup(arg);
2082 }
2083 break;
2084
2085 case oCanonicalizePermittedCNAMEs:
2086 value = options->num_permitted_cnames != 0;
2087 i = 0;
2088 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
2089 /*
2090 * Either 'none' (only in first position), '*' for
2091 * everything or 'list:list'
2092 */
2093 if (strcasecmp(arg, "none") == 0) {
2094 if (i > 0 || ac > 0) {
2095 error("%s line %d: keyword %s \"none\" "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2097
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
2096 "argument must appear alone.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2097
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
2097 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2097
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
;
2098 goto out;
2099 }
2100 arg2 = "";
2101 } else if (strcmp(arg, "*") == 0) {
2102 arg2 = arg;
2103 } else {
2104 lowercase(arg);
2105 if ((arg2 = strchr(arg, ':')) == NULL((void *)0) ||
2106 arg2[1] == '\0') {
2107 error("%s line %d: "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2109
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: " "Invalid permitted CNAME \"%s\""
, filename, linenum, arg)
2108 "Invalid permitted CNAME \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2109
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: " "Invalid permitted CNAME \"%s\""
, filename, linenum, arg)
2109 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2109
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: " "Invalid permitted CNAME \"%s\""
, filename, linenum, arg)
;
2110 goto out;
2111 }
2112 *arg2 = '\0';
2113 arg2++;
2114 }
2115 i++;
2116 if (!*activep || value)
2117 continue;
2118 if (options->num_permitted_cnames >=
2119 MAX_CANON_DOMAINS32) {
2120 error("%s line %d: too many permitted CNAMEs.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2121
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: too many permitted CNAMEs."
, filename, linenum)
2121 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2121
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: too many permitted CNAMEs."
, filename, linenum)
;
2122 goto out;
2123 }
2124 cname = options->permitted_cnames +
2125 options->num_permitted_cnames++;
2126 cname->source_list = xstrdup(arg);
2127 cname->target_list = xstrdup(arg2);
2128 }
2129 break;
2130
2131 case oCanonicalizeHostname:
2132 intptr = &options->canonicalize_hostname;
2133 multistate_ptr = multistate_canonicalizehostname;
2134 goto parse_multistate;
2135
2136 case oCanonicalizeMaxDots:
2137 intptr = &options->canonicalize_max_dots;
2138 goto parse_int;
2139
2140 case oCanonicalizeFallbackLocal:
2141 intptr = &options->canonicalize_fallback_local;
2142 goto parse_flag;
2143
2144 case oStreamLocalBindMask:
2145 arg = argv_next(&ac, &av);
2146 if (!arg || *arg == '\0') {
2147 error("%.200s line %d: Missing StreamLocalBindMask "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2148
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing StreamLocalBindMask "
"argument.", filename, linenum)
2148 "argument.", filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2148
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing StreamLocalBindMask "
"argument.", filename, linenum)
;
2149 goto out;
2150 }
2151 /* Parse mode in octal format */
2152 value = strtol(arg, &endofnumber, 8);
2153 if (arg == endofnumber || value < 0 || value > 0777) {
2154 error("%.200s line %d: Bad mask.", filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2154
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Bad mask."
, filename, linenum)
;
2155 goto out;
2156 }
2157 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2158 break;
2159
2160 case oStreamLocalBindUnlink:
2161 intptr = &options->fwd_opts.streamlocal_bind_unlink;
2162 goto parse_flag;
2163
2164 case oRevokedHostKeys:
2165 charptr = &options->revoked_host_keys;
2166 goto parse_string;
2167
2168 case oFingerprintHash:
2169 intptr = &options->fingerprint_hash;
2170 arg = argv_next(&ac, &av);
2171 if (!arg || *arg == '\0') {
2172 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2173
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
2173 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2173
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
2174 goto out;
2175 }
2176 if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2177 error("%.200s line %d: Invalid hash algorithm \"%s\".",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2178
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid hash algorithm \"%s\"."
, filename, linenum, arg)
2178 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2178
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid hash algorithm \"%s\"."
, filename, linenum, arg)
;
2179 goto out;
2180 }
2181 if (*activep && *intptr == -1)
2182 *intptr = value;
2183 break;
2184
2185 case oUpdateHostkeys:
2186 intptr = &options->update_hostkeys;
2187 multistate_ptr = multistate_yesnoask;
2188 goto parse_multistate;
2189
2190 case oHostbasedAcceptedAlgorithms:
2191 charptr = &options->hostbased_accepted_algos;
2192 ca_only = 0;
2193 goto parse_pubkey_algos;
2194
2195 case oPubkeyAcceptedAlgorithms:
2196 charptr = &options->pubkey_accepted_algos;
2197 ca_only = 0;
2198 goto parse_pubkey_algos;
2199
2200 case oAddKeysToAgent:
2201 arg = argv_next(&ac, &av);
2202 arg2 = argv_next(&ac, &av);
2203 value = parse_multistate_value(arg, filename, linenum,
2204 multistate_yesnoaskconfirm);
2205 value2 = 0; /* unlimited lifespan by default */
2206 if (value == 3 && arg2 != NULL((void *)0)) {
2207 /* allow "AddKeysToAgent confirm 5m" */
2208 if ((value2 = convtime(arg2)) == -1) {
2209 error("%s line %d: invalid time value.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2210
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: invalid time value."
, filename, linenum)
2210 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2210
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: invalid time value."
, filename, linenum)
;
2211 goto out;
2212 }
2213 } else if (value == -1 && arg2 == NULL((void *)0)) {
2214 if ((value2 = convtime(arg)) == -1) {
2215 error("%s line %d: unsupported option",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2216
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported option"
, filename, linenum)
2216 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2216
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported option"
, filename, linenum)
;
2217 goto out;
2218 }
2219 value = 1; /* yes */
2220 } else if (value == -1 || arg2 != NULL((void *)0)) {
2221 error("%s line %d: unsupported option",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2222
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported option"
, filename, linenum)
2222 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2222
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported option"
, filename, linenum)
;
2223 goto out;
2224 }
2225 if (*activep && options->add_keys_to_agent == -1) {
2226 options->add_keys_to_agent = value;
2227 options->add_keys_to_agent_lifespan = value2;
2228 }
2229 break;
2230
2231 case oIdentityAgent:
2232 charptr = &options->identity_agent;
2233 arg = argv_next(&ac, &av);
2234 if (!arg || *arg == '\0') {
2235 error("%.200s line %d: Missing argument.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2236
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
2236 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2236
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Missing argument."
, filename, linenum)
;
2237 goto out;
2238 }
2239 parse_agent_path:
2240 /* Extra validation if the string represents an env var. */
2241 if ((arg2 = dollar_expand(&r, arg)) == NULL((void *)0) || r) {
2242 error("%.200s line %d: Invalid environment expansion "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2243
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid environment expansion "
"%s.", filename, linenum, arg)
2243 "%s.", filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2243
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid environment expansion "
"%s.", filename, linenum, arg)
;
2244 goto out;
2245 }
2246 free(arg2);
2247 /* check for legacy environment format */
2248 if (arg[0] == '$' && arg[1] != '{' &&
2249 !valid_env_name(arg + 1)) {
2250 error("%.200s line %d: Invalid environment name %s.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2251
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid environment name %s."
, filename, linenum, arg)
2251 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2251
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: Invalid environment name %s."
, filename, linenum, arg)
;
2252 goto out;
2253 }
2254 if (*activep && *charptr == NULL((void *)0))
2255 *charptr = xstrdup(arg);
2256 break;
2257
2258 case oEnableEscapeCommandline:
2259 intptr = &options->enable_escape_commandline;
2260 goto parse_flag;
2261
2262 case oRequiredRSASize:
2263 intptr = &options->required_rsa_size;
2264 goto parse_int;
2265
2266 case oObscureKeystrokeTiming:
2267 value = -1;
2268 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
2269 if (value != -1) {
2270 error("%s line %d: invalid arguments",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2271
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: invalid arguments"
, filename, linenum)
2271 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2271
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: invalid arguments"
, filename, linenum)
;
2272 goto out;
2273 }
2274 if (strcmp(arg, "yes") == 0 ||
2275 strcmp(arg, "true") == 0)
2276 value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS20;
2277 else if (strcmp(arg, "no") == 0 ||
2278 strcmp(arg, "false") == 0)
2279 value = 0;
2280 else if (strncmp(arg, "interval:", 9) == 0) {
2281 if ((errstr = atoi_err(arg + 9,
2282 &value)) != NULL((void *)0)) {
2283 error("%s line %d: integer value %s.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2284
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: integer value %s."
, filename, linenum, errstr)
2284 filename, linenum, errstr)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2284
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: integer value %s."
, filename, linenum, errstr)
;
2285 goto out;
2286 }
2287 if (value <= 0 || value > 1000) {
2288 error("%s line %d: value out of range.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2289
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: value out of range."
, filename, linenum)
2289 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2289
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: value out of range."
, filename, linenum)
;
2290 goto out;
2291 }
2292 } else {
2293 error("%s line %d: unsupported argument \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2294
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported argument \"%s\""
, filename, linenum, arg)
2294 filename, linenum, arg)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2294
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: unsupported argument \"%s\""
, filename, linenum, arg)
;
2295 goto out;
2296 }
2297 }
2298 if (value == -1) {
2299 error("%s line %d: missing argument",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2300
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: missing argument"
, filename, linenum)
2300 filename, linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2300
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: missing argument"
, filename, linenum)
;
2301 goto out;
2302 }
2303 intptr = &options->obscure_keystroke_timing_interval;
2304 if (*activep && *intptr == -1)
2305 *intptr = value;
2306 break;
2307
2308 case oChannelTimeout:
2309 uvalue = options->num_channel_timeouts;
2310 i = 0;
2311 while ((arg = argv_next(&ac, &av)) != NULL((void *)0)) {
2312 /* Allow "none" only in first position */
2313 if (strcasecmp(arg, "none") == 0) {
2314 if (i > 0 || ac > 0) {
2315 error("%s line %d: keyword %s \"none\" "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2317
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
2316 "argument must appear alone.",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2317
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
2317 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2317
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: keyword %s \"none\" "
"argument must appear alone.", filename, linenum, keyword)
;
2318 goto out;
2319 }
2320 } else if (parse_pattern_interval(arg,
2321 NULL((void *)0), NULL((void *)0)) != 0) {
2322 fatal("%s line %d: invalid channel timeout %s",sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2323
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: invalid channel timeout %s"
, filename, linenum, arg)
2323 filename, linenum, arg)sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2323
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s line %d: invalid channel timeout %s"
, filename, linenum, arg)
;
2324 }
2325 if (!*activep || uvalue != 0)
2326 continue;
2327 opt_array_append(filename, linenum, keyword,
2328 &options->channel_timeouts,
2329 &options->num_channel_timeouts, arg);
2330 }
2331 break;
2332
2333 case oDeprecated:
2334 debug("%s line %d: Deprecated option \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2335
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s line %d: Deprecated option \"%s\""
, filename, linenum, keyword)
2335 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2335
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s line %d: Deprecated option \"%s\""
, filename, linenum, keyword)
;
2336 argv_consume(&ac);
2337 break;
2338
2339 case oUnsupported:
2340 error("%s line %d: Unsupported option \"%s\"",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2341
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Unsupported option \"%s\""
, filename, linenum, keyword)
2341 filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2341
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Unsupported option \"%s\""
, filename, linenum, keyword)
;
2342 argv_consume(&ac);
2343 break;
2344
2345 default:
2346 error("%s line %d: Unimplemented opcode %d",sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2347
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Unimplemented opcode %d"
, filename, linenum, opcode)
2347 filename, linenum, opcode)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2347
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s line %d: Unimplemented opcode %d"
, filename, linenum, opcode)
;
2348 goto out;
2349 }
2350
2351 /* Check that there is no garbage at end of line. */
2352 if (ac > 0) {
2353 error("%.200s line %d: keyword %s extra arguments "sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2354
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: keyword %s extra arguments "
"at end of line", filename, linenum, keyword)
2354 "at end of line", filename, linenum, keyword)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2354
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.200s line %d: keyword %s extra arguments "
"at end of line", filename, linenum, keyword)
;
2355 goto out;
2356 }
2357
2358 /* success */
2359 ret = 0;
2360 out:
2361 argv_free(oav, oac);
2362 return ret;
2363}
2364
2365/*
2366 * Reads the config file and modifies the options accordingly. Options
2367 * should already be initialized before this call. This never returns if
2368 * there is an error. If the file does not exist, this returns 0.
2369 */
2370int
2371read_config_file(const char *filename, struct passwd *pw, const char *host,
2372 const char *original_host, Options *options, int flags,
2373 int *want_final_pass)
2374{
2375 int active = 1;
2376
2377 return read_config_file_depth(filename, pw, host, original_host,
2378 options, flags, &active, want_final_pass, 0);
2379}
2380
2381#define READCONF_MAX_DEPTH16 16
2382static int
2383read_config_file_depth(const char *filename, struct passwd *pw,
2384 const char *host, const char *original_host, Options *options,
2385 int flags, int *activep, int *want_final_pass, int depth)
2386{
2387 FILE *f;
2388 char *line = NULL((void *)0);
2389 size_t linesize = 0;
2390 int linenum;
2391 int bad_options = 0;
2392
2393 if (depth < 0 || depth > READCONF_MAX_DEPTH16)
2394 fatal("Too many recursive configuration includes")sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2394
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Too many recursive configuration includes"
)
;
2395
2396 if ((f = fopen(filename, "r")) == NULL((void *)0))
2397 return 0;
2398
2399 if (flags & SSHCONF_CHECKPERM1) {
2400 struct stat sb;
2401
2402 if (fstat(fileno(f)(!__isthreaded ? ((f)->_file) : (fileno)(f)), &sb) == -1)
2403 fatal("fstat %s: %s", filename, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2403
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "fstat %s: %s", filename
, strerror((*__errno())))
;
2404 if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2405 (sb.st_mode & 022) != 0))
2406 fatal("Bad owner or permissions on %s", filename)sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2406
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Bad owner or permissions on %s"
, filename)
;
2407 }
2408
2409 debug("Reading configuration data %.200s", filename)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2409
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Reading configuration data %.200s"
, filename)
;
2410
2411 /*
2412 * Mark that we are now processing the options. This flag is turned
2413 * on/off by Host specifications.
2414 */
2415 linenum = 0;
2416 while (getline(&line, &linesize, f) != -1) {
2417 /* Update line number counter. */
2418 linenum++;
2419 /*
2420 * Trim out comments and strip whitespace.
2421 * NB - preserve newlines, they are needed to reproduce
2422 * line numbers later for error messages.
2423 */
2424 if (process_config_line_depth(options, pw, host, original_host,
2425 line, filename, linenum, activep, flags, want_final_pass,
2426 depth) != 0)
2427 bad_options++;
2428 }
2429 free(line);
2430 fclose(f);
2431 if (bad_options > 0)
2432 fatal("%s: terminating, %d bad configuration options",sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2433
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s: terminating, %d bad configuration options"
, filename, bad_options)
2433 filename, bad_options)sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2433
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s: terminating, %d bad configuration options"
, filename, bad_options)
;
2434 return 1;
2435}
2436
2437/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2438int
2439option_clear_or_none(const char *o)
2440{
2441 return o == NULL((void *)0) || strcasecmp(o, "none") == 0;
2442}
2443
2444/*
2445 * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2446 * Allowed to be called on non-final configuration.
2447 */
2448int
2449config_has_permitted_cnames(Options *options)
2450{
2451 if (options->num_permitted_cnames == 1 &&
2452 strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2453 strcmp(options->permitted_cnames[0].target_list, "") == 0)
2454 return 0;
2455 return options->num_permitted_cnames > 0;
2456}
2457
2458/*
2459 * Initializes options to special values that indicate that they have not yet
2460 * been set. Read_config_file will only set options with this value. Options
2461 * are processed in the following order: command line, user config file,
2462 * system config file. Last, fill_default_options is called.
2463 */
2464
2465void
2466initialize_options(Options * options)
2467{
2468 memset(options, 'X', sizeof(*options));
2469 options->host_arg = NULL((void *)0);
2470 options->forward_agent = -1;
2471 options->forward_agent_sock_path = NULL((void *)0);
2472 options->forward_x11 = -1;
2473 options->forward_x11_trusted = -1;
2474 options->forward_x11_timeout = -1;
2475 options->stdio_forward_host = NULL((void *)0);
2476 options->stdio_forward_port = 0;
2477 options->clear_forwardings = -1;
2478 options->exit_on_forward_failure = -1;
2479 options->xauth_location = NULL((void *)0);
2480 options->fwd_opts.gateway_ports = -1;
2481 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2482 options->fwd_opts.streamlocal_bind_unlink = -1;
2483 options->pubkey_authentication = -1;
2484 options->gss_authentication = -1;
2485 options->gss_deleg_creds = -1;
2486 options->password_authentication = -1;
2487 options->kbd_interactive_authentication = -1;
2488 options->kbd_interactive_devices = NULL((void *)0);
2489 options->hostbased_authentication = -1;
2490 options->batch_mode = -1;
2491 options->check_host_ip = -1;
2492 options->strict_host_key_checking = -1;
2493 options->compression = -1;
2494 options->tcp_keep_alive = -1;
2495 options->port = -1;
2496 options->address_family = -1;
2497 options->connection_attempts = -1;
2498 options->connection_timeout = -1;
2499 options->number_of_password_prompts = -1;
2500 options->ciphers = NULL((void *)0);
2501 options->macs = NULL((void *)0);
2502 options->kex_algorithms = NULL((void *)0);
2503 options->hostkeyalgorithms = NULL((void *)0);
2504 options->ca_sign_algorithms = NULL((void *)0);
2505 options->num_identity_files = 0;
2506 memset(options->identity_keys, 0, sizeof(options->identity_keys));
2507 options->num_certificate_files = 0;
2508 memset(options->certificates, 0, sizeof(options->certificates));
2509 options->hostname = NULL((void *)0);
2510 options->host_key_alias = NULL((void *)0);
2511 options->proxy_command = NULL((void *)0);
2512 options->jump_user = NULL((void *)0);
2513 options->jump_host = NULL((void *)0);
2514 options->jump_port = -1;
2515 options->jump_extra = NULL((void *)0);
2516 options->user = NULL((void *)0);
2517 options->escape_char = -1;
2518 options->num_system_hostfiles = 0;
2519 options->num_user_hostfiles = 0;
2520 options->local_forwards = NULL((void *)0);
2521 options->num_local_forwards = 0;
2522 options->remote_forwards = NULL((void *)0);
2523 options->num_remote_forwards = 0;
2524 options->permitted_remote_opens = NULL((void *)0);
2525 options->num_permitted_remote_opens = 0;
2526 options->log_facility = SYSLOG_FACILITY_NOT_SET;
2527 options->log_level = SYSLOG_LEVEL_NOT_SET;
2528 options->num_log_verbose = 0;
2529 options->log_verbose = NULL((void *)0);
2530 options->preferred_authentications = NULL((void *)0);
2531 options->bind_address = NULL((void *)0);
2532 options->bind_interface = NULL((void *)0);
2533 options->pkcs11_provider = NULL((void *)0);
2534 options->sk_provider = NULL((void *)0);
2535 options->enable_ssh_keysign = - 1;
2536 options->no_host_authentication_for_localhost = - 1;
2537 options->identities_only = - 1;
2538 options->rekey_limit = - 1;
2539 options->rekey_interval = -1;
2540 options->verify_host_key_dns = -1;
2541 options->server_alive_interval = -1;
2542 options->server_alive_count_max = -1;
2543 options->send_env = NULL((void *)0);
2544 options->num_send_env = 0;
2545 options->setenv = NULL((void *)0);
2546 options->num_setenv = 0;
2547 options->control_path = NULL((void *)0);
2548 options->control_master = -1;
2549 options->control_persist = -1;
2550 options->control_persist_timeout = 0;
2551 options->hash_known_hosts = -1;
2552 options->tun_open = -1;
2553 options->tun_local = -1;
2554 options->tun_remote = -1;
2555 options->local_command = NULL((void *)0);
2556 options->permit_local_command = -1;
2557 options->remote_command = NULL((void *)0);
2558 options->add_keys_to_agent = -1;
2559 options->add_keys_to_agent_lifespan = -1;
2560 options->identity_agent = NULL((void *)0);
2561 options->visual_host_key = -1;
2562 options->ip_qos_interactive = -1;
2563 options->ip_qos_bulk = -1;
2564 options->request_tty = -1;
2565 options->session_type = -1;
2566 options->stdin_null = -1;
2567 options->fork_after_authentication = -1;
2568 options->proxy_use_fdpass = -1;
2569 options->ignored_unknown = NULL((void *)0);
2570 options->num_canonical_domains = 0;
2571 options->num_permitted_cnames = 0;
2572 options->canonicalize_max_dots = -1;
2573 options->canonicalize_fallback_local = -1;
2574 options->canonicalize_hostname = -1;
2575 options->revoked_host_keys = NULL((void *)0);
2576 options->fingerprint_hash = -1;
2577 options->update_hostkeys = -1;
2578 options->hostbased_accepted_algos = NULL((void *)0);
2579 options->pubkey_accepted_algos = NULL((void *)0);
2580 options->known_hosts_command = NULL((void *)0);
2581 options->required_rsa_size = -1;
2582 options->enable_escape_commandline = -1;
2583 options->obscure_keystroke_timing_interval = -1;
2584 options->tag = NULL((void *)0);
2585 options->channel_timeouts = NULL((void *)0);
2586 options->num_channel_timeouts = 0;
2587}
2588
2589/*
2590 * A petite version of fill_default_options() that just fills the options
2591 * needed for hostname canonicalization to proceed.
2592 */
2593void
2594fill_default_options_for_canonicalization(Options *options)
2595{
2596 if (options->canonicalize_max_dots == -1)
2597 options->canonicalize_max_dots = 1;
2598 if (options->canonicalize_fallback_local == -1)
2599 options->canonicalize_fallback_local = 1;
2600 if (options->canonicalize_hostname == -1)
2601 options->canonicalize_hostname = SSH_CANONICALISE_NO0;
2602}
2603
2604/*
2605 * Called after processing other sources of option data, this fills those
2606 * options for which no value has been specified with their default values.
2607 */
2608int
2609fill_default_options(Options * options)
2610{
2611 char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2612 char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2613 int ret = 0, r;
2614
2615 if (options->forward_agent == -1)
2616 options->forward_agent = 0;
2617 if (options->forward_x11 == -1)
2618 options->forward_x11 = 0;
2619 if (options->forward_x11_trusted == -1)
2620 options->forward_x11_trusted = 0;
2621 if (options->forward_x11_timeout == -1)
2622 options->forward_x11_timeout = 1200;
2623 /*
2624 * stdio forwarding (-W) changes the default for these but we defer
2625 * setting the values so they can be overridden.
2626 */
2627 if (options->exit_on_forward_failure == -1)
2628 options->exit_on_forward_failure =
2629 options->stdio_forward_host != NULL((void *)0) ? 1 : 0;
2630 if (options->clear_forwardings == -1)
2631 options->clear_forwardings =
2632 options->stdio_forward_host != NULL((void *)0) ? 1 : 0;
2633 if (options->clear_forwardings == 1)
2634 clear_forwardings(options);
2635
2636 if (options->xauth_location == NULL((void *)0))
2637 options->xauth_location = xstrdup(_PATH_XAUTH"/usr/X11R6/bin/xauth");
2638 if (options->fwd_opts.gateway_ports == -1)
2639 options->fwd_opts.gateway_ports = 0;
2640 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2641 options->fwd_opts.streamlocal_bind_mask = 0177;
2642 if (options->fwd_opts.streamlocal_bind_unlink == -1)
2643 options->fwd_opts.streamlocal_bind_unlink = 0;
2644 if (options->pubkey_authentication == -1)
2645 options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL0x03;
2646 if (options->gss_authentication == -1)
2647 options->gss_authentication = 0;
2648 if (options->gss_deleg_creds == -1)
2649 options->gss_deleg_creds = 0;
2650 if (options->password_authentication == -1)
2651 options->password_authentication = 1;
2652 if (options->kbd_interactive_authentication == -1)
2653 options->kbd_interactive_authentication = 1;
2654 if (options->hostbased_authentication == -1)
2655 options->hostbased_authentication = 0;
2656 if (options->batch_mode == -1)
2657 options->batch_mode = 0;
2658 if (options->check_host_ip == -1)
2659 options->check_host_ip = 0;
2660 if (options->strict_host_key_checking == -1)
2661 options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK3;
2662 if (options->compression == -1)
2663 options->compression = 0;
2664 if (options->tcp_keep_alive == -1)
2665 options->tcp_keep_alive = 1;
2666 if (options->port == -1)
2667 options->port = 0; /* Filled in ssh_connect. */
2668 if (options->address_family == -1)
2669 options->address_family = AF_UNSPEC0;
2670 if (options->connection_attempts == -1)
2671 options->connection_attempts = 1;
2672 if (options->number_of_password_prompts == -1)
2673 options->number_of_password_prompts = 3;
2674 /* options->hostkeyalgorithms, default set in myproposals.h */
2675 if (options->add_keys_to_agent == -1) {
2676 options->add_keys_to_agent = 0;
2677 options->add_keys_to_agent_lifespan = 0;
2678 }
2679 if (options->num_identity_files == 0) {
2680 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA".ssh" "/id_rsa", 0);
2681 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA".ssh" "/id_ecdsa", 0);
2682 add_identity_file(options, "~/",
2683 _PATH_SSH_CLIENT_ID_ECDSA_SK".ssh" "/id_ecdsa_sk", 0);
2684 add_identity_file(options, "~/",
2685 _PATH_SSH_CLIENT_ID_ED25519".ssh" "/id_ed25519", 0);
2686 add_identity_file(options, "~/",
2687 _PATH_SSH_CLIENT_ID_ED25519_SK".ssh" "/id_ed25519_sk", 0);
2688 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS".ssh" "/id_xmss", 0);
2689#ifdef WITH_DSA1
2690 add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA".ssh" "/id_dsa", 0);
2691#endif
2692 }
2693 if (options->escape_char == -1)
2694 options->escape_char = '~';
2695 if (options->num_system_hostfiles == 0) {
2696 options->system_hostfiles[options->num_system_hostfiles++] =
2697 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE"/etc" "/ssh" "/ssh_known_hosts");
2698 options->system_hostfiles[options->num_system_hostfiles++] =
2699 xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2"/etc" "/ssh" "/ssh_known_hosts2");
2700 }
2701 if (options->update_hostkeys == -1) {
2702 if (options->verify_host_key_dns <= 0 &&
2703 (options->num_user_hostfiles == 0 ||
2704 (options->num_user_hostfiles == 1 && strcmp(options->
2705 user_hostfiles[0], _PATH_SSH_USER_HOSTFILE"~/" ".ssh" "/known_hosts") == 0)))
2706 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES1;
2707 else
2708 options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO0;
2709 }
2710 if (options->num_user_hostfiles == 0) {
2711 options->user_hostfiles[options->num_user_hostfiles++] =
2712 xstrdup(_PATH_SSH_USER_HOSTFILE"~/" ".ssh" "/known_hosts");
2713 options->user_hostfiles[options->num_user_hostfiles++] =
2714 xstrdup(_PATH_SSH_USER_HOSTFILE2"~/" ".ssh" "/known_hosts2");
2715 }
2716 if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2717 options->log_level = SYSLOG_LEVEL_INFO;
2718 if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2719 options->log_facility = SYSLOG_FACILITY_USER;
2720 if (options->no_host_authentication_for_localhost == - 1)
2721 options->no_host_authentication_for_localhost = 0;
2722 if (options->identities_only == -1)
2723 options->identities_only = 0;
2724 if (options->enable_ssh_keysign == -1)
2725 options->enable_ssh_keysign = 0;
2726 if (options->rekey_limit == -1)
2727 options->rekey_limit = 0;
2728 if (options->rekey_interval == -1)
2729 options->rekey_interval = 0;
2730 if (options->verify_host_key_dns == -1)
2731 options->verify_host_key_dns = 0;
2732 if (options->server_alive_interval == -1)
2733 options->server_alive_interval = 0;
2734 if (options->server_alive_count_max == -1)
2735 options->server_alive_count_max = 3;
2736 if (options->control_master == -1)
2737 options->control_master = 0;
2738 if (options->control_persist == -1) {
2739 options->control_persist = 0;
2740 options->control_persist_timeout = 0;
2741 }
2742 if (options->hash_known_hosts == -1)
2743 options->hash_known_hosts = 0;
2744 if (options->tun_open == -1)
2745 options->tun_open = SSH_TUNMODE_NO0x00;
2746 if (options->tun_local == -1)
2747 options->tun_local = SSH_TUNID_ANY0x7fffffff;
2748 if (options->tun_remote == -1)
2749 options->tun_remote = SSH_TUNID_ANY0x7fffffff;
2750 if (options->permit_local_command == -1)
2751 options->permit_local_command = 0;
2752 if (options->visual_host_key == -1)
2753 options->visual_host_key = 0;
2754 if (options->ip_qos_interactive == -1)
2755 options->ip_qos_interactive = IPTOS_DSCP_AF210x48;
2756 if (options->ip_qos_bulk == -1)
2757 options->ip_qos_bulk = IPTOS_DSCP_CS10x20;
2758 if (options->request_tty == -1)
2759 options->request_tty = REQUEST_TTY_AUTO0;
2760 if (options->session_type == -1)
2761 options->session_type = SESSION_TYPE_DEFAULT2;
2762 if (options->stdin_null == -1)
2763 options->stdin_null = 0;
2764 if (options->fork_after_authentication == -1)
2765 options->fork_after_authentication = 0;
2766 if (options->proxy_use_fdpass == -1)
2767 options->proxy_use_fdpass = 0;
2768 if (options->canonicalize_max_dots == -1)
2769 options->canonicalize_max_dots = 1;
2770 if (options->canonicalize_fallback_local == -1)
2771 options->canonicalize_fallback_local = 1;
2772 if (options->canonicalize_hostname == -1)
2773 options->canonicalize_hostname = SSH_CANONICALISE_NO0;
2774 if (options->fingerprint_hash == -1)
2775 options->fingerprint_hash = SSH_FP_HASH_DEFAULT2;
2776 if (options->sk_provider == NULL((void *)0))
2777 options->sk_provider = xstrdup("internal");
2778 if (options->required_rsa_size == -1)
2779 options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE1024;
2780 if (options->enable_escape_commandline == -1)
2781 options->enable_escape_commandline = 0;
2782 if (options->obscure_keystroke_timing_interval == -1) {
2783 options->obscure_keystroke_timing_interval =
2784 SSH_KEYSTROKE_DEFAULT_INTERVAL_MS20;
2785 }
2786
2787 /* Expand KEX name lists */
2788 all_cipher = cipher_alg_list(',', 0);
2789 all_mac = mac_alg_list(',');
2790 all_kex = kex_alg_list(',');
2791 all_key = sshkey_alg_list(0, 0, 1, ',');
2792 all_sig = sshkey_alg_list(0, 1, 1, ',');
2793 /* remove unsupported algos from default lists */
2794 def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT"chacha20-poly1305@openssh.com," "aes128-ctr,aes192-ctr,aes256-ctr,"
"aes128-gcm@openssh.com,aes256-gcm@openssh.com"
, all_cipher);
2795 def_mac = match_filter_allowlist(KEX_CLIENT_MAC"umac-64-etm@openssh.com," "umac-128-etm@openssh.com," "hmac-sha2-256-etm@openssh.com,"
"hmac-sha2-512-etm@openssh.com," "hmac-sha1-etm@openssh.com,"
"umac-64@openssh.com," "umac-128@openssh.com," "hmac-sha2-256,"
"hmac-sha2-512," "hmac-sha1"
, all_mac);
2796 def_kex = match_filter_allowlist(KEX_CLIENT_KEX"sntrup761x25519-sha512@openssh.com," "curve25519-sha256," "curve25519-sha256@libssh.org,"
"ecdh-sha2-nistp256," "ecdh-sha2-nistp384," "ecdh-sha2-nistp521,"
"diffie-hellman-group-exchange-sha256," "diffie-hellman-group16-sha512,"
"diffie-hellman-group18-sha512," "diffie-hellman-group14-sha256"
, all_kex);
2797 def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG"ssh-ed25519-cert-v01@openssh.com," "ecdsa-sha2-nistp256-cert-v01@openssh.com,"
"ecdsa-sha2-nistp384-cert-v01@openssh.com," "ecdsa-sha2-nistp521-cert-v01@openssh.com,"
"sk-ssh-ed25519-cert-v01@openssh.com," "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,"
"rsa-sha2-512-cert-v01@openssh.com," "rsa-sha2-256-cert-v01@openssh.com,"
"ssh-ed25519," "ecdsa-sha2-nistp256," "ecdsa-sha2-nistp384,"
"ecdsa-sha2-nistp521," "sk-ssh-ed25519@openssh.com," "sk-ecdsa-sha2-nistp256@openssh.com,"
"rsa-sha2-512," "rsa-sha2-256"
, all_key);
2798 def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS"ssh-ed25519," "ecdsa-sha2-nistp256," "ecdsa-sha2-nistp384," "ecdsa-sha2-nistp521,"
"sk-ssh-ed25519@openssh.com," "sk-ecdsa-sha2-nistp256@openssh.com,"
"rsa-sha2-512," "rsa-sha2-256"
, all_sig);
2799#define ASSEMBLE(what, defaults, all) \
2800 do { \
2801 if ((r = kex_assemble_names(&options->what, \
2802 defaults, all)) != 0) { \
2803 error_fr(r, "%s", #what)sshlog("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 2803
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "%s", #what)
; \
2804 goto fail; \
2805 } \
2806 } while (0)
2807 ASSEMBLE(ciphers, def_cipher, all_cipher);
2808 ASSEMBLE(macs, def_mac, all_mac);
2809 ASSEMBLE(kex_algorithms, def_kex, all_kex);
2810 ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2811 ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2812 ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2813#undef ASSEMBLE
2814
2815#define CLEAR_ON_NONE(v) \
2816 do { \
2817 if (option_clear_or_none(v)) { \
2818 free(v); \
2819 v = NULL((void *)0); \
2820 } \
2821 } while(0)
2822#define CLEAR_ON_NONE_ARRAY(v, nv, none) \
2823 do { \
2824 if (options->nv == 1 && \
2825 strcasecmp(options->v[0], none) == 0) { \
2826 free(options->v[0]); \
2827 free(options->v); \
2828 options->v = NULL((void *)0); \
2829 options->nv = 0; \
2830 } \
2831 } while (0)
2832 CLEAR_ON_NONE(options->local_command);
2833 CLEAR_ON_NONE(options->remote_command);
2834 CLEAR_ON_NONE(options->proxy_command);
2835 CLEAR_ON_NONE(options->control_path);
2836 CLEAR_ON_NONE(options->revoked_host_keys);
2837 CLEAR_ON_NONE(options->pkcs11_provider);
2838 CLEAR_ON_NONE(options->sk_provider);
2839 CLEAR_ON_NONE(options->known_hosts_command);
2840 CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
2841#undef CLEAR_ON_NONE
2842#undef CLEAR_ON_NONE_ARRAY
2843 if (options->jump_host != NULL((void *)0) &&
2844 strcmp(options->jump_host, "none") == 0 &&
2845 options->jump_port == 0 && options->jump_user == NULL((void *)0)) {
2846 free(options->jump_host);
2847 options->jump_host = NULL((void *)0);
2848 }
2849 if (options->num_permitted_cnames == 1 &&
2850 !config_has_permitted_cnames(options)) {
2851 /* clean up CanonicalizePermittedCNAMEs=none */
2852 free(options->permitted_cnames[0].source_list);
2853 free(options->permitted_cnames[0].target_list);
2854 memset(options->permitted_cnames, '\0',
2855 sizeof(*options->permitted_cnames));
2856 options->num_permitted_cnames = 0;
2857 }
2858 /* options->identity_agent distinguishes NULL from 'none' */
2859 /* options->user will be set in the main program if appropriate */
2860 /* options->hostname will be set in the main program if appropriate */
2861 /* options->host_key_alias should not be set by default */
2862 /* options->preferred_authentications will be set in ssh */
2863
2864 /* success */
2865 ret = 0;
2866 fail:
2867 free(all_cipher);
2868 free(all_mac);
2869 free(all_kex);
2870 free(all_key);
2871 free(all_sig);
2872 free(def_cipher);
2873 free(def_mac);
2874 free(def_kex);
2875 free(def_key);
2876 free(def_sig);
2877 return ret;
2878}
2879
2880void
2881free_options(Options *o)
2882{
2883 int i;
2884
2885 if (o == NULL((void *)0))
2886 return;
2887
2888#define FREE_ARRAY(type, n, a) \
2889 do { \
2890 type _i; \
2891 for (_i = 0; _i < (n); _i++) \
2892 free((a)[_i]); \
2893 } while (0)
2894
2895 free(o->forward_agent_sock_path);
2896 free(o->xauth_location);
2897 FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2898 free(o->log_verbose);
2899 free(o->ciphers);
2900 free(o->macs);
2901 free(o->hostkeyalgorithms);
2902 free(o->kex_algorithms);
2903 free(o->ca_sign_algorithms);
2904 free(o->hostname);
2905 free(o->host_key_alias);
2906 free(o->proxy_command);
2907 free(o->user);
2908 FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2909 FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2910 free(o->preferred_authentications);
2911 free(o->bind_address);
2912 free(o->bind_interface);
2913 free(o->pkcs11_provider);
2914 free(o->sk_provider);
2915 for (i = 0; i < o->num_identity_files; i++) {
2916 free(o->identity_files[i]);
2917 sshkey_free(o->identity_keys[i]);
2918 }
2919 for (i = 0; i < o->num_certificate_files; i++) {
2920 free(o->certificate_files[i]);
2921 sshkey_free(o->certificates[i]);
2922 }
2923 free(o->identity_agent);
2924 for (i = 0; i < o->num_local_forwards; i++) {
2925 free(o->local_forwards[i].listen_host);
2926 free(o->local_forwards[i].listen_path);
2927 free(o->local_forwards[i].connect_host);
2928 free(o->local_forwards[i].connect_path);
2929 }
2930 free(o->local_forwards);
2931 for (i = 0; i < o->num_remote_forwards; i++) {
2932 free(o->remote_forwards[i].listen_host);
2933 free(o->remote_forwards[i].listen_path);
2934 free(o->remote_forwards[i].connect_host);
2935 free(o->remote_forwards[i].connect_path);
2936 }
2937 free(o->remote_forwards);
2938 free(o->stdio_forward_host);
2939 FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2940 free(o->send_env);
2941 FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2942 free(o->setenv);
2943 free(o->control_path);
2944 free(o->local_command);
2945 free(o->remote_command);
2946 FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2947 for (i = 0; i < o->num_permitted_cnames; i++) {
2948 free(o->permitted_cnames[i].source_list);
2949 free(o->permitted_cnames[i].target_list);
2950 }
2951 free(o->revoked_host_keys);
2952 free(o->hostbased_accepted_algos);
2953 free(o->pubkey_accepted_algos);
2954 free(o->jump_user);
2955 free(o->jump_host);
2956 free(o->jump_extra);
2957 free(o->ignored_unknown);
2958 explicit_bzero(o, sizeof(*o));
2959#undef FREE_ARRAY
2960}
2961
2962struct fwdarg {
2963 char *arg;
2964 int ispath;
2965};
2966
2967/*
2968 * parse_fwd_field
2969 * parses the next field in a port forwarding specification.
2970 * sets fwd to the parsed field and advances p past the colon
2971 * or sets it to NULL at end of string.
2972 * returns 0 on success, else non-zero.
2973 */
2974static int
2975parse_fwd_field(char **p, struct fwdarg *fwd)
2976{
2977 char *ep, *cp = *p;
2978 int ispath = 0;
2979
2980 if (*cp == '\0') {
2981 *p = NULL((void *)0);
2982 return -1; /* end of string */
2983 }
2984
2985 /*
2986 * A field escaped with square brackets is used literally.
2987 * XXX - allow ']' to be escaped via backslash?
2988 */
2989 if (*cp == '[') {
2990 /* find matching ']' */
2991 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2992 if (*ep == '/')
2993 ispath = 1;
2994 }
2995 /* no matching ']' or not at end of field. */
2996 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2997 return -1;
2998 /* NUL terminate the field and advance p past the colon */
2999 *ep++ = '\0';
3000 if (*ep != '\0')
3001 *ep++ = '\0';
3002 fwd->arg = cp + 1;
3003 fwd->ispath = ispath;
3004 *p = ep;
3005 return 0;
3006 }
3007
3008 for (cp = *p; *cp != '\0'; cp++) {
3009 switch (*cp) {
3010 case '\\':
3011 memmove(cp, cp + 1, strlen(cp + 1) + 1);
3012 if (*cp == '\0')
3013 return -1;
3014 break;
3015 case '/':
3016 ispath = 1;
3017 break;
3018 case ':':
3019 *cp++ = '\0';
3020 goto done;
3021 }
3022 }
3023done:
3024 fwd->arg = *p;
3025 fwd->ispath = ispath;
3026 *p = cp;
3027 return 0;
3028}
3029
3030/*
3031 * parse_forward
3032 * parses a string containing a port forwarding specification of the form:
3033 * dynamicfwd == 0
3034 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3035 * listenpath:connectpath
3036 * dynamicfwd == 1
3037 * [listenhost:]listenport
3038 * returns number of arguments parsed or zero on error
3039 */
3040int
3041parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3042{
3043 struct fwdarg fwdargs[4];
3044 char *p, *cp;
3045 int i, err;
3046
3047 memset(fwd, 0, sizeof(*fwd));
3048 memset(fwdargs, 0, sizeof(fwdargs));
3049
3050 /*
3051 * We expand environment variables before checking if we think they're
3052 * paths so that if ${VAR} expands to a fully qualified path it is
3053 * treated as a path.
3054 */
3055 cp = p = dollar_expand(&err, fwdspec);
3056 if (p == NULL((void *)0) || err)
3057 return 0;
3058
3059 /* skip leading spaces */
3060 while (isspace((u_char)*cp))
3061 cp++;
3062
3063 for (i = 0; i < 4; ++i) {
3064 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3065 break;
3066 }
3067
3068 /* Check for trailing garbage */
3069 if (cp != NULL((void *)0) && *cp != '\0') {
3070 i = 0; /* failure */
3071 }
3072
3073 switch (i) {
3074 case 1:
3075 if (fwdargs[0].ispath) {
3076 fwd->listen_path = xstrdup(fwdargs[0].arg);
3077 fwd->listen_port = PORT_STREAMLOCAL-2;
3078 } else {
3079 fwd->listen_host = NULL((void *)0);
3080 fwd->listen_port = a2port(fwdargs[0].arg);
3081 }
3082 fwd->connect_host = xstrdup("socks");
3083 break;
3084
3085 case 2:
3086 if (fwdargs[0].ispath && fwdargs[1].ispath) {
3087 fwd->listen_path = xstrdup(fwdargs[0].arg);
3088 fwd->listen_port = PORT_STREAMLOCAL-2;
3089 fwd->connect_path = xstrdup(fwdargs[1].arg);
3090 fwd->connect_port = PORT_STREAMLOCAL-2;
3091 } else if (fwdargs[1].ispath) {
3092 fwd->listen_host = NULL((void *)0);
3093 fwd->listen_port = a2port(fwdargs[0].arg);
3094 fwd->connect_path = xstrdup(fwdargs[1].arg);
3095 fwd->connect_port = PORT_STREAMLOCAL-2;
3096 } else {
3097 fwd->listen_host = xstrdup(fwdargs[0].arg);
3098 fwd->listen_port = a2port(fwdargs[1].arg);
3099 fwd->connect_host = xstrdup("socks");
3100 }
3101 break;
3102
3103 case 3:
3104 if (fwdargs[0].ispath) {
3105 fwd->listen_path = xstrdup(fwdargs[0].arg);
3106 fwd->listen_port = PORT_STREAMLOCAL-2;
3107 fwd->connect_host = xstrdup(fwdargs[1].arg);
3108 fwd->connect_port = a2port(fwdargs[2].arg);
3109 } else if (fwdargs[2].ispath) {
3110 fwd->listen_host = xstrdup(fwdargs[0].arg);
3111 fwd->listen_port = a2port(fwdargs[1].arg);
3112 fwd->connect_path = xstrdup(fwdargs[2].arg);
3113 fwd->connect_port = PORT_STREAMLOCAL-2;
3114 } else {
3115 fwd->listen_host = NULL((void *)0);
3116 fwd->listen_port = a2port(fwdargs[0].arg);
3117 fwd->connect_host = xstrdup(fwdargs[1].arg);
3118 fwd->connect_port = a2port(fwdargs[2].arg);
3119 }
3120 break;
3121
3122 case 4:
3123 fwd->listen_host = xstrdup(fwdargs[0].arg);
3124 fwd->listen_port = a2port(fwdargs[1].arg);
3125 fwd->connect_host = xstrdup(fwdargs[2].arg);
3126 fwd->connect_port = a2port(fwdargs[3].arg);
3127 break;
3128 default:
3129 i = 0; /* failure */
3130 }
3131
3132 free(p);
3133
3134 if (dynamicfwd) {
3135 if (!(i == 1 || i == 2))
3136 goto fail_free;
3137 } else {
3138 if (!(i == 3 || i == 4)) {
3139 if (fwd->connect_path == NULL((void *)0) &&
3140 fwd->listen_path == NULL((void *)0))
3141 goto fail_free;
3142 }
3143 if (fwd->connect_port <= 0 && fwd->connect_path == NULL((void *)0))
3144 goto fail_free;
3145 }
3146
3147 if ((fwd->listen_port < 0 && fwd->listen_path == NULL((void *)0)) ||
3148 (!remotefwd && fwd->listen_port == 0))
3149 goto fail_free;
3150 if (fwd->connect_host != NULL((void *)0) &&
3151 strlen(fwd->connect_host) >= NI_MAXHOST256)
3152 goto fail_free;
3153 /*
3154 * XXX - if connecting to a remote socket, max sun len may not
3155 * match this host
3156 */
3157 if (fwd->connect_path != NULL((void *)0) &&
3158 strlen(fwd->connect_path) >= PATH_MAX_SUN(sizeof((struct sockaddr_un *)0)->sun_path))
3159 goto fail_free;
3160 if (fwd->listen_host != NULL((void *)0) &&
3161 strlen(fwd->listen_host) >= NI_MAXHOST256)
3162 goto fail_free;
3163 if (fwd->listen_path != NULL((void *)0) &&
3164 strlen(fwd->listen_path) >= PATH_MAX_SUN(sizeof((struct sockaddr_un *)0)->sun_path))
3165 goto fail_free;
3166
3167 return (i);
3168
3169 fail_free:
3170 free(fwd->connect_host);
3171 fwd->connect_host = NULL((void *)0);
3172 free(fwd->connect_path);
3173 fwd->connect_path = NULL((void *)0);
3174 free(fwd->listen_host);
3175 fwd->listen_host = NULL((void *)0);
3176 free(fwd->listen_path);
3177 fwd->listen_path = NULL((void *)0);
3178 return (0);
3179}
3180
3181int
3182parse_jump(const char *s, Options *o, int active)
3183{
3184 char *orig, *sdup, *cp;
3185 char *host = NULL((void *)0), *user = NULL((void *)0);
3186 int r, ret = -1, port = -1, first;
3187
3188 active &= o->proxy_command == NULL((void *)0) && o->jump_host == NULL((void *)0);
3189
3190 orig = sdup = xstrdup(s);
3191
3192 /* Remove comment and trailing whitespace */
3193 if ((cp = strchr(orig, '#')) != NULL((void *)0))
3194 *cp = '\0';
3195 rtrim(orig);
3196
3197 first = active;
3198 do {
3199 if (strcasecmp(s, "none") == 0)
3200 break;
3201 if ((cp = strrchr(sdup, ',')) == NULL((void *)0))
3202 cp = sdup; /* last */
3203 else
3204 *cp++ = '\0';
3205
3206 if (first) {
3207 /* First argument and configuration is active */
3208 r = parse_ssh_uri(cp, &user, &host, &port);
3209 if (r == -1 || (r == 1 &&
3210 parse_user_host_port(cp, &user, &host, &port) != 0))
3211 goto out;
3212 } else {
3213 /* Subsequent argument or inactive configuration */
3214 r = parse_ssh_uri(cp, NULL((void *)0), NULL((void *)0), NULL((void *)0));
3215 if (r == -1 || (r == 1 &&
3216 parse_user_host_port(cp, NULL((void *)0), NULL((void *)0), NULL((void *)0)) != 0))
3217 goto out;
3218 }
3219 first = 0; /* only check syntax for subsequent hosts */
3220 } while (cp != sdup);
3221 /* success */
3222 if (active) {
3223 if (strcasecmp(s, "none") == 0) {
3224 o->jump_host = xstrdup("none");
3225 o->jump_port = 0;
3226 } else {
3227 o->jump_user = user;
3228 o->jump_host = host;
3229 o->jump_port = port;
3230 o->proxy_command = xstrdup("none");
3231 user = host = NULL((void *)0);
3232 if ((cp = strrchr(s, ',')) != NULL((void *)0) && cp != s) {
3233 o->jump_extra = xstrdup(s);
3234 o->jump_extra[cp - s] = '\0';
3235 }
3236 }
3237 }
3238 ret = 0;
3239 out:
3240 free(orig);
3241 free(user);
3242 free(host);
3243 return ret;
3244}
3245
3246int
3247parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3248{
3249 char *user = NULL((void *)0), *host = NULL((void *)0), *path = NULL((void *)0);
3250 int r, port;
3251
3252 r = parse_uri("ssh", uri, &user, &host, &port, &path);
3253 if (r == 0 && path != NULL((void *)0))
3254 r = -1; /* path not allowed */
3255 if (r == 0) {
3256 if (userp != NULL((void *)0)) {
3257 *userp = user;
3258 user = NULL((void *)0);
3259 }
3260 if (hostp != NULL((void *)0)) {
3261 *hostp = host;
3262 host = NULL((void *)0);
3263 }
3264 if (portp != NULL((void *)0))
3265 *portp = port;
3266 }
3267 free(user);
3268 free(host);
3269 free(path);
3270 return r;
3271}
3272
3273/* XXX the following is a near-vebatim copy from servconf.c; refactor */
3274static const char *
3275fmt_multistate_int(int val, const struct multistate *m)
3276{
3277 u_int i;
3278
3279 for (i = 0; m[i].key != NULL((void *)0); i++) {
3280 if (m[i].value == val)
3281 return m[i].key;
3282 }
3283 return "UNKNOWN";
3284}
3285
3286static const char *
3287fmt_intarg(OpCodes code, int val)
3288{
3289 if (val == -1)
3290 return "unset";
3291 switch (code) {
3292 case oAddressFamily:
3293 return fmt_multistate_int(val, multistate_addressfamily);
3294 case oVerifyHostKeyDNS:
3295 case oUpdateHostkeys:
3296 return fmt_multistate_int(val, multistate_yesnoask);
3297 case oStrictHostKeyChecking:
3298 return fmt_multistate_int(val, multistate_strict_hostkey);
3299 case oControlMaster:
3300 return fmt_multistate_int(val, multistate_controlmaster);
3301 case oTunnel:
3302 return fmt_multistate_int(val, multistate_tunnel);
3303 case oRequestTTY:
3304 return fmt_multistate_int(val, multistate_requesttty);
3305 case oSessionType:
3306 return fmt_multistate_int(val, multistate_sessiontype);
3307 case oCanonicalizeHostname:
3308 return fmt_multistate_int(val, multistate_canonicalizehostname);
3309 case oAddKeysToAgent:
3310 return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3311 case oPubkeyAuthentication:
3312 return fmt_multistate_int(val, multistate_pubkey_auth);
3313 case oFingerprintHash:
3314 return ssh_digest_alg_name(val);
3315 default:
3316 switch (val) {
3317 case 0:
3318 return "no";
3319 case 1:
3320 return "yes";
3321 default:
3322 return "UNKNOWN";
3323 }
3324 }
3325}
3326
3327static const char *
3328lookup_opcode_name(OpCodes code)
3329{
3330 u_int i;
3331
3332 for (i = 0; keywords[i].name != NULL((void *)0); i++)
3333 if (keywords[i].opcode == code)
3334 return(keywords[i].name);
3335 return "UNKNOWN";
3336}
3337
3338static void
3339dump_cfg_int(OpCodes code, int val)
3340{
3341 if (code == oObscureKeystrokeTiming) {
3342 if (val == 0) {
3343 printf("%s no\n", lookup_opcode_name(code));
3344 return;
3345 } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS20) {
3346 printf("%s yes\n", lookup_opcode_name(code));
3347 return;
3348 }
3349 /* FALLTHROUGH */
3350 }
3351 printf("%s %d\n", lookup_opcode_name(code), val);
3352}
3353
3354static void
3355dump_cfg_fmtint(OpCodes code, int val)
3356{
3357 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3358}
3359
3360static void
3361dump_cfg_string(OpCodes code, const char *val)
3362{
3363 if (val == NULL((void *)0))
3364 return;
3365 printf("%s %s\n", lookup_opcode_name(code), val);
3366}
3367
3368static void
3369dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3370{
3371 u_int i;
3372
3373 for (i = 0; i < count; i++)
3374 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3375}
3376
3377static void
3378dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3379{
3380 u_int i;
3381
3382 printf("%s", lookup_opcode_name(code));
3383 if (count == 0)
3384 printf(" none");
3385 for (i = 0; i < count; i++)
3386 printf(" %s", vals[i]);
3387 printf("\n");
3388}
3389
3390static void
3391dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3392{
3393 const struct Forward *fwd;
3394 u_int i;
3395
3396 /* oDynamicForward */
3397 for (i = 0; i < count; i++) {
3398 fwd = &fwds[i];
3399 if (code == oDynamicForward && fwd->connect_host != NULL((void *)0) &&
3400 strcmp(fwd->connect_host, "socks") != 0)
3401 continue;
3402 if (code == oLocalForward && fwd->connect_host != NULL((void *)0) &&
3403 strcmp(fwd->connect_host, "socks") == 0)
3404 continue;
3405 printf("%s", lookup_opcode_name(code));
3406 if (fwd->listen_port == PORT_STREAMLOCAL-2)
3407 printf(" %s", fwd->listen_path);
3408 else if (fwd->listen_host == NULL((void *)0))
3409 printf(" %d", fwd->listen_port);
3410 else {
3411 printf(" [%s]:%d",
3412 fwd->listen_host, fwd->listen_port);
3413 }
3414 if (code != oDynamicForward) {
3415 if (fwd->connect_port == PORT_STREAMLOCAL-2)
3416 printf(" %s", fwd->connect_path);
3417 else if (fwd->connect_host == NULL((void *)0))
3418 printf(" %d", fwd->connect_port);
3419 else {
3420 printf(" [%s]:%d",
3421 fwd->connect_host, fwd->connect_port);
3422 }
3423 }
3424 printf("\n");
3425 }
3426}
3427
3428void
3429dump_client_config(Options *o, const char *host)
3430{
3431 int i, r;
3432 char buf[8], *all_key;
3433
3434 /*
3435 * Expand HostKeyAlgorithms name lists. This isn't handled in
3436 * fill_default_options() like the other algorithm lists because
3437 * the host key algorithms are by default dynamically chosen based
3438 * on the host's keys found in known_hosts.
3439 */
3440 all_key = sshkey_alg_list(0, 0, 1, ',');
3441 if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3442 all_key)) != 0)
3443 fatal_fr(r, "expand HostKeyAlgorithms")sshfatal("/usr/src/usr.bin/ssh/ssh/../readconf.c", __func__, 3443
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "expand HostKeyAlgorithms"
)
;
3444 free(all_key);
3445
3446 /* Most interesting options first: user, host, port */
3447 dump_cfg_string(oHost, o->host_arg);
3448 dump_cfg_string(oUser, o->user);
3449 dump_cfg_string(oHostname, host);
3450 dump_cfg_int(oPort, o->port);
3451
3452 /* Flag options */
3453 dump_cfg_fmtint(oAddressFamily, o->address_family);
3454 dump_cfg_fmtint(oBatchMode, o->batch_mode);
3455 dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3456 dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3457 dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3458 dump_cfg_fmtint(oCompression, o->compression);
3459 dump_cfg_fmtint(oControlMaster, o->control_master);
3460 dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3461 dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3462 dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3463 dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3464 dump_cfg_fmtint(oForwardX11, o->forward_x11);
3465 dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3466 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3467#ifdef GSSAPI
3468 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3469 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3470#endif /* GSSAPI */
3471 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3472 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3473 dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3474 dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3475 dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3476 dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3477 dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3478 dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3479 dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3480 dump_cfg_fmtint(oRequestTTY, o->request_tty);
3481 dump_cfg_fmtint(oSessionType, o->session_type);
3482 dump_cfg_fmtint(oStdinNull, o->stdin_null);
3483 dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3484 dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3485 dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3486 dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3487 dump_cfg_fmtint(oTunnel, o->tun_open);
3488 dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3489 dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3490 dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3491 dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3492
3493 /* Integer options */
3494 dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3495 dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3496 dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3497 dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3498 dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3499 dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3500 dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3501 dump_cfg_int(oObscureKeystrokeTiming,
3502 o->obscure_keystroke_timing_interval);
3503
3504 /* String options */
3505 dump_cfg_string(oBindAddress, o->bind_address);
3506 dump_cfg_string(oBindInterface, o->bind_interface);
3507 dump_cfg_string(oCiphers, o->ciphers);
3508 dump_cfg_string(oControlPath, o->control_path);
3509 dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3510 dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3511 dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3512 dump_cfg_string(oIdentityAgent, o->identity_agent);
3513 dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3514 dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3515 dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3516 dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3517 dump_cfg_string(oLocalCommand, o->local_command);
3518 dump_cfg_string(oRemoteCommand, o->remote_command);
3519 dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3520 dump_cfg_string(oMacs, o->macs);
3521#ifdef ENABLE_PKCS111
3522 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3523#endif
3524 dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3525 dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3526 dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3527 dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3528 dump_cfg_string(oXAuthLocation, o->xauth_location);
3529 dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3530 dump_cfg_string(oTag, o->tag);
3531
3532 /* Forwards */
3533 dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3534 dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3535 dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3536
3537 /* String array options */
3538 dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3539 dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3540 dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3541 dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3542 dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3543 dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3544 dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3545 dump_cfg_strarray_oneline(oLogVerbose,
3546 o->num_log_verbose, o->log_verbose);
3547 dump_cfg_strarray_oneline(oChannelTimeout,
3548 o->num_channel_timeouts, o->channel_timeouts);
3549
3550 /* Special cases */
3551
3552 /* PermitRemoteOpen */
3553 if (o->num_permitted_remote_opens == 0)
3554 printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3555 else
3556 dump_cfg_strarray_oneline(oPermitRemoteOpen,
3557 o->num_permitted_remote_opens, o->permitted_remote_opens);
3558
3559 /* AddKeysToAgent */
3560 if (o->add_keys_to_agent_lifespan <= 0)
3561 dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3562 else {
3563 printf("addkeystoagent%s %d\n",
3564 o->add_keys_to_agent == 3 ? " confirm" : "",
3565 o->add_keys_to_agent_lifespan);
3566 }
3567
3568 /* oForwardAgent */
3569 if (o->forward_agent_sock_path == NULL((void *)0))
3570 dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3571 else
3572 dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3573
3574 /* oConnectTimeout */
3575 if (o->connection_timeout == -1)
3576 printf("connecttimeout none\n");
3577 else
3578 dump_cfg_int(oConnectTimeout, o->connection_timeout);
3579
3580 /* oTunnelDevice */
3581 printf("tunneldevice");
3582 if (o->tun_local == SSH_TUNID_ANY0x7fffffff)
3583 printf(" any");
3584 else
3585 printf(" %d", o->tun_local);
3586 if (o->tun_remote == SSH_TUNID_ANY0x7fffffff)
3587 printf(":any");
3588 else
3589 printf(":%d", o->tun_remote);
3590 printf("\n");
3591
3592 /* oCanonicalizePermittedCNAMEs */
3593 printf("canonicalizePermittedcnames");
3594 if (o->num_permitted_cnames == 0)
3595 printf(" none");
3596 for (i = 0; i < o->num_permitted_cnames; i++) {
3597 printf(" %s:%s", o->permitted_cnames[i].source_list,
3598 o->permitted_cnames[i].target_list);
3599 }
3600 printf("\n");
3601
3602 /* oControlPersist */
3603 if (o->control_persist == 0 || o->control_persist_timeout == 0)
3604 dump_cfg_fmtint(oControlPersist, o->control_persist);
3605 else
3606 dump_cfg_int(oControlPersist, o->control_persist_timeout);
3607
3608 /* oEscapeChar */
3609 if (o->escape_char == SSH_ESCAPECHAR_NONE-2)
3610 printf("escapechar none\n");
3611 else {
3612 vis(buf, o->escape_char, VIS_WHITE(0x04 | 0x08 | 0x10), 0);
3613 printf("escapechar %s\n", buf);
3614 }
3615
3616 /* oIPQoS */
3617 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3618 printf("%s\n", iptos2str(o->ip_qos_bulk));
3619
3620 /* oRekeyLimit */
3621 printf("rekeylimit %llu %d\n",
3622 (unsigned long long)o->rekey_limit, o->rekey_interval);
3623
3624 /* oStreamLocalBindMask */
3625 printf("streamlocalbindmask 0%o\n",
3626 o->fwd_opts.streamlocal_bind_mask);
3627
3628 /* oLogFacility */
3629 printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3630
3631 /* oProxyCommand / oProxyJump */
3632 if (o->jump_host == NULL((void *)0))
3633 dump_cfg_string(oProxyCommand, o->proxy_command);
3634 else {
3635 /* Check for numeric addresses */
3636 i = strchr(o->jump_host, ':') != NULL((void *)0) ||
3637 strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3638 snprintf(buf, sizeof(buf), "%d", o->jump_port);
3639 printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3640 /* optional additional jump spec */
3641 o->jump_extra == NULL((void *)0) ? "" : o->jump_extra,
3642 o->jump_extra == NULL((void *)0) ? "" : ",",
3643 /* optional user */
3644 o->jump_user == NULL((void *)0) ? "" : o->jump_user,
3645 o->jump_user == NULL((void *)0) ? "" : "@",
3646 /* opening [ if hostname is numeric */
3647 i ? "[" : "",
3648 /* mandatory hostname */
3649 o->jump_host,
3650 /* closing ] if hostname is numeric */
3651 i ? "]" : "",
3652 /* optional port number */
3653 o->jump_port <= 0 ? "" : ":",
3654 o->jump_port <= 0 ? "" : buf);
3655 }
3656}