#!/usr/bin/env php splitArguments($original_command); $argv = array_merge($argv, $original_argv); $args = new PhutilArgumentParser($argv); $args->setTagline('receive SSH requests'); $args->setSynopsis(<<parsePartial( array( array( 'name' => 'phabricator-ssh-user', 'param' => 'username', ), )); try { $user_name = $args->getArg('phabricator-ssh-user'); if (!strlen($user_name)) { throw new Exception("No username."); } $user = id(new PhabricatorUser())->loadOneWhere( 'userName = %s', $user_name); if (!$user) { throw new Exception("Invalid username."); } if ($user->getIsDisabled()) { throw new Exception("You have been exiled."); } $workflows = array( new ConduitSSHWorkflow(), ); // This duplicates logic in parseWorkflows(), but allows us to raise more // concise/relevant exceptions when the client is a remote SSH. $remain = $args->getUnconsumedArgumentVector(); if (empty($remain)) { throw new Exception("No interactive logins."); } else { $command = head($remain); $workflow_names = mpull($workflows, 'getName', 'getName'); if (empty($workflow_names[$command])) { throw new Exception("Invalid command."); } } $workflow = $args->parseWorkflows($workflows); $workflow->setUser($user); $sock_stdin = fopen('php://stdin', 'r'); if (!$sock_stdin) { throw new Exception("Unable to open stdin."); } $sock_stdout = fopen('php://stdout', 'w'); if (!$sock_stdout) { throw new Exception("Unable to open stdout."); } $socket_channel = new PhutilSocketChannel( $sock_stdin, $sock_stdout); $metrics_channel = new PhutilMetricsChannel($socket_channel); $workflow->setIOChannel($metrics_channel); $err = $workflow->execute($args); $metrics_channel->flush(); } catch (Exception $ex) { echo "phabricator-ssh-exec: ".$ex->getMessage()."\n"; exit(1); }