diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | canohost.c | 13 | ||||
-rw-r--r-- | misc.c | 10 | ||||
-rw-r--r-- | misc.h | 4 | ||||
-rw-r--r-- | readconf.c | 199 | ||||
-rw-r--r-- | sftp-server.c | 25 | ||||
-rw-r--r-- | ssh.c | 28 |
7 files changed, 149 insertions, 139 deletions
@@ -37,6 +37,15 @@ | |||
37 | [readconf.c readconf.h ssh-keysign.c ssh.c ssh_config.5] | 37 | [readconf.c readconf.h ssh-keysign.c ssh.c ssh_config.5] |
38 | add a "Match" keyword to ssh_config that allows matching on hostname, | 38 | add a "Match" keyword to ssh_config that allows matching on hostname, |
39 | user and result of arbitrary commands. "nice work" markus@ | 39 | user and result of arbitrary commands. "nice work" markus@ |
40 | - djm@cvs.openbsd.org 2013/10/14 23:28:23 | ||
41 | [canohost.c misc.c misc.h readconf.c sftp-server.c ssh.c] | ||
42 | refactor client config code a little: | ||
43 | add multistate option partsing to readconf.c, similar to servconf.c's | ||
44 | existing code. | ||
45 | move checking of options that accept "none" as an argument to readconf.c | ||
46 | add a lowercase() function and use it instead of explicit tolower() in | ||
47 | loops | ||
48 | part of a larger diff that was ok markus@ | ||
40 | 49 | ||
41 | 20131010 | 50 | 20131010 |
42 | - (dtucker) OpenBSD CVS Sync | 51 | - (dtucker) OpenBSD CVS Sync |
diff --git a/canohost.c b/canohost.c index 69e8e6f6d..a8eeb0e35 100644 --- a/canohost.c +++ b/canohost.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: canohost.c,v 1.67 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: canohost.c,v 1.68 2013/10/14 23:28:22 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -48,7 +48,6 @@ static char * | |||
48 | get_remote_hostname(int sock, int use_dns) | 48 | get_remote_hostname(int sock, int use_dns) |
49 | { | 49 | { |
50 | struct sockaddr_storage from; | 50 | struct sockaddr_storage from; |
51 | int i; | ||
52 | socklen_t fromlen; | 51 | socklen_t fromlen; |
53 | struct addrinfo hints, *ai, *aitop; | 52 | struct addrinfo hints, *ai, *aitop; |
54 | char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; | 53 | char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; |
@@ -99,13 +98,9 @@ get_remote_hostname(int sock, int use_dns) | |||
99 | return xstrdup(ntop); | 98 | return xstrdup(ntop); |
100 | } | 99 | } |
101 | 100 | ||
102 | /* | 101 | /* Names are stores in lowercase. */ |
103 | * Convert it to all lowercase (which is expected by the rest | 102 | lowercase(name); |
104 | * of this software). | 103 | |
105 | */ | ||
106 | for (i = 0; name[i]; i++) | ||
107 | if (isupper(name[i])) | ||
108 | name[i] = (char)tolower(name[i]); | ||
109 | /* | 104 | /* |
110 | * Map it back to an IP address and check that the given | 105 | * Map it back to an IP address and check that the given |
111 | * address actually is an address of this host. This is | 106 | * address actually is an address of this host. This is |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.91 2013/07/12 00:43:50 djm Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.92 2013/10/14 23:28:23 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -43,6 +43,7 @@ | |||
43 | #include <netinet/ip.h> | 43 | #include <netinet/ip.h> |
44 | #include <netinet/tcp.h> | 44 | #include <netinet/tcp.h> |
45 | 45 | ||
46 | #include <ctype.h> | ||
46 | #include <errno.h> | 47 | #include <errno.h> |
47 | #include <fcntl.h> | 48 | #include <fcntl.h> |
48 | #include <netdb.h> | 49 | #include <netdb.h> |
@@ -1017,6 +1018,13 @@ iptos2str(int iptos) | |||
1017 | snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); | 1018 | snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); |
1018 | return iptos_str; | 1019 | return iptos_str; |
1019 | } | 1020 | } |
1021 | |||
1022 | void | ||
1023 | lowercase(char *s) | ||
1024 | { | ||
1025 | for (; *s; s++) | ||
1026 | *s = tolower((u_char)*s); | ||
1027 | } | ||
1020 | void | 1028 | void |
1021 | sock_set_v6only(int s) | 1029 | sock_set_v6only(int s) |
1022 | { | 1030 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.h,v 1.49 2013/06/01 13:15:52 dtucker Exp $ */ | 1 | /* $OpenBSD: misc.h,v 1.50 2013/10/14 23:28:23 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -36,6 +36,8 @@ void sanitise_stdfd(void); | |||
36 | void ms_subtract_diff(struct timeval *, int *); | 36 | void ms_subtract_diff(struct timeval *, int *); |
37 | void ms_to_timeval(struct timeval *, int); | 37 | void ms_to_timeval(struct timeval *, int); |
38 | time_t monotime(void); | 38 | time_t monotime(void); |
39 | void lowercase(char *s); | ||
40 | |||
39 | void sock_set_v6only(int); | 41 | void sock_set_v6only(int); |
40 | 42 | ||
41 | struct passwd *pwcopy(struct passwd *); | 43 | struct passwd *pwcopy(struct passwd *); |
diff --git a/readconf.c b/readconf.c index f7b912ef6..9340effd0 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.206 2013/10/14 22:22:02 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.207 2013/10/14 23:28:23 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -555,6 +555,61 @@ parse_token(const char *cp, const char *filename, int linenum, | |||
555 | return oBadOption; | 555 | return oBadOption; |
556 | } | 556 | } |
557 | 557 | ||
558 | /* Multistate option parsing */ | ||
559 | struct multistate { | ||
560 | char *key; | ||
561 | int value; | ||
562 | }; | ||
563 | static const struct multistate multistate_flag[] = { | ||
564 | { "true", 1 }, | ||
565 | { "false", 0 }, | ||
566 | { "yes", 1 }, | ||
567 | { "no", 0 }, | ||
568 | { NULL, -1 } | ||
569 | }; | ||
570 | static const struct multistate multistate_yesnoask[] = { | ||
571 | { "true", 1 }, | ||
572 | { "false", 0 }, | ||
573 | { "yes", 1 }, | ||
574 | { "no", 0 }, | ||
575 | { "ask", 2 }, | ||
576 | { NULL, -1 } | ||
577 | }; | ||
578 | static const struct multistate multistate_addressfamily[] = { | ||
579 | { "inet", AF_INET }, | ||
580 | { "inet6", AF_INET6 }, | ||
581 | { "any", AF_UNSPEC }, | ||
582 | { NULL, -1 } | ||
583 | }; | ||
584 | static const struct multistate multistate_controlmaster[] = { | ||
585 | { "true", SSHCTL_MASTER_YES }, | ||
586 | { "yes", SSHCTL_MASTER_YES }, | ||
587 | { "false", SSHCTL_MASTER_NO }, | ||
588 | { "no", SSHCTL_MASTER_NO }, | ||
589 | { "auto", SSHCTL_MASTER_AUTO }, | ||
590 | { "ask", SSHCTL_MASTER_ASK }, | ||
591 | { "autoask", SSHCTL_MASTER_AUTO_ASK }, | ||
592 | { NULL, -1 } | ||
593 | }; | ||
594 | static const struct multistate multistate_tunnel[] = { | ||
595 | { "ethernet", SSH_TUNMODE_ETHERNET }, | ||
596 | { "point-to-point", SSH_TUNMODE_POINTOPOINT }, | ||
597 | { "true", SSH_TUNMODE_DEFAULT }, | ||
598 | { "yes", SSH_TUNMODE_DEFAULT }, | ||
599 | { "false", SSH_TUNMODE_NO }, | ||
600 | { "no", SSH_TUNMODE_NO }, | ||
601 | { NULL, -1 } | ||
602 | }; | ||
603 | static const struct multistate multistate_requesttty[] = { | ||
604 | { "true", REQUEST_TTY_YES }, | ||
605 | { "yes", REQUEST_TTY_YES }, | ||
606 | { "false", REQUEST_TTY_NO }, | ||
607 | { "no", REQUEST_TTY_NO }, | ||
608 | { "force", REQUEST_TTY_FORCE }, | ||
609 | { "auto", REQUEST_TTY_AUTO }, | ||
610 | { NULL, -1 } | ||
611 | }; | ||
612 | |||
558 | /* | 613 | /* |
559 | * Processes a single option line as used in the configuration files. This | 614 | * Processes a single option line as used in the configuration files. This |
560 | * only sets those values that have not already been set. | 615 | * only sets those values that have not already been set. |
@@ -572,6 +627,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
572 | long long val64; | 627 | long long val64; |
573 | size_t len; | 628 | size_t len; |
574 | Forward fwd; | 629 | Forward fwd; |
630 | const struct multistate *multistate_ptr; | ||
575 | 631 | ||
576 | if (activep == NULL) { /* We are processing a command line directive */ | 632 | if (activep == NULL) { /* We are processing a command line directive */ |
577 | cmdline = 1; | 633 | cmdline = 1; |
@@ -595,8 +651,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host, | |||
595 | if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') | 651 | if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') |
596 | return 0; | 652 | return 0; |
597 | /* Match lowercase keyword */ | 653 | /* Match lowercase keyword */ |
598 | for (i = 0; i < strlen(keyword); i++) | 654 | lowercase(keyword); |
599 | keyword[i] = tolower(keyword[i]); | ||
600 | 655 | ||
601 | opcode = parse_token(keyword, filename, linenum, | 656 | opcode = parse_token(keyword, filename, linenum, |
602 | options->ignored_unknown); | 657 | options->ignored_unknown); |
@@ -626,17 +681,23 @@ parse_time: | |||
626 | 681 | ||
627 | case oForwardAgent: | 682 | case oForwardAgent: |
628 | intptr = &options->forward_agent; | 683 | intptr = &options->forward_agent; |
629 | parse_flag: | 684 | parse_flag: |
685 | multistate_ptr = multistate_flag; | ||
686 | parse_multistate: | ||
630 | arg = strdelim(&s); | 687 | arg = strdelim(&s); |
631 | if (!arg || *arg == '\0') | 688 | if (!arg || *arg == '\0') |
632 | fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); | 689 | fatal("%s line %d: missing argument.", |
633 | value = 0; /* To avoid compiler warning... */ | 690 | filename, linenum); |
634 | if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) | 691 | value = -1; |
635 | value = 1; | 692 | for (i = 0; multistate_ptr[i].key != NULL; i++) { |
636 | else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) | 693 | if (strcasecmp(arg, multistate_ptr[i].key) == 0) { |
637 | value = 0; | 694 | value = multistate_ptr[i].value; |
638 | else | 695 | break; |
639 | fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); | 696 | } |
697 | } | ||
698 | if (value == -1) | ||
699 | fatal("%s line %d: unsupported option \"%s\".", | ||
700 | filename, linenum, arg); | ||
640 | if (*activep && *intptr == -1) | 701 | if (*activep && *intptr == -1) |
641 | *intptr = value; | 702 | *intptr = value; |
642 | break; | 703 | break; |
@@ -719,27 +780,13 @@ parse_flag: | |||
719 | 780 | ||
720 | case oVerifyHostKeyDNS: | 781 | case oVerifyHostKeyDNS: |
721 | intptr = &options->verify_host_key_dns; | 782 | intptr = &options->verify_host_key_dns; |
722 | goto parse_yesnoask; | 783 | multistate_ptr = multistate_yesnoask; |
784 | goto parse_multistate; | ||
723 | 785 | ||
724 | case oStrictHostKeyChecking: | 786 | case oStrictHostKeyChecking: |
725 | intptr = &options->strict_host_key_checking; | 787 | intptr = &options->strict_host_key_checking; |
726 | parse_yesnoask: | 788 | multistate_ptr = multistate_yesnoask; |
727 | arg = strdelim(&s); | 789 | goto parse_multistate; |
728 | if (!arg || *arg == '\0') | ||
729 | fatal("%.200s line %d: Missing yes/no/ask argument.", | ||
730 | filename, linenum); | ||
731 | value = 0; /* To avoid compiler warning... */ | ||
732 | if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) | ||
733 | value = 1; | ||
734 | else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) | ||
735 | value = 0; | ||
736 | else if (strcmp(arg, "ask") == 0) | ||
737 | value = 2; | ||
738 | else | ||
739 | fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); | ||
740 | if (*activep && *intptr == -1) | ||
741 | *intptr = value; | ||
742 | break; | ||
743 | 790 | ||
744 | case oCompression: | 791 | case oCompression: |
745 | intptr = &options->compression; | 792 | intptr = &options->compression; |
@@ -1080,22 +1127,9 @@ parse_int: | |||
1080 | break; | 1127 | break; |
1081 | 1128 | ||
1082 | case oAddressFamily: | 1129 | case oAddressFamily: |
1083 | arg = strdelim(&s); | ||
1084 | if (!arg || *arg == '\0') | ||
1085 | fatal("%s line %d: missing address family.", | ||
1086 | filename, linenum); | ||
1087 | intptr = &options->address_family; | 1130 | intptr = &options->address_family; |
1088 | if (strcasecmp(arg, "inet") == 0) | 1131 | multistate_ptr = multistate_addressfamily; |
1089 | value = AF_INET; | 1132 | goto parse_multistate; |
1090 | else if (strcasecmp(arg, "inet6") == 0) | ||
1091 | value = AF_INET6; | ||
1092 | else if (strcasecmp(arg, "any") == 0) | ||
1093 | value = AF_UNSPEC; | ||
1094 | else | ||
1095 | fatal("Unsupported AddressFamily \"%s\"", arg); | ||
1096 | if (*activep && *intptr == -1) | ||
1097 | *intptr = value; | ||
1098 | break; | ||
1099 | 1133 | ||
1100 | case oEnableSSHKeysign: | 1134 | case oEnableSSHKeysign: |
1101 | intptr = &options->enable_ssh_keysign; | 1135 | intptr = &options->enable_ssh_keysign; |
@@ -1134,27 +1168,8 @@ parse_int: | |||
1134 | 1168 | ||
1135 | case oControlMaster: | 1169 | case oControlMaster: |
1136 | intptr = &options->control_master; | 1170 | intptr = &options->control_master; |
1137 | arg = strdelim(&s); | 1171 | multistate_ptr = multistate_controlmaster; |
1138 | if (!arg || *arg == '\0') | 1172 | goto parse_multistate; |
1139 | fatal("%.200s line %d: Missing ControlMaster argument.", | ||
1140 | filename, linenum); | ||
1141 | value = 0; /* To avoid compiler warning... */ | ||
1142 | if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) | ||
1143 | value = SSHCTL_MASTER_YES; | ||
1144 | else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) | ||
1145 | value = SSHCTL_MASTER_NO; | ||
1146 | else if (strcmp(arg, "auto") == 0) | ||
1147 | value = SSHCTL_MASTER_AUTO; | ||
1148 | else if (strcmp(arg, "ask") == 0) | ||
1149 | value = SSHCTL_MASTER_ASK; | ||
1150 | else if (strcmp(arg, "autoask") == 0) | ||
1151 | value = SSHCTL_MASTER_AUTO_ASK; | ||
1152 | else | ||
1153 | fatal("%.200s line %d: Bad ControlMaster argument.", | ||
1154 | filename, linenum); | ||
1155 | if (*activep && *intptr == -1) | ||
1156 | *intptr = value; | ||
1157 | break; | ||
1158 | 1173 | ||
1159 | case oControlPersist: | 1174 | case oControlPersist: |
1160 | /* no/false/yes/true, or a time spec */ | 1175 | /* no/false/yes/true, or a time spec */ |
@@ -1186,25 +1201,8 @@ parse_int: | |||
1186 | 1201 | ||
1187 | case oTunnel: | 1202 | case oTunnel: |
1188 | intptr = &options->tun_open; | 1203 | intptr = &options->tun_open; |
1189 | arg = strdelim(&s); | 1204 | multistate_ptr = multistate_tunnel; |
1190 | if (!arg || *arg == '\0') | 1205 | goto parse_multistate; |
1191 | fatal("%s line %d: Missing yes/point-to-point/" | ||
1192 | "ethernet/no argument.", filename, linenum); | ||
1193 | value = 0; /* silence compiler */ | ||
1194 | if (strcasecmp(arg, "ethernet") == 0) | ||
1195 | value = SSH_TUNMODE_ETHERNET; | ||
1196 | else if (strcasecmp(arg, "point-to-point") == 0) | ||
1197 | value = SSH_TUNMODE_POINTOPOINT; | ||
1198 | else if (strcasecmp(arg, "yes") == 0) | ||
1199 | value = SSH_TUNMODE_DEFAULT; | ||
1200 | else if (strcasecmp(arg, "no") == 0) | ||
1201 | value = SSH_TUNMODE_NO; | ||
1202 | else | ||
1203 | fatal("%s line %d: Bad yes/point-to-point/ethernet/" | ||
1204 | "no argument: %s", filename, linenum, arg); | ||
1205 | if (*activep) | ||
1206 | *intptr = value; | ||
1207 | break; | ||
1208 | 1206 | ||
1209 | case oTunnelDevice: | 1207 | case oTunnelDevice: |
1210 | arg = strdelim(&s); | 1208 | arg = strdelim(&s); |
@@ -1253,24 +1251,9 @@ parse_int: | |||
1253 | goto parse_flag; | 1251 | goto parse_flag; |
1254 | 1252 | ||
1255 | case oRequestTTY: | 1253 | case oRequestTTY: |
1256 | arg = strdelim(&s); | ||
1257 | if (!arg || *arg == '\0') | ||
1258 | fatal("%s line %d: missing argument.", | ||
1259 | filename, linenum); | ||
1260 | intptr = &options->request_tty; | 1254 | intptr = &options->request_tty; |
1261 | if (strcasecmp(arg, "yes") == 0) | 1255 | multistate_ptr = multistate_requesttty; |
1262 | value = REQUEST_TTY_YES; | 1256 | goto parse_multistate; |
1263 | else if (strcasecmp(arg, "no") == 0) | ||
1264 | value = REQUEST_TTY_NO; | ||
1265 | else if (strcasecmp(arg, "force") == 0) | ||
1266 | value = REQUEST_TTY_FORCE; | ||
1267 | else if (strcasecmp(arg, "auto") == 0) | ||
1268 | value = REQUEST_TTY_AUTO; | ||
1269 | else | ||
1270 | fatal("Unsupported RequestTTY \"%s\"", arg); | ||
1271 | if (*activep && *intptr == -1) | ||
1272 | *intptr = value; | ||
1273 | break; | ||
1274 | 1257 | ||
1275 | case oIgnoreUnknown: | 1258 | case oIgnoreUnknown: |
1276 | charptr = &options->ignored_unknown; | 1259 | charptr = &options->ignored_unknown; |
@@ -1596,8 +1579,16 @@ fill_default_options(Options * options) | |||
1596 | options->request_tty = REQUEST_TTY_AUTO; | 1579 | options->request_tty = REQUEST_TTY_AUTO; |
1597 | if (options->proxy_use_fdpass == -1) | 1580 | if (options->proxy_use_fdpass == -1) |
1598 | options->proxy_use_fdpass = 0; | 1581 | options->proxy_use_fdpass = 0; |
1599 | /* options->local_command should not be set by default */ | 1582 | #define CLEAR_ON_NONE(v) \ |
1600 | /* options->proxy_command should not be set by default */ | 1583 | do { \ |
1584 | if (v != NULL && strcasecmp(v, "none") == 0) { \ | ||
1585 | free(v); \ | ||
1586 | v = NULL; \ | ||
1587 | } \ | ||
1588 | } while(0) | ||
1589 | CLEAR_ON_NONE(options->local_command); | ||
1590 | CLEAR_ON_NONE(options->proxy_command); | ||
1591 | CLEAR_ON_NONE(options->control_path); | ||
1601 | /* options->user will be set in the main program if appropriate */ | 1592 | /* options->user will be set in the main program if appropriate */ |
1602 | /* options->hostname will be set in the main program if appropriate */ | 1593 | /* options->hostname will be set in the main program if appropriate */ |
1603 | /* options->host_key_alias should not be set by default */ | 1594 | /* options->host_key_alias should not be set by default */ |
diff --git a/sftp-server.c b/sftp-server.c index b62bd3510..3056c454e 100644 --- a/sftp-server.c +++ b/sftp-server.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-server.c,v 1.100 2013/10/14 14:18:56 jmc Exp $ */ | 1 | /* $OpenBSD: sftp-server.c,v 1.101 2013/10/14 23:28:23 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -230,6 +230,8 @@ flags_from_portable(int pflags) | |||
230 | } else if (pflags & SSH2_FXF_WRITE) { | 230 | } else if (pflags & SSH2_FXF_WRITE) { |
231 | flags = O_WRONLY; | 231 | flags = O_WRONLY; |
232 | } | 232 | } |
233 | if (pflags & SSH2_FXF_APPEND) | ||
234 | flags |= O_APPEND; | ||
233 | if (pflags & SSH2_FXF_CREAT) | 235 | if (pflags & SSH2_FXF_CREAT) |
234 | flags |= O_CREAT; | 236 | flags |= O_CREAT; |
235 | if (pflags & SSH2_FXF_TRUNC) | 237 | if (pflags & SSH2_FXF_TRUNC) |
@@ -256,6 +258,8 @@ string_from_portable(int pflags) | |||
256 | PAPPEND("READ") | 258 | PAPPEND("READ") |
257 | if (pflags & SSH2_FXF_WRITE) | 259 | if (pflags & SSH2_FXF_WRITE) |
258 | PAPPEND("WRITE") | 260 | PAPPEND("WRITE") |
261 | if (pflags & SSH2_FXF_APPEND) | ||
262 | PAPPEND("APPEND") | ||
259 | if (pflags & SSH2_FXF_CREAT) | 263 | if (pflags & SSH2_FXF_CREAT) |
260 | PAPPEND("CREATE") | 264 | PAPPEND("CREATE") |
261 | if (pflags & SSH2_FXF_TRUNC) | 265 | if (pflags & SSH2_FXF_TRUNC) |
@@ -279,6 +283,7 @@ struct Handle { | |||
279 | int use; | 283 | int use; |
280 | DIR *dirp; | 284 | DIR *dirp; |
281 | int fd; | 285 | int fd; |
286 | int flags; | ||
282 | char *name; | 287 | char *name; |
283 | u_int64_t bytes_read, bytes_write; | 288 | u_int64_t bytes_read, bytes_write; |
284 | int next_unused; | 289 | int next_unused; |
@@ -302,7 +307,7 @@ static void handle_unused(int i) | |||
302 | } | 307 | } |
303 | 308 | ||
304 | static int | 309 | static int |
305 | handle_new(int use, const char *name, int fd, DIR *dirp) | 310 | handle_new(int use, const char *name, int fd, int flags, DIR *dirp) |
306 | { | 311 | { |
307 | int i; | 312 | int i; |
308 | 313 | ||
@@ -320,6 +325,7 @@ handle_new(int use, const char *name, int fd, DIR *dirp) | |||
320 | handles[i].use = use; | 325 | handles[i].use = use; |
321 | handles[i].dirp = dirp; | 326 | handles[i].dirp = dirp; |
322 | handles[i].fd = fd; | 327 | handles[i].fd = fd; |
328 | handles[i].flags = flags; | ||
323 | handles[i].name = xstrdup(name); | 329 | handles[i].name = xstrdup(name); |
324 | handles[i].bytes_read = handles[i].bytes_write = 0; | 330 | handles[i].bytes_read = handles[i].bytes_write = 0; |
325 | 331 | ||
@@ -382,6 +388,14 @@ handle_to_fd(int handle) | |||
382 | return -1; | 388 | return -1; |
383 | } | 389 | } |
384 | 390 | ||
391 | static int | ||
392 | handle_to_flags(int handle) | ||
393 | { | ||
394 | if (handle_is_ok(handle, HANDLE_FILE)) | ||
395 | return handles[handle].flags; | ||
396 | return 0; | ||
397 | } | ||
398 | |||
385 | static void | 399 | static void |
386 | handle_update_read(int handle, ssize_t bytes) | 400 | handle_update_read(int handle, ssize_t bytes) |
387 | { | 401 | { |
@@ -668,7 +682,7 @@ process_open(u_int32_t id) | |||
668 | if (fd < 0) { | 682 | if (fd < 0) { |
669 | status = errno_to_portable(errno); | 683 | status = errno_to_portable(errno); |
670 | } else { | 684 | } else { |
671 | handle = handle_new(HANDLE_FILE, name, fd, NULL); | 685 | handle = handle_new(HANDLE_FILE, name, fd, flags, NULL); |
672 | if (handle < 0) { | 686 | if (handle < 0) { |
673 | close(fd); | 687 | close(fd); |
674 | } else { | 688 | } else { |
@@ -754,7 +768,8 @@ process_write(u_int32_t id) | |||
754 | if (fd < 0) | 768 | if (fd < 0) |
755 | status = SSH2_FX_FAILURE; | 769 | status = SSH2_FX_FAILURE; |
756 | else { | 770 | else { |
757 | if (lseek(fd, off, SEEK_SET) < 0) { | 771 | if (!(handle_to_flags(handle) & O_APPEND) && |
772 | lseek(fd, off, SEEK_SET) < 0) { | ||
758 | status = errno_to_portable(errno); | 773 | status = errno_to_portable(errno); |
759 | error("process_write: seek failed"); | 774 | error("process_write: seek failed"); |
760 | } else { | 775 | } else { |
@@ -971,7 +986,7 @@ process_opendir(u_int32_t id) | |||
971 | if (dirp == NULL) { | 986 | if (dirp == NULL) { |
972 | status = errno_to_portable(errno); | 987 | status = errno_to_portable(errno); |
973 | } else { | 988 | } else { |
974 | handle = handle_new(HANDLE_DIR, path, 0, dirp); | 989 | handle = handle_new(HANDLE_DIR, path, 0, 0, dirp); |
975 | if (handle < 0) { | 990 | if (handle < 0) { |
976 | closedir(dirp); | 991 | closedir(dirp); |
977 | } else { | 992 | } else { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.382 2013/10/14 22:22:04 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.383 2013/10/14 23:28:23 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -723,6 +723,14 @@ main(int ac, char **av) | |||
723 | 723 | ||
724 | channel_set_af(options.address_family); | 724 | channel_set_af(options.address_family); |
725 | 725 | ||
726 | /* Tidy and check options */ | ||
727 | if (options.host_key_alias != NULL) | ||
728 | lowercase(options.host_key_alias); | ||
729 | if (options.proxy_command != NULL && | ||
730 | strcmp(options.proxy_command, "-") == 0 && | ||
731 | options.proxy_use_fdpass) | ||
732 | fatal("ProxyCommand=- and ProxyUseFDPass are incompatible"); | ||
733 | |||
726 | /* reinit */ | 734 | /* reinit */ |
727 | log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog); | 735 | log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog); |
728 | 736 | ||
@@ -779,24 +787,6 @@ main(int ac, char **av) | |||
779 | free(cp); | 787 | free(cp); |
780 | } | 788 | } |
781 | 789 | ||
782 | /* force lowercase for hostkey matching */ | ||
783 | if (options.host_key_alias != NULL) { | ||
784 | for (p = options.host_key_alias; *p; p++) | ||
785 | if (isupper(*p)) | ||
786 | *p = (char)tolower(*p); | ||
787 | } | ||
788 | |||
789 | if (options.proxy_command != NULL && | ||
790 | strcmp(options.proxy_command, "none") == 0) { | ||
791 | free(options.proxy_command); | ||
792 | options.proxy_command = NULL; | ||
793 | } | ||
794 | if (options.control_path != NULL && | ||
795 | strcmp(options.control_path, "none") == 0) { | ||
796 | free(options.control_path); | ||
797 | options.control_path = NULL; | ||
798 | } | ||
799 | |||
800 | if (options.control_path != NULL) { | 790 | if (options.control_path != NULL) { |
801 | cp = tilde_expand_filename(options.control_path, | 791 | cp = tilde_expand_filename(options.control_path, |
802 | original_real_uid); | 792 | original_real_uid); |