From: djm Date: Sun, 10 Feb 2008 11:29:40 +0000 (+0000) Subject: - markus@cvs.openbsd.org 2008/02/04 21:53:00 X-Git-Tag: V_4_9_P1~68 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/c33ba17eb7bdd9ddb13694d916b7bcbad24fc570 - markus@cvs.openbsd.org 2008/02/04 21:53:00 [session.c sftp-server.c sftp.h] link sftp-server into sshd; feedback and ok djm@ --- diff --git a/ChangeLog b/ChangeLog index 72607ed9..d31b8ef7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -68,6 +68,9 @@ explain how to handle local file names containing colons; requested by Tamas TEVESZ ok dtucker + - markus@cvs.openbsd.org 2008/02/04 21:53:00 + [session.c sftp-server.c sftp.h] + link sftp-server into sshd; feedback and ok djm@ 20080119 - (djm) Silence noice from expr in ssh-copy-id; patch from diff --git a/session.c b/session.c index 2b0580b4..a1319b38 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.224 2007/09/11 15:47:17 gilles Exp $ */ +/* $OpenBSD: session.c,v 1.225 2008/02/04 21:53:00 markus Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -87,6 +87,7 @@ #include "session.h" #include "kex.h" #include "monitor_wrap.h" +#include "sftp.h" #if defined(KRB5) && defined(USE_AFS) #include @@ -132,6 +133,10 @@ const char *original_command = NULL; #define MAX_SESSIONS 10 Session sessions[MAX_SESSIONS]; +#define SUBSYSTEM_NONE 0 +#define SUBSYSTEM_EXT 1 +#define SUBSYSTEM_INT_SFTP 2 + #ifdef HAVE_LOGIN_CAP login_cap_t *lc; #endif @@ -683,10 +688,14 @@ do_exec(Session *s, const char *command) if (options.adm_forced_command) { original_command = command; command = options.adm_forced_command; + if (s->is_subsystem) + s->is_subsystem = SUBSYSTEM_EXT; debug("Forced command (config) '%.900s'", command); } else if (forced_command) { original_command = command; command = forced_command; + if (s->is_subsystem) + s->is_subsystem = SUBSYSTEM_EXT; debug("Forced command (key option) '%.900s'", command); } @@ -1465,12 +1474,13 @@ child_close_fds(void) * environment, closing extra file descriptors, setting the user and group * ids, and executing the command or shell. */ +#define ARGV_MAX 10 void do_child(Session *s, const char *command) { extern char **environ; char **env; - char *argv[10]; + char *argv[ARGV_MAX]; const char *shell, *shell0, *hostname = NULL; struct passwd *pw = s->pw; @@ -1602,6 +1612,22 @@ do_child(Session *s, const char *command) /* restore SIGPIPE for child */ signal(SIGPIPE, SIG_DFL); + if (s->is_subsystem == SUBSYSTEM_INT_SFTP) { + extern int optind, optreset; + int i; + char *p, *args; + + setproctitle("%s@internal-sftp-server", s->pw->pw_name); + args = strdup(command ? command : "sftp-server"); + for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " "))) + if (i < ARGV_MAX - 1) + argv[i++] = p; + argv[i] = NULL; + optind = optreset = 1; + __progname = argv[0]; + exit(sftp_server_main(i, argv)); + } + if (options.use_login) { launch_login(pw, hostname); /* NEVERREACHED */ @@ -1874,13 +1900,16 @@ session_subsystem_req(Session *s) if (strcmp(subsys, options.subsystem_name[i]) == 0) { prog = options.subsystem_command[i]; cmd = options.subsystem_args[i]; - if (stat(prog, &st) < 0) { + if (!strcmp("internal-sftp", prog)) { + s->is_subsystem = SUBSYSTEM_INT_SFTP; + } else if (stat(prog, &st) < 0) { error("subsystem: cannot stat %s: %s", prog, strerror(errno)); break; + } else { + s->is_subsystem = SUBSYSTEM_EXT; } debug("subsystem: exec() %s", cmd); - s->is_subsystem = 1; do_exec(s, cmd); success = 1; break; diff --git a/sftp-server.c b/sftp-server.c index 5c84c728..373bd5ed 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server.c,v 1.75 2008/01/21 17:24:30 djm Exp $ */ +/* $OpenBSD: sftp-server.c,v 1.76 2008/02/04 21:53:00 markus Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * @@ -1110,7 +1110,7 @@ process(void) if (msg_len > SFTP_MAX_MSG_LENGTH) { error("bad message from %s local user %s", client_addr, pw->pw_name); - cleanup_exit(11); + sftp_server_cleanup_exit(11); } if (buf_len < msg_len + 4) return; @@ -1183,18 +1183,22 @@ process(void) break; } /* discard the remaining bytes from the current packet */ - if (buf_len < buffer_len(&iqueue)) - fatal("iqueue grew unexpectedly"); + if (buf_len < buffer_len(&iqueue)) { + error("iqueue grew unexpectedly"); + sftp_server_cleanup_exit(255); + } consumed = buf_len - buffer_len(&iqueue); - if (msg_len < consumed) - fatal("msg_len %d < consumed %d", msg_len, consumed); + if (msg_len < consumed) { + error("msg_len %d < consumed %d", msg_len, consumed); + sftp_server_cleanup_exit(255); + } if (msg_len > consumed) buffer_consume(&iqueue, msg_len - consumed); } /* Cleanup handler that logs active handles upon normal exit */ void -cleanup_exit(int i) +sftp_server_cleanup_exit(int i) { if (pw != NULL && client_addr != NULL) { handle_log_exit(); @@ -1205,7 +1209,7 @@ cleanup_exit(int i) } static void -usage(void) +sftp_server_usage(void) { extern char *__progname; @@ -1215,7 +1219,7 @@ usage(void) } int -main(int argc, char **argv) +sftp_server_main(int argc, char **argv) { fd_set *rset, *wset; int in, out, max, ch, skipargs = 0, log_stderr = 0; @@ -1256,7 +1260,7 @@ main(int argc, char **argv) break; case 'h': default: - usage(); + sftp_server_usage(); } } @@ -1264,15 +1268,19 @@ main(int argc, char **argv) if ((cp = getenv("SSH_CONNECTION")) != NULL) { client_addr = xstrdup(cp); - if ((cp = strchr(client_addr, ' ')) == NULL) - fatal("Malformed SSH_CONNECTION variable: \"%s\"", + if ((cp = strchr(client_addr, ' ')) == NULL) { + error("Malformed SSH_CONNECTION variable: \"%s\"", getenv("SSH_CONNECTION")); + sftp_server_cleanup_exit(255); + } *cp = '\0'; } else client_addr = xstrdup("UNKNOWN"); - if ((pw = getpwuid(getuid())) == NULL) - fatal("No user found for uid %lu", (u_long)getuid()); + if ((pw = getpwuid(getuid())) == NULL) { + error("No user found for uid %lu", (u_long)getuid()); + sftp_server_cleanup_exit(255); + } pw = pwcopy(pw); logit("session opened for local user %s from [%s]", @@ -1320,7 +1328,7 @@ main(int argc, char **argv) if (errno == EINTR) continue; error("select: %s", strerror(errno)); - cleanup_exit(2); + sftp_server_cleanup_exit(2); } /* copy stdin to iqueue */ @@ -1328,10 +1336,10 @@ main(int argc, char **argv) len = read(in, buf, sizeof buf); if (len == 0) { debug("read eof"); - cleanup_exit(0); + sftp_server_cleanup_exit(0); } else if (len < 0) { error("read: %s", strerror(errno)); - cleanup_exit(1); + sftp_server_cleanup_exit(1); } else { buffer_append(&iqueue, buf, len); } @@ -1341,7 +1349,7 @@ main(int argc, char **argv) len = write(out, buffer_ptr(&oqueue), olen); if (len < 0) { error("write: %s", strerror(errno)); - cleanup_exit(1); + sftp_server_cleanup_exit(1); } else { buffer_consume(&oqueue, len); } diff --git a/sftp.h b/sftp.h index 610c0b75..12b9cc05 100644 --- a/sftp.h +++ b/sftp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.h,v 1.5 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: sftp.h,v 1.6 2008/02/04 21:53:00 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -90,3 +90,6 @@ #define SSH2_FX_CONNECTION_LOST 7 #define SSH2_FX_OP_UNSUPPORTED 8 #define SSH2_FX_MAX 8 + +int sftp_server_main(int, char **); +void sftp_server_cleanup_exit(int) __dead;