/** * Dispath one message * @param callback if not NULL, each packet will be processed with this function; * in case that function returns TRUE, packet won't be processed * by dispather, but will be returned; * function has to accept one argument (whole packet /with * leading packet type byte) and return boolean * * @return string|NULL string if packet was catched by return filter, NULL * otherwise */ public function dispatch($return_filter = NULL) { if ($return_filter !== NULL && !is_callable($return_filter)) { throw new Error('Given callback is not callable.'); } $packet = $this->protocol->receive(); if ($return_filter !== NULL) { if ($return_filter($packet)) { return $packet; } } list($packet_type) = parse('b', $packet); if (!isset($this->callbacks[$packet_type])) { $this->protocol->send('bu', SSH_MSG_UNIMPLEMENTED, $this->protocol->getReceiveSeq()); return NULL; } $callback = $this->callbacks[$packet_type]; if ($callback === NULL) { return NULL; } $callback($packet); return NULL; }
/** * @param string * @return bool */ public function authenticate(PacketProtocol $protocol, $packet) { if ($this->user) { $protocol->send('bnb', SSH_MSG_USERAUTH_FAILURE, array(), 0); return FALSE; } list($user, $service, $method) = parse('sss', $packet); if ($service !== 'ssh-connection' || $method !== 'publickey') { $protocol->send('bnb', SSH_MSG_USERAUTH_FAILURE, array('publickey'), 0); return FALSE; } list($signed, $publickey_algorithm, $publickey) = parse('bss', $packet); // FIXME: currently on ssh-rsa supported if ($publickey_algorithm !== 'ssh-rsa' || ($content = @file_get_contents($this->dir . '/' . $user)) === FALSE) { $protocol->send('bnb', SSH_MSG_USERAUTH_FAILURE, array('publickey'), 0); return FALSE; } if (!$signed) { $protocol->send('bss', SSH_MSG_USERAUTH_PK_OK, $publickey_algorithm, $publickey); return FALSE; } list($signature) = parse('s', $packet); list($known_publickey_algorithm, $known_publickey, ) = explode(' ', trim($content), 3); $known_publickey = base64_decode($known_publickey); if (!($known_publickey_algorithm === $publickey_algorithm && $known_publickey === $publickey)) { $protocol->send('bnb', SSH_MSG_USERAUTH_FAILURE, array('publickey'), 0); return FALSE; } $data = format('sbsssbss', $protocol->getSessionId(), SSH_MSG_USERAUTH_REQUEST, $user, $service, 'publickey', 1, $publickey_algorithm, $publickey); if (verify($publickey, $data, $signature)) { $protocol->send('b', SSH_MSG_USERAUTH_SUCCESS); $this->user = $user; $this->service = $service; return TRUE; } return FALSE; }
/** * @param string * @return int */ public function stream_write($data) { if ($this->window_size < strlen($data)) { $this->protocol->send('buu', SSH_MSG_CHANNEL_WINDOW_ADJUST, $this->channel, 0x7fffffff); } $this->protocol->send('buus', SSH_MSG_CHANNEL_EXTENDED_DATA, $this->channel, SSH_EXTENDED_DATA_STDERR, $data); $this->window_size -= strlen($data); return strlen($data); }