pssht  latest
SSH server library written in PHP
REQUEST.php
1 <?php
2 
3 /*
4 * This file is part of pssht.
5 *
6 * (c) François Poirotte <clicky@erebot.net>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 
13 
16 
21 {
23  protected $methods;
24 
26  protected $connection;
27 
34  public function __construct(array $methods)
35  {
36  $method = new \fpoirotte\Pssht\Authentication\None();
37  $realMethods = array($method->getName() => $method);
38  foreach ($methods as $method) {
39  if (!($method instanceof AuthenticationInterface)) {
40  throw new \InvalidArgumentException();
41  }
42  $realMethods[$method->getName()] = $method;
43  }
44 
45  $this->methods = $realMethods;
46  $this->connection = null;
47  }
48 
49  // SSH_MSG_USERAUTH_REQUEST = 50
50  public function handle(
51  $msgType,
52  \fpoirotte\Pssht\Wire\Decoder $decoder,
53  \fpoirotte\Pssht\Transport $transport,
54  array &$context
55  ) {
56  if ($this->connection !== null) {
57  // Silently ignore subsequent authentication requests
58  // after a successful authentication took place.
59  return true;
60  }
61 
62  $encoder = new \fpoirotte\Pssht\Wire\Encoder();
63  $user = $decoder->decodeString();
64  $service = $decoder->decodeString();
65  $method = $decoder->decodeString();
66 
67  $encoder->encodeString($user);
68  $encoder->encodeString($service);
69  $encoder->encodeString($method);
70  $decoder->getBuffer()->unget($encoder->getBuffer()->get(0));
71 
72  if (!isset($context['authMethods'])) {
73  $context['authMethods'] = $this->methods;
74  }
75 
76  if (!isset($context['banner'])) {
77  $context['banner'] = (string) $transport->getBanner();
78  if ($context['banner'] !== '') {
79  $response = new \fpoirotte\Pssht\Messages\USERAUTH\BANNER($context['banner']);
80  $transport->writeMessage($response);
81  }
82  }
83 
84  if (!isset($context['authMethods'][$method])) {
85  return $this->failure($transport, $context);
86  }
87 
88  $messagesCls = array(
89  'none' =>
90  '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\None',
91  'hostbased' =>
92  '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\HostBased',
93  'password' =>
94  '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\Password',
95  'publickey' =>
96  '\\fpoirotte\\Pssht\\Messages\\USERAUTH\\REQUEST\\PublicKey',
97  );
98  $methodObj = $context['authMethods'][$method];
99  $message = $messagesCls[$method]::unserialize($decoder);
100 
101  switch ($methodObj->check($message, $transport, $context)) {
103  return true;
104 
106  return $this->failure($transport, $context);
107 
109  break;
110 
111  default:
112  throw new \RuntimeException();
113  }
114 
115  switch ($methodObj->authenticate($message, $transport, $context)) {
117  unset($context['authMethods'][$method]);
118  // Do not break.
119 
121  return $this->failure($transport, $context);
122 
124  break;
125 
126  default:
127  throw new \RuntimeException();
128  }
129 
130  unset($context['authMethods'][$method]);
131  $response = new \fpoirotte\Pssht\Messages\USERAUTH\SUCCESS();
132  $this->connection = new \fpoirotte\Pssht\Connection($transport);
133  $transport->writeMessage($response);
134 
135  $compressor = $transport->getCompressor();
136  if ($compressor instanceof \fpoirotte\Pssht\Compression\DelayedCompressionInterface) {
137  $compressor->setAuthenticated();
138  }
139  $uncompressor = $transport->getUncompressor();
140  if ($uncompressor instanceof \fpoirotte\Pssht\Compression\DelayedCompressionInterface) {
141  $uncompressor->setAuthenticated();
142  }
143 
144  return true;
145  }
146 
165  protected function failure(
166  \fpoirotte\Pssht\Transport $transport,
167  array &$context,
168  $partial = false
169  ) {
170  if (!is_bool($partial)) {
171  throw new \InvalidArgumentException();
172  }
173 
174  $remaining = $context['authMethods'];
175  unset($remaining['none']);
176  $remaining = array_keys($remaining);
177  $response = new \fpoirotte\Pssht\Messages\USERAUTH\FAILURE($remaining, $partial);
178  $transport->writeMessage($response);
179  return true;
180  }
181 }
$methods
Allowed authentication methods.
Definition: REQUEST.php:23
const AUTH_REMOVE
The authentication failed and the method should be removed.
handle($msgType,\fpoirotte\Pssht\Wire\Decoder $decoder,\fpoirotte\Pssht\Transport $transport, array &$context)
Definition: REQUEST.php:50
const AUTH_ACCEPT
The authentication was successful.
failure(\fpoirotte\Pssht\Transport $transport, array &$context, $partial=false)
Definition: REQUEST.php:165