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