summaryrefslogtreecommitdiff
path: root/sftp-server.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2008-07-22 19:45:18 +0000
committerColin Watson <cjwatson@debian.org>2008-07-22 19:45:18 +0000
commit137d76ba65883aa8143af1fcad83b57e7badef0c (patch)
treef426e804bb5248ceafedfab7bb78ae6e6752942c /sftp-server.c
parentdac7d049dad31f5f84d421d4eb628a7e13f977d7 (diff)
parentef94e5613d37bcbf880f21ee6094e4b1c7683a4c (diff)
* New upstream release (closes: #474301). Important changes not previously
backported to 4.7p1: - 4.9/4.9p1 (http://www.openssh.com/txt/release-4.9): + Added chroot(2) support for sshd(8), controlled by a new option "ChrootDirectory" (closes: #139047, LP: #24777). + Linked sftp-server(8) into sshd(8). The internal sftp server is used when the command "internal-sftp" is specified in a Subsystem or ForceCommand declaration. When used with ChrootDirectory, the internal sftp server requires no special configuration of files inside the chroot environment. + Added a protocol extension method "posix-rename@openssh.com" for sftp-server(8) to perform POSIX atomic rename() operations; sftp(1) prefers this if available (closes: #308561). + Removed the fixed limit of 100 file handles in sftp-server(8). + ssh(8) will now skip generation of SSH protocol 1 ephemeral server keys when in inetd mode and protocol 2 connections are negotiated. This speeds up protocol 2 connections to inetd-mode servers that also allow Protocol 1. + Accept the PermitRootLogin directive in a sshd_config(5) Match block. Allows for, e.g. permitting root only from the local network. + Reworked sftp(1) argument splitting and escaping to be more internally consistent (i.e. between sftp commands) and more consistent with sh(1). Please note that this will change the interpretation of some quoted strings, especially those with embedded backslash escape sequences. + Support "Banner=none" in sshd_config(5) to disable sending of a pre-login banner (e.g. in a Match block). + ssh(1) ProxyCommands are now executed with $SHELL rather than /bin/sh. + ssh(1)'s ConnectTimeout option is now applied to both the TCP connection and the SSH banner exchange (previously it just covered the TCP connection). This allows callers of ssh(1) to better detect and deal with stuck servers that accept a TCP connection but don't progress the protocol, and also makes ConnectTimeout useful for connections via a ProxyCommand. + scp(1) incorrectly reported "stalled" on slow copies (closes: #140828). + scp(1) date underflow for timestamps before epoch. + ssh(1) used the obsolete SIG DNS RRtype for host keys in DNS, instead of the current standard RRSIG. + Correctly drain ACKs when a sftp(1) upload write fails midway, avoids a fatal() exit from what should be a recoverable condition. + Fixed ssh-keygen(1) selective host key hashing (i.e. "ssh-keygen -HF hostname") to not include any IP address in the data to be hashed. + Make ssh(1) skip listening on the IPv6 wildcard address when a binding address of 0.0.0.0 is used against an old SSH server that does not support the RFC4254 syntax for wildcard bind addresses. + Enable IPV6_V6ONLY socket option on sshd(8) listen socket, as is already done for X11/TCP forwarding sockets (closes: #439661). + Fix FD leak that could hang a ssh(1) connection multiplexing master. + Make ssh(1) -q option documentation consistent with reality. + Fixed sshd(8) PAM support not calling pam_session_close(), or failing to call it with root privileges (closes: #372680). + Fix activation of OpenSSL engine support when requested in configure (LP: #119295). - 5.1/5.1p1 (http://www.openssh.com/txt/release-5.1): + Introduce experimental SSH Fingerprint ASCII Visualisation to ssh(1) and ssh-keygen(1). Visual fingerprint display is controlled by a new ssh_config(5) option "VisualHostKey". The intent is to render SSH host keys in a visual form that is amenable to easy recall and rejection of changed host keys. + sshd_config(5) now supports CIDR address/masklen matching in "Match address" blocks, with a fallback to classic wildcard matching. + sshd(8) now supports CIDR matching in ~/.ssh/authorized_keys from="..." restrictions, also with a fallback to classic wildcard matching. + Added an extended test mode (-T) to sshd(8) to request that it write its effective configuration to stdout and exit. Extended test mode also supports the specification of connection parameters (username, source address and hostname) to test the application of sshd_config(5) Match rules. + ssh(1) now prints the number of bytes transferred and the overall connection throughput for SSH protocol 2 sessions when in verbose mode (previously these statistics were displayed for protocol 1 connections only). + sftp-server(8) now supports extension methods statvfs@openssh.com and fstatvfs@openssh.com that implement statvfs(2)-like operations. + sftp(1) now has a "df" command to the sftp client that uses the statvfs@openssh.com to produce a df(1)-like display of filesystem space and inode utilisation (requires statvfs@openssh.com support on the server). + Added a MaxSessions option to sshd_config(5) to allow control of the number of multiplexed sessions supported over a single TCP connection. This allows increasing the number of allowed sessions above the previous default of 10, disabling connection multiplexing (MaxSessions=1) or disallowing login/shell/subsystem sessions entirely (MaxSessions=0). + Added a no-more-sessions@openssh.com global request extension that is sent from ssh(1) to sshd(8) when the client knows that it will never request another session (i.e. when session multiplexing is disabled). This allows a server to disallow further session requests and terminate the session in cases where the client has been hijacked. + ssh-keygen(1) now supports the use of the -l option in combination with -F to search for a host in ~/.ssh/known_hosts and display its fingerprint. + ssh-keyscan(1) now defaults to "rsa" (protocol 2) keys, instead of "rsa1". + Added an AllowAgentForwarding option to sshd_config(8) to control whether authentication agent forwarding is permitted. Note that this is a loose control, as a client may install their own unofficial forwarder. + ssh(1) and sshd(8): avoid unnecessary malloc/copy/free when receiving network data, resulting in a ~10% speedup. + ssh(1) and sshd(8) will now try additional addresses when connecting to a port forward destination whose DNS name resolves to more than one address. The previous behaviour was to try the only first address and give up if that failed. + ssh(1) and sshd(8) now support signalling that channels are half-closed for writing, through a channel protocol extension notification "eow@openssh.com". This allows propagation of closed file descriptors, so that commands such as "ssh -2 localhost od /bin/ls | true" do not send unnecessary data over the wire. + sshd(8): increased the default size of ssh protocol 1 ephemeral keys from 768 to 1024 bits. + When ssh(1) has been requested to fork after authentication ("ssh -f") with ExitOnForwardFailure enabled, delay the fork until after replies for any -R forwards have been seen. Allows for robust detection of -R forward failure when using -f. + "Match group" blocks in sshd_config(5) now support negation of groups. E.g. "Match group staff,!guests". + sftp(1) and sftp-server(8) now allow chmod-like operations to set set[ug]id/sticky bits. + The MaxAuthTries option is now permitted in sshd_config(5) match blocks. + Multiplexed ssh(1) sessions now support a subset of the ~ escapes that are available to a primary connection. + ssh(1) connection multiplexing will now fall back to creating a new connection in most error cases (closes: #352830). + Make ssh(1) deal more gracefully with channel requests that fail. Previously it would optimistically assume that requests would always succeed, which could cause hangs if they did not (e.g. when the server runs out of file descriptors). + ssh(1) now reports multiplexing errors via the multiplex slave's stderr where possible (subject to LogLevel in the mux master). + Prevent sshd(8) from erroneously applying public key restrictions leaned from ~/.ssh/authorized_keys to other authentication methods when public key authentication subsequently fails (LP: #161047). + Fixed an UMAC alignment problem that manifested on Itanium platforms.
Diffstat (limited to 'sftp-server.c')
-rw-r--r--sftp-server.c220
1 files changed, 167 insertions, 53 deletions
diff --git a/sftp-server.c b/sftp-server.c
index 76edebc5a..24c4ff717 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-server.c,v 1.73 2007/05/17 07:55:29 djm Exp $ */ 1/* $OpenBSD: sftp-server.c,v 1.84 2008/06/26 06:10:09 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 *
@@ -23,6 +23,12 @@
23#ifdef HAVE_SYS_TIME_H 23#ifdef HAVE_SYS_TIME_H
24# include <sys/time.h> 24# include <sys/time.h>
25#endif 25#endif
26#ifdef HAVE_SYS_MOUNT_H
27#include <sys/mount.h>
28#endif
29#ifdef HAVE_SYS_STATVFS_H
30#include <sys/statvfs.h>
31#endif
26 32
27#include <dirent.h> 33#include <dirent.h>
28#include <errno.h> 34#include <errno.h>
@@ -98,6 +104,9 @@ errno_to_portable(int unixerrno)
98 case EINVAL: 104 case EINVAL:
99 ret = SSH2_FX_BAD_MESSAGE; 105 ret = SSH2_FX_BAD_MESSAGE;
100 break; 106 break;
107 case ENOSYS:
108 ret = SSH2_FX_OP_UNSUPPORTED;
109 break;
101 default: 110 default:
102 ret = SSH2_FX_FAILURE; 111 ret = SSH2_FX_FAILURE;
103 break; 112 break;
@@ -169,6 +178,7 @@ struct Handle {
169 int fd; 178 int fd;
170 char *name; 179 char *name;
171 u_int64_t bytes_read, bytes_write; 180 u_int64_t bytes_read, bytes_write;
181 int next_unused;
172}; 182};
173 183
174enum { 184enum {
@@ -177,40 +187,46 @@ enum {
177 HANDLE_FILE 187 HANDLE_FILE
178}; 188};
179 189
180Handle handles[100]; 190Handle *handles = NULL;
191u_int num_handles = 0;
192int first_unused_handle = -1;
181 193
182static void 194static void handle_unused(int i)
183handle_init(void)
184{ 195{
185 u_int i; 196 handles[i].use = HANDLE_UNUSED;
186 197 handles[i].next_unused = first_unused_handle;
187 for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) 198 first_unused_handle = i;
188 handles[i].use = HANDLE_UNUSED;
189} 199}
190 200
191static int 201static int
192handle_new(int use, const char *name, int fd, DIR *dirp) 202handle_new(int use, const char *name, int fd, DIR *dirp)
193{ 203{
194 u_int i; 204 int i;
195 205
196 for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) { 206 if (first_unused_handle == -1) {
197 if (handles[i].use == HANDLE_UNUSED) { 207 if (num_handles + 1 <= num_handles)
198 handles[i].use = use; 208 return -1;
199 handles[i].dirp = dirp; 209 num_handles++;
200 handles[i].fd = fd; 210 handles = xrealloc(handles, num_handles, sizeof(Handle));
201 handles[i].name = xstrdup(name); 211 handle_unused(num_handles - 1);
202 handles[i].bytes_read = handles[i].bytes_write = 0;
203 return i;
204 }
205 } 212 }
206 return -1; 213
214 i = first_unused_handle;
215 first_unused_handle = handles[i].next_unused;
216
217 handles[i].use = use;
218 handles[i].dirp = dirp;
219 handles[i].fd = fd;
220 handles[i].name = xstrdup(name);
221 handles[i].bytes_read = handles[i].bytes_write = 0;
222
223 return i;
207} 224}
208 225
209static int 226static int
210handle_is_ok(int i, int type) 227handle_is_ok(int i, int type)
211{ 228{
212 return i >= 0 && (u_int)i < sizeof(handles)/sizeof(Handle) && 229 return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
213 handles[i].use == type;
214} 230}
215 231
216static int 232static int
@@ -300,12 +316,12 @@ handle_close(int handle)
300 316
301 if (handle_is_ok(handle, HANDLE_FILE)) { 317 if (handle_is_ok(handle, HANDLE_FILE)) {
302 ret = close(handles[handle].fd); 318 ret = close(handles[handle].fd);
303 handles[handle].use = HANDLE_UNUSED;
304 xfree(handles[handle].name); 319 xfree(handles[handle].name);
320 handle_unused(handle);
305 } else if (handle_is_ok(handle, HANDLE_DIR)) { 321 } else if (handle_is_ok(handle, HANDLE_DIR)) {
306 ret = closedir(handles[handle].dirp); 322 ret = closedir(handles[handle].dirp);
307 handles[handle].use = HANDLE_UNUSED;
308 xfree(handles[handle].name); 323 xfree(handles[handle].name);
324 handle_unused(handle);
309 } else { 325 } else {
310 errno = ENOENT; 326 errno = ENOENT;
311 } 327 }
@@ -333,7 +349,7 @@ handle_log_exit(void)
333{ 349{
334 u_int i; 350 u_int i;
335 351
336 for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) 352 for (i = 0; i < num_handles; i++)
337 if (handles[i].use != HANDLE_UNUSED) 353 if (handles[i].use != HANDLE_UNUSED)
338 handle_log_close(i, "forced"); 354 handle_log_close(i, "forced");
339} 355}
@@ -468,6 +484,33 @@ send_attrib(u_int32_t id, const Attrib *a)
468 buffer_free(&msg); 484 buffer_free(&msg);
469} 485}
470 486
487static void
488send_statvfs(u_int32_t id, struct statvfs *st)
489{
490 Buffer msg;
491 u_int64_t flag;
492
493 flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
494 flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
495
496 buffer_init(&msg);
497 buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY);
498 buffer_put_int(&msg, id);
499 buffer_put_int64(&msg, st->f_bsize);
500 buffer_put_int64(&msg, st->f_frsize);
501 buffer_put_int64(&msg, st->f_blocks);
502 buffer_put_int64(&msg, st->f_bfree);
503 buffer_put_int64(&msg, st->f_bavail);
504 buffer_put_int64(&msg, st->f_files);
505 buffer_put_int64(&msg, st->f_ffree);
506 buffer_put_int64(&msg, st->f_favail);
507 buffer_put_int64(&msg, FSID_TO_ULONG(st->f_fsid));
508 buffer_put_int64(&msg, flag);
509 buffer_put_int64(&msg, st->f_namemax);
510 send_msg(&msg);
511 buffer_free(&msg);
512}
513
471/* parse incoming */ 514/* parse incoming */
472 515
473static void 516static void
@@ -480,6 +523,15 @@ process_init(void)
480 buffer_init(&msg); 523 buffer_init(&msg);
481 buffer_put_char(&msg, SSH2_FXP_VERSION); 524 buffer_put_char(&msg, SSH2_FXP_VERSION);
482 buffer_put_int(&msg, SSH2_FILEXFER_VERSION); 525 buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
526 /* POSIX rename extension */
527 buffer_put_cstring(&msg, "posix-rename@openssh.com");
528 buffer_put_cstring(&msg, "1"); /* version */
529 /* statvfs extension */
530 buffer_put_cstring(&msg, "statvfs@openssh.com");
531 buffer_put_cstring(&msg, "2"); /* version */
532 /* fstatvfs extension */
533 buffer_put_cstring(&msg, "fstatvfs@openssh.com");
534 buffer_put_cstring(&msg, "2"); /* version */
483 send_msg(&msg); 535 send_msg(&msg);
484 buffer_free(&msg); 536 buffer_free(&msg);
485} 537}
@@ -711,7 +763,7 @@ process_setstat(void)
711 } 763 }
712 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 764 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
713 logit("set \"%s\" mode %04o", name, a->perm); 765 logit("set \"%s\" mode %04o", name, a->perm);
714 ret = chmod(name, a->perm & 0777); 766 ret = chmod(name, a->perm & 07777);
715 if (ret == -1) 767 if (ret == -1)
716 status = errno_to_portable(errno); 768 status = errno_to_portable(errno);
717 } 769 }
@@ -765,9 +817,9 @@ process_fsetstat(void)
765 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 817 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
766 logit("set \"%s\" mode %04o", name, a->perm); 818 logit("set \"%s\" mode %04o", name, a->perm);
767#ifdef HAVE_FCHMOD 819#ifdef HAVE_FCHMOD
768 ret = fchmod(fd, a->perm & 0777); 820 ret = fchmod(fd, a->perm & 07777);
769#else 821#else
770 ret = chmod(name, a->perm & 0777); 822 ret = chmod(name, a->perm & 07777);
771#endif 823#endif
772 if (ret == -1) 824 if (ret == -1)
773 status = errno_to_portable(errno); 825 status = errno_to_portable(errno);
@@ -918,7 +970,7 @@ process_mkdir(void)
918 name = get_string(NULL); 970 name = get_string(NULL);
919 a = get_attrib(); 971 a = get_attrib();
920 mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? 972 mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
921 a->perm & 0777 : 0777; 973 a->perm & 07777 : 0777;
922 debug3("request %u: mkdir", id); 974 debug3("request %u: mkdir", id);
923 logit("mkdir name \"%s\" mode 0%o", name, mode); 975 logit("mkdir name \"%s\" mode 0%o", name, mode);
924 ret = mkdir(name, mode); 976 ret = mkdir(name, mode);
@@ -990,6 +1042,9 @@ process_rename(void)
990 /* Race-free rename of regular files */ 1042 /* Race-free rename of regular files */
991 if (link(oldpath, newpath) == -1) { 1043 if (link(oldpath, newpath) == -1) {
992 if (errno == EOPNOTSUPP 1044 if (errno == EOPNOTSUPP
1045#ifdef EXDEV
1046 || errno == EXDEV
1047#endif
993#ifdef LINK_OPNOTSUPP_ERRNO 1048#ifdef LINK_OPNOTSUPP_ERRNO
994 || errno == LINK_OPNOTSUPP_ERRNO 1049 || errno == LINK_OPNOTSUPP_ERRNO
995#endif 1050#endif
@@ -1073,6 +1128,59 @@ process_symlink(void)
1073} 1128}
1074 1129
1075static void 1130static void
1131process_extended_posix_rename(u_int32_t id)
1132{
1133 char *oldpath, *newpath;
1134
1135 oldpath = get_string(NULL);
1136 newpath = get_string(NULL);
1137 debug3("request %u: posix-rename", id);
1138 logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
1139 if (rename(oldpath, newpath) == -1)
1140 send_status(id, errno_to_portable(errno));
1141 else
1142 send_status(id, SSH2_FX_OK);
1143 xfree(oldpath);
1144 xfree(newpath);
1145}
1146
1147static void
1148process_extended_statvfs(u_int32_t id)
1149{
1150 char *path;
1151 struct statvfs st;
1152
1153 path = get_string(NULL);
1154 debug3("request %u: statfs", id);
1155 logit("statfs \"%s\"", path);
1156
1157 if (statvfs(path, &st) != 0)
1158 send_status(id, errno_to_portable(errno));
1159 else
1160 send_statvfs(id, &st);
1161 xfree(path);
1162}
1163
1164static void
1165process_extended_fstatvfs(u_int32_t id)
1166{
1167 int handle, fd;
1168 struct statvfs st;
1169
1170 handle = get_handle();
1171 debug("request %u: fstatvfs \"%s\" (handle %u)",
1172 id, handle_to_name(handle), handle);
1173 if ((fd = handle_to_fd(handle)) < 0) {
1174 send_status(id, SSH2_FX_FAILURE);
1175 return;
1176 }
1177 if (fstatvfs(fd, &st) != 0)
1178 send_status(id, errno_to_portable(errno));
1179 else
1180 send_statvfs(id, &st);
1181}
1182
1183static void
1076process_extended(void) 1184process_extended(void)
1077{ 1185{
1078 u_int32_t id; 1186 u_int32_t id;
@@ -1080,7 +1188,14 @@ process_extended(void)
1080 1188
1081 id = get_int(); 1189 id = get_int();
1082 request = get_string(NULL); 1190 request = get_string(NULL);
1083 send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ 1191 if (strcmp(request, "posix-rename@openssh.com") == 0)
1192 process_extended_posix_rename(id);
1193 else if (strcmp(request, "statvfs@openssh.com") == 0)
1194 process_extended_statvfs(id);
1195 else if (strcmp(request, "fstatvfs@openssh.com") == 0)
1196 process_extended_fstatvfs(id);
1197 else
1198 send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
1084 xfree(request); 1199 xfree(request);
1085} 1200}
1086 1201
@@ -1103,7 +1218,7 @@ process(void)
1103 if (msg_len > SFTP_MAX_MSG_LENGTH) { 1218 if (msg_len > SFTP_MAX_MSG_LENGTH) {
1104 error("bad message from %s local user %s", 1219 error("bad message from %s local user %s",
1105 client_addr, pw->pw_name); 1220 client_addr, pw->pw_name);
1106 cleanup_exit(11); 1221 sftp_server_cleanup_exit(11);
1107 } 1222 }
1108 if (buf_len < msg_len + 4) 1223 if (buf_len < msg_len + 4)
1109 return; 1224 return;
@@ -1176,18 +1291,22 @@ process(void)
1176 break; 1291 break;
1177 } 1292 }
1178 /* discard the remaining bytes from the current packet */ 1293 /* discard the remaining bytes from the current packet */
1179 if (buf_len < buffer_len(&iqueue)) 1294 if (buf_len < buffer_len(&iqueue)) {
1180 fatal("iqueue grew unexpectedly"); 1295 error("iqueue grew unexpectedly");
1296 sftp_server_cleanup_exit(255);
1297 }
1181 consumed = buf_len - buffer_len(&iqueue); 1298 consumed = buf_len - buffer_len(&iqueue);
1182 if (msg_len < consumed) 1299 if (msg_len < consumed) {
1183 fatal("msg_len %d < consumed %d", msg_len, consumed); 1300 error("msg_len %d < consumed %d", msg_len, consumed);
1301 sftp_server_cleanup_exit(255);
1302 }
1184 if (msg_len > consumed) 1303 if (msg_len > consumed)
1185 buffer_consume(&iqueue, msg_len - consumed); 1304 buffer_consume(&iqueue, msg_len - consumed);
1186} 1305}
1187 1306
1188/* Cleanup handler that logs active handles upon normal exit */ 1307/* Cleanup handler that logs active handles upon normal exit */
1189void 1308void
1190cleanup_exit(int i) 1309sftp_server_cleanup_exit(int i)
1191{ 1310{
1192 if (pw != NULL && client_addr != NULL) { 1311 if (pw != NULL && client_addr != NULL) {
1193 handle_log_exit(); 1312 handle_log_exit();
@@ -1198,7 +1317,7 @@ cleanup_exit(int i)
1198} 1317}
1199 1318
1200static void 1319static void
1201usage(void) 1320sftp_server_usage(void)
1202{ 1321{
1203 extern char *__progname; 1322 extern char *__progname;
1204 1323
@@ -1208,7 +1327,7 @@ usage(void)
1208} 1327}
1209 1328
1210int 1329int
1211main(int argc, char **argv) 1330sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1212{ 1331{
1213 fd_set *rset, *wset; 1332 fd_set *rset, *wset;
1214 int in, out, max, ch, skipargs = 0, log_stderr = 0; 1333 int in, out, max, ch, skipargs = 0, log_stderr = 0;
@@ -1219,9 +1338,6 @@ main(int argc, char **argv)
1219 extern char *optarg; 1338 extern char *optarg;
1220 extern char *__progname; 1339 extern char *__progname;
1221 1340
1222 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1223 sanitise_stdfd();
1224
1225 __progname = ssh_get_progname(argv[0]); 1341 __progname = ssh_get_progname(argv[0]);
1226 log_init(__progname, log_level, log_facility, log_stderr); 1342 log_init(__progname, log_level, log_facility, log_stderr);
1227 1343
@@ -1244,12 +1360,12 @@ main(int argc, char **argv)
1244 break; 1360 break;
1245 case 'f': 1361 case 'f':
1246 log_facility = log_facility_number(optarg); 1362 log_facility = log_facility_number(optarg);
1247 if (log_level == SYSLOG_FACILITY_NOT_SET) 1363 if (log_facility == SYSLOG_FACILITY_NOT_SET)
1248 error("Invalid log facility \"%s\"", optarg); 1364 error("Invalid log facility \"%s\"", optarg);
1249 break; 1365 break;
1250 case 'h': 1366 case 'h':
1251 default: 1367 default:
1252 usage(); 1368 sftp_server_usage();
1253 } 1369 }
1254 } 1370 }
1255 1371
@@ -1257,22 +1373,20 @@ main(int argc, char **argv)
1257 1373
1258 if ((cp = getenv("SSH_CONNECTION")) != NULL) { 1374 if ((cp = getenv("SSH_CONNECTION")) != NULL) {
1259 client_addr = xstrdup(cp); 1375 client_addr = xstrdup(cp);
1260 if ((cp = strchr(client_addr, ' ')) == NULL) 1376 if ((cp = strchr(client_addr, ' ')) == NULL) {
1261 fatal("Malformed SSH_CONNECTION variable: \"%s\"", 1377 error("Malformed SSH_CONNECTION variable: \"%s\"",
1262 getenv("SSH_CONNECTION")); 1378 getenv("SSH_CONNECTION"));
1379 sftp_server_cleanup_exit(255);
1380 }
1263 *cp = '\0'; 1381 *cp = '\0';
1264 } else 1382 } else
1265 client_addr = xstrdup("UNKNOWN"); 1383 client_addr = xstrdup("UNKNOWN");
1266 1384
1267 if ((pw = getpwuid(getuid())) == NULL) 1385 pw = pwcopy(user_pw);
1268 fatal("No user found for uid %lu", (u_long)getuid());
1269 pw = pwcopy(pw);
1270 1386
1271 logit("session opened for local user %s from [%s]", 1387 logit("session opened for local user %s from [%s]",
1272 pw->pw_name, client_addr); 1388 pw->pw_name, client_addr);
1273 1389
1274 handle_init();
1275
1276 in = dup(STDIN_FILENO); 1390 in = dup(STDIN_FILENO);
1277 out = dup(STDOUT_FILENO); 1391 out = dup(STDOUT_FILENO);
1278 1392
@@ -1315,7 +1429,7 @@ main(int argc, char **argv)
1315 if (errno == EINTR) 1429 if (errno == EINTR)
1316 continue; 1430 continue;
1317 error("select: %s", strerror(errno)); 1431 error("select: %s", strerror(errno));
1318 cleanup_exit(2); 1432 sftp_server_cleanup_exit(2);
1319 } 1433 }
1320 1434
1321 /* copy stdin to iqueue */ 1435 /* copy stdin to iqueue */
@@ -1323,10 +1437,10 @@ main(int argc, char **argv)
1323 len = read(in, buf, sizeof buf); 1437 len = read(in, buf, sizeof buf);
1324 if (len == 0) { 1438 if (len == 0) {
1325 debug("read eof"); 1439 debug("read eof");
1326 cleanup_exit(0); 1440 sftp_server_cleanup_exit(0);
1327 } else if (len < 0) { 1441 } else if (len < 0) {
1328 error("read: %s", strerror(errno)); 1442 error("read: %s", strerror(errno));
1329 cleanup_exit(1); 1443 sftp_server_cleanup_exit(1);
1330 } else { 1444 } else {
1331 buffer_append(&iqueue, buf, len); 1445 buffer_append(&iqueue, buf, len);
1332 } 1446 }
@@ -1336,7 +1450,7 @@ main(int argc, char **argv)
1336 len = write(out, buffer_ptr(&oqueue), olen); 1450 len = write(out, buffer_ptr(&oqueue), olen);
1337 if (len < 0) { 1451 if (len < 0) {
1338 error("write: %s", strerror(errno)); 1452 error("write: %s", strerror(errno));
1339 cleanup_exit(1); 1453 sftp_server_cleanup_exit(1);
1340 } else { 1454 } else {
1341 buffer_consume(&oqueue, len); 1455 buffer_consume(&oqueue, len);
1342 } 1456 }