Get sshd working well enough for shell and sftp sessions.
The main thing that doesn't work is terminating connections when the
command (sh or sftp-server) terminates since we don't have signals.
Change-Id: Ic4a2e355f3b1c54ad3990b124d9d49cf6e7a6f15
diff --git a/BUILD.gn b/BUILD.gn
index 65500c7..26caaf7 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -238,6 +238,7 @@
":umac128",
"//third_party/boringssl",
]
+ libs = [ "launchpad" ]
configs += [ ":fuchsia" ]
}
diff --git a/auth.c b/auth.c
index 6ee6116..27797df 100644
--- a/auth.c
+++ b/auth.c
@@ -174,6 +174,7 @@
free(shell);
return 0;
}
+#ifndef __Fuchsia__
if (S_ISREG(st.st_mode) == 0 ||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
logit("User %.100s not allowed because shell %.100s "
@@ -181,6 +182,7 @@
free(shell);
return 0;
}
+#endif // __Fuchsia__
free(shell);
}
diff --git a/fuchsia/README.md b/fuchsia/README.md
new file mode 100644
index 0000000..aa1a6d7
--- /dev/null
+++ b/fuchsia/README.md
@@ -0,0 +1,29 @@
+# OpenSSH on Fuchsia
+
+## Running
+
+### ssh
+
+### sshd
+
+First generate host keys on your Fuchsia device:
+```
+$ ssh-keygen -A
+```
+
+Then copy your public SSH key to your Fuchsia device from your host:
+```
+% netcp ~/.ssh/id_rsa.pub :/.ssh/authorized_keys
+```
+
+Run `sshd` with `-d` for debug mode and `-r` to disable reexecing:
+```
+$ sshd -dr
+```
+### scp
+
+### sftp
+
+## Port Notes
+
+TODO
diff --git a/fuchsia/config.h b/fuchsia/config.h
index 802c4ba..bd98195 100644
--- a/fuchsia/config.h
+++ b/fuchsia/config.h
@@ -961,7 +961,7 @@
/* #undef HAVE_SETGROUPENT */
/* Define to 1 if you have the `setgroups' function. */
-#define HAVE_SETGROUPS 1
+/*#define HAVE_SETGROUPS 1*/
/* Define to 1 if you have the `setlinebuf' function. */
#define HAVE_SETLINEBUF 1
@@ -1045,7 +1045,7 @@
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the `socketpair' function. */
-#define HAVE_SOCKETPAIR 1
+/*#define HAVE_SOCKETPAIR 1*/
/* Have PEERCRED socket option */
#define HAVE_SO_PEERCRED 1
@@ -1162,7 +1162,7 @@
/* #undef HAVE_SWAP32 */
/* Define to 1 if you have the `sysconf' function. */
-#define HAVE_SYSCONF 1
+/*#define HAVE_SYSCONF 1*/
/* Define if you have syslen in utmpx.h */
/* #undef HAVE_SYSLEN_IN_UTMPX */
@@ -1678,7 +1678,7 @@
/* #undef USE_PAM */
/* Use PIPES instead of a socketpair() */
-/* #undef USE_PIPES */
+#define USE_PIPES 1
/* Define if you have Solaris privileges */
/* #undef USE_SOLARIS_PRIVS */
diff --git a/fuchsia/fuchsia-compat.c b/fuchsia/fuchsia-compat.c
index 0fa72de..efabdaa 100644
--- a/fuchsia/fuchsia-compat.c
+++ b/fuchsia/fuchsia-compat.c
@@ -1,5 +1,14 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <launchpad/launchpad.h>
#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
+#include <unistd.h>
int chroot(const char *path) { return -1; }
@@ -31,3 +40,38 @@
struct passwd *getpwuid(uid_t uid) {
return getpwent();
}
+
+#define ARGV_MAX 256
+
+mx_handle_t fuchsia_launch_child(const char *command, int in, int out, int err) {
+ const char *argv[ARGV_MAX];
+ int argc = 1;
+ argv[0] = "/boot/bin/sh";
+ if (command) {
+ argv[argc++] = "-c";
+ argv[argc++] = command;
+ } else {
+ command = argv[0];
+ }
+ argv[argc] = NULL;
+
+ launchpad_t *lp;
+ launchpad_create(0, command, &lp);
+ launchpad_load_from_file(lp, argv[0]);
+ launchpad_set_args(lp, argc, argv);
+ launchpad_clone(lp, LP_CLONE_MXIO_ROOT|LP_CLONE_MXIO_CWD);
+ // TODO: set up environment
+ launchpad_transfer_fd(lp, in, STDIN_FILENO);
+ launchpad_transfer_fd(lp, out, STDOUT_FILENO);
+ launchpad_transfer_fd(lp, err, STDERR_FILENO);
+
+ mx_handle_t proc = 0;
+ const char* errmsg;
+
+ mx_status_t status = launchpad_go(lp, &proc, &errmsg);
+ if (status < 0) {
+ printf("error from launchpad_go: %s\n", errmsg);
+ }
+
+ return proc;
+}
diff --git a/fuchsia/fuchsia-compat.h b/fuchsia/fuchsia-compat.h
index db749d6..a04794d 100644
--- a/fuchsia/fuchsia-compat.h
+++ b/fuchsia/fuchsia-compat.h
@@ -1,5 +1,12 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#pragma once
+#include <magenta/types.h>
+
int chroot(const char *path);
+mx_handle_t fuchsia_launch_child(const char *command, int in, int out, int err);
#define CUSTOM_SYS_AUTH_PASSWD
diff --git a/fuchsia/sshd_config b/fuchsia/sshd_config
index 08ab390..5b94765 100644
--- a/fuchsia/sshd_config
+++ b/fuchsia/sshd_config
@@ -93,7 +93,7 @@
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
-#UsePrivilegeSeparation sandbox
+UsePrivilegeSeparation no
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
@@ -109,7 +109,7 @@
#Banner none
# override default of no subsystems
-Subsystem sftp /usr/libexec/sftp-server
+Subsystem sftp /system/bin/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c
index 9380b33..a7aa4b3 100644
--- a/openbsd-compat/bsd-closefrom.c
+++ b/openbsd-compat/bsd-closefrom.c
@@ -47,6 +47,10 @@
# endif
#endif
+#ifdef __Fuchsia__
+#include <mxio/limits.h>
+#endif
+
#ifndef OPEN_MAX
# define OPEN_MAX 256
#endif
@@ -95,6 +99,8 @@
*/
#ifdef HAVE_SYSCONF
maxfd = sysconf(_SC_OPEN_MAX);
+#elif __Fuchsia__
+ maxfd = MAX_MXIO_FD;
#else
maxfd = getdtablesize();
#endif /* HAVE_SYSCONF */
diff --git a/session.c b/session.c
index a08aa69..c51ede8 100644
--- a/session.c
+++ b/session.c
@@ -343,6 +343,27 @@
session_proctitle(s);
+#ifdef __Fuchsia__
+ mx_handle_t process_handle = fuchsia_launch_child(command, pin[0], pout[1], perr[1]);
+ if (process_handle == 0) {
+#ifdef USE_PIPES
+ close(pin[0]);
+ close(pin[1]);
+ close(pout[0]);
+ close(pout[1]);
+ close(perr[0]);
+ close(perr[1]);
+#else
+ close(inout[0]);
+ close(inout[1]);
+ close(err[0]);
+ close(err[1]);
+#endif
+ return -1;
+ }
+ // Force an mx_handle_t into a pid_t.
+ pid = (pid_t)process_handle;
+#else
/* Fork the child. */
switch ((pid = fork())) {
case -1:
@@ -434,6 +455,7 @@
#endif
s->pid = pid;
+#endif // __Fuchsia__
/* Set interactive/non-interactive mode. */
packet_set_interactive(s->display != NULL,
options.ip_qos_interactive, options.ip_qos_bulk);