Beispiel #1
0
 public function serialize(\fpoirotte\Pssht\Wire\Encoder $encoder)
 {
     parent::serialize($encoder);
     $encoder->encodeBoolean($this->signature !== null);
     $encoder->encodeString($this->algorithm);
     $encoder->encodeString($this->key);
     if ($this->signature !== null) {
         $encoder2 = new \fpoirotte\Pssht\Wire\Encoder();
         $encoder2->encodeString($this->algorithm);
         $encoder2->encodeString($this->signature);
         $encoder->encodeString($encoder2->getBuffer()->get(0));
     }
     return $this;
 }
Beispiel #2
0
 public function serialize(\fpoirotte\Pssht\Wire\Encoder $encoder)
 {
     parent::serialize($encoder);
     $encoder->encodeString($this->algorithm);
     $encoder->encodeString($this->key);
     $encoder->encodeString($this->hostname);
     $encoder->encodeString($this->remoteUser);
     // Special handling of the signature.
     $encoder2 = new \fpoirotte\Pssht\Wire\Encoder();
     $encoder2->encodeString($this->algorithm);
     $encoder2->encodeString($this->signature);
     $encoder->encodeString($encoder2->getBuffer()->get(0));
     return $this;
 }
Beispiel #3
0
 public function authenticate(\fpoirotte\Pssht\Messages\USERAUTH\REQUEST\Base $message, \fpoirotte\Pssht\Transport $transport, array &$context)
 {
     if (!$message instanceof \fpoirotte\Pssht\Messages\USERAUTH\REQUEST\PublicKey) {
         throw new \InvalidArgumentException();
     }
     if ($message->getSignature() === null) {
         return self::AUTH_REJECT;
     }
     $logging = \Plop\Plop::getInstance();
     $reverse = gethostbyaddr($transport->getAddress());
     $algos = \fpoirotte\Pssht\Algorithms::factory();
     $cls = $algos->getClass('PublicKey', $message->getAlgorithm());
     if ($cls === null || !$this->store->exists($message->getUserName(), $message->getKey())) {
         $logging->info('Rejected public key connection from remote host "%(reverse)s" ' . 'to "%(luser)s" (unsupported key)', array('luser' => escape($message->getUserName()), 'reverse' => $reverse));
         return self::AUTH_REJECT;
     }
     $key = $cls::loadPublic(base64_encode($message->getKey()));
     $encoder = new \fpoirotte\Pssht\Wire\Encoder();
     $encoder->encodeString($context['DH']->getExchangeHash());
     $encoder->encodeBytes(chr(\fpoirotte\Pssht\Messages\USERAUTH\REQUEST\Base::getMessageId()));
     $encoder->encodeString($message->getUserName());
     $encoder->encodeString($message->getServiceName());
     $encoder->encodeString(static::getName());
     $encoder->encodeBoolean(true);
     $encoder->encodeString($message->getAlgorithm());
     $encoder->encodeString($message->getKey());
     if ($key->check($encoder->getBuffer()->get(0), $message->getSignature())) {
         $logging->info('Accepted public key connection from remote host "%(reverse)s" ' . 'to "%(luser)s" (using "%(algorithm)s" algorithm)', array('luser' => escape($message->getUserName()), 'reverse' => $reverse, 'algorithm' => escape($message->getAlgorithm())));
         return self::AUTH_ACCEPT;
     }
     $logging->info('Rejected public key connection from remote host "%(reverse)s" ' . 'to "%(luser)s" (invalid signature)', array('luser' => escape($message->getUserName()), 'reverse' => $reverse));
     return self::AUTH_REJECT;
 }
Beispiel #4
0
 public function handle($msgType, \fpoirotte\Pssht\Wire\Decoder $decoder, \fpoirotte\Pssht\Transport $transport, array &$context)
 {
     $encoder = new \fpoirotte\Pssht\Wire\Encoder();
     $channel = $decoder->decodeUint32();
     $type = $decoder->decodeString();
     $wantsReply = $decoder->decodeBoolean();
     $encoder->encodeUint32($channel);
     $encoder->encodeString($type);
     $encoder->encodeBoolean($wantsReply);
     $decoder->getBuffer()->unget($encoder->getBuffer()->get(0));
     $remoteChannel = $this->connection->getChannel($channel);
     switch ($type) {
         case 'exec':
         case 'shell':
         case 'pty-req':
             // Normalize the name.
             // Eg. "pty-req" becomes "PtyReq".
             $cls = str_replace(' ', '', ucwords(str_replace('-', ' ', $type)));
             $cls = '\\fpoirotte\\Pssht\\Messages\\CHANNEL\\REQUEST\\' . $cls;
             $message = $cls::unserialize($decoder);
             break;
         default:
             if ($wantsReply) {
                 $response = new \fpoirotte\Pssht\Messages\CHANNEL\FAILURE($remoteChannel);
                 $transport->writeMessage($response);
             }
             return true;
     }
     if (!$wantsReply) {
         return true;
     }
     if (in_array($type, array('shell', 'exec'), true)) {
         $response = new \fpoirotte\Pssht\Messages\CHANNEL\SUCCESS($remoteChannel);
     } else {
         $response = new \fpoirotte\Pssht\Messages\CHANNEL\FAILURE($remoteChannel);
     }
     $transport->writeMessage($response);
     if (in_array($type, array('shell', 'exec'), true)) {
         $callable = $transport->getApplicationFactory();
         if ($callable !== null) {
             call_user_func($callable, $transport, $this->connection, $message);
         }
     }
     return true;
 }
Beispiel #5
0
 public function authenticate(\fpoirotte\Pssht\Messages\USERAUTH\REQUEST\Base $message, \fpoirotte\Pssht\Transport $transport, array &$context)
 {
     if (!$message instanceof \fpoirotte\Pssht\Messages\USERAUTH\REQUEST\HostBased) {
         throw new \InvalidArgumentException();
     }
     $logging = \Plop\Plop::getInstance();
     $reverse = gethostbyaddr($transport->getAddress());
     $untrustedHost = rtrim($message->getHostname(), '.');
     $algos = \fpoirotte\Pssht\Algorithms::factory();
     $cls = $algos->getClass('PublicKey', $message->getAlgorithm());
     if ($cls === null || !$this->store->exists($message->getUserName(), $message->getKey())) {
         $logging->info('Rejected host based connection from %(ruser)s@%(rhost)s ' . '(%(ruser)s@%(reverse)s) to "%(luser)s" ' . '(unsupported key)', array('ruser' => escape($message->getRemoteUser()), 'luser' => escape($message->getUserName()), 'rhost' => escape($untrustedHost), 'reverse' => $reverse));
         return self::AUTH_REMOVE;
     }
     $key = $cls::loadPublic(base64_encode($message->getKey()));
     $encoder = new \fpoirotte\Pssht\Wire\Encoder();
     $encoder->encodeString($context['DH']->getExchangeHash());
     $encoder->encodeBytes(chr(\fpoirotte\Pssht\Messages\USERAUTH\REQUEST\Base::getMessageId()));
     $encoder->encodeString($message->getUserName());
     $encoder->encodeString($message->getServiceName());
     $encoder->encodeString(static::getName());
     $encoder->encodeString($message->getAlgorithm());
     $encoder->encodeString($message->getKey());
     $encoder->encodeString($message->getHostname());
     $encoder->encodeString($message->getRemoteUser());
     if (!$key->check($encoder->getBuffer()->get(0), $message->getSignature())) {
         $logging->warn('Rejected host based connection from %(ruser)s@%(rhost)s ' . '(%(ruser)s@%(reverse)s) to "%(luser)s" (invalid signature)', array('ruser' => escape($message->getRemoteUser()), 'luser' => escape($message->getUserName()), 'rhost' => escape($untrustedHost), 'reverse' => $reverse));
         return self::AUTH_REJECT;
     }
     if ($reverse !== $untrustedHost) {
         $logging->warning('Ignored reverse lookup mismatch for %(address)s (' . '"%(reverse)s" vs. "%(untrusted)s")', array('address' => $transport->getAddress(), 'reverse' => $reverse, 'untrusted' => escape($untrustedHost)));
     }
     if ($message->getUserName() !== $message->getRemoteUser()) {
         $logging->warning('Rejected host based connection from %(ruser)s@%(rhost)s ' . '(%(ruser)s@%(reverse)s): remote user does not match ' . 'local user (%(luser)s)', array('ruser' => escape($message->getRemoteUser()), 'luser' => escape($message->getUserName()), 'rhost' => escape($untrustedHost), 'reverse' => $reverse));
         return self::AUTH_REMOVE;
     }
     $logging->info('Accepted host based connection ' . 'from "%(ruser)s@%(rhost)s" (%(ruser)s@%(reverse)s) ' . 'to "%(luser)s" (using "%(algorithm)s" algorithm)', array('ruser' => escape($message->getRemoteUser()), 'luser' => escape($message->getUserName()), 'rhost' => escape($untrustedHost), 'reverse' => $reverse, 'algorithm' => escape($message->getAlgorithm())));
     return self::AUTH_ACCEPT;
 }
Beispiel #6
0
 public function handle($msgType, \fpoirotte\Pssht\Wire\Decoder $decoder, \fpoirotte\Pssht\Transport $transport, array &$context)
 {
     if ($this->connection !== null) {
         // Silently ignore subsequent authentication requests
         // after a successful authentication took place.
         return true;
     }
     $encoder = new \fpoirotte\Pssht\Wire\Encoder();
     $user = $decoder->decodeString();
     $service = $decoder->decodeString();
     $method = $decoder->decodeString();
     $encoder->encodeString($user);
     $encoder->encodeString($service);
     $encoder->encodeString($method);
     $decoder->getBuffer()->unget($encoder->getBuffer()->get(0));
     if (!isset($context['authMethods'])) {
         $context['authMethods'] = $this->methods;
     }
     if (!isset($context['banner'])) {
         $context['banner'] = (string) $transport->getBanner();
         if ($context['banner'] !== '') {
             $response = new \fpoirotte\Pssht\Messages\USERAUTH\BANNER($context['banner']);
             $transport->writeMessage($response);
         }
     }
     if (!isset($context['authMethods'][$method])) {
         return $this->failure($transport, $context);
     }
     $messagesCls = array('none' => '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\None', 'hostbased' => '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\HostBased', 'password' => '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\Password', 'publickey' => '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\PublicKey');
     $methodObj = $context['authMethods'][$method];
     $message = $messagesCls[$method]::unserialize($decoder);
     switch ($methodObj->check($message, $transport, $context)) {
         case AuthenticationInterface::CHECK_IGNORE:
             return true;
         case AuthenticationInterface::CHECK_REJECT:
             return $this->failure($transport, $context);
         case AuthenticationInterface::CHECK_OK:
             break;
         default:
             throw new \RuntimeException();
     }
     switch ($methodObj->authenticate($message, $transport, $context)) {
         case AuthenticationInterface::AUTH_REMOVE:
             unset($context['authMethods'][$method]);
             // Do not break.
         // Do not break.
         case AuthenticationInterface::AUTH_REJECT:
             return $this->failure($transport, $context);
         case AuthenticationInterface::AUTH_ACCEPT:
             break;
         default:
             throw new \RuntimeException();
     }
     unset($context['authMethods'][$method]);
     $response = new \fpoirotte\Pssht\Messages\USERAUTH\SUCCESS();
     $this->connection = new \fpoirotte\Pssht\Connection($transport);
     $transport->writeMessage($response);
     $compressor = $transport->getCompressor();
     if ($compressor instanceof \fpoirotte\Pssht\DelayedCompressionInterface) {
         $compressor->setAuthenticated();
     }
     $uncompressor = $transport->getUncompressor();
     if ($uncompressor instanceof \fpoirotte\Pssht\DelayedCompressionInterface) {
         $uncompressor->setAuthenticated();
     }
     return true;
 }