1<?php
2
3namespace Safe;
4
5use Safe\Exceptions\Ssh2Exception;
6
7/**
8 * Authenticate over SSH using the ssh agent
9 *
10 * @param resource $session An SSH connection link identifier, obtained from a call to
11 * ssh2_connect.
12 * @param string $username Remote user name.
13 * @throws Ssh2Exception
14 *
15 */
16function ssh2_auth_agent($session, string $username): void
17{
18    error_clear_last();
19    $result = \ssh2_auth_agent($session, $username);
20    if ($result === false) {
21        throw Ssh2Exception::createFromPhpError();
22    }
23}
24
25
26/**
27 * Authenticate using a public hostkey read from a file.
28 *
29 * @param resource $session An SSH connection link identifier, obtained from a call to
30 * ssh2_connect.
31 * @param string $username
32 * @param string $hostname
33 * @param string $pubkeyfile
34 * @param string $privkeyfile
35 * @param string $passphrase If privkeyfile is encrypted (which it should
36 * be), the passphrase must be provided.
37 * @param string $local_username If local_username is omitted, then the value
38 * for username will be used for it.
39 * @throws Ssh2Exception
40 *
41 */
42function ssh2_auth_hostbased_file($session, string $username, string $hostname, string $pubkeyfile, string $privkeyfile, string $passphrase = null, string $local_username = null): void
43{
44    error_clear_last();
45    if ($local_username !== null) {
46        $result = \ssh2_auth_hostbased_file($session, $username, $hostname, $pubkeyfile, $privkeyfile, $passphrase, $local_username);
47    } elseif ($passphrase !== null) {
48        $result = \ssh2_auth_hostbased_file($session, $username, $hostname, $pubkeyfile, $privkeyfile, $passphrase);
49    } else {
50        $result = \ssh2_auth_hostbased_file($session, $username, $hostname, $pubkeyfile, $privkeyfile);
51    }
52    if ($result === false) {
53        throw Ssh2Exception::createFromPhpError();
54    }
55}
56
57
58/**
59 * Authenticate over SSH using a plain password. Since version 0.12 this function
60 * also supports keyboard_interactive method.
61 *
62 * @param resource $session An SSH connection link identifier, obtained from a call to
63 * ssh2_connect.
64 * @param string $username Remote user name.
65 * @param string $password Password for username
66 * @throws Ssh2Exception
67 *
68 */
69function ssh2_auth_password($session, string $username, string $password): void
70{
71    error_clear_last();
72    $result = \ssh2_auth_password($session, $username, $password);
73    if ($result === false) {
74        throw Ssh2Exception::createFromPhpError();
75    }
76}
77
78
79/**
80 * Authenticate using a public key read from a file.
81 *
82 * @param resource $session An SSH connection link identifier, obtained from a call to
83 * ssh2_connect.
84 * @param string $username
85 * @param string $pubkeyfile The public key file needs to be in OpenSSH's format. It should look something like:
86 *
87 * ssh-rsa AAAAB3NzaC1yc2EAAA....NX6sqSnHA8= rsa-key-20121110
88 * @param string $privkeyfile
89 * @param string $passphrase If privkeyfile is encrypted (which it should
90 * be), the passphrase must be provided.
91 * @throws Ssh2Exception
92 *
93 */
94function ssh2_auth_pubkey_file($session, string $username, string $pubkeyfile, string $privkeyfile, string $passphrase = null): void
95{
96    error_clear_last();
97    if ($passphrase !== null) {
98        $result = \ssh2_auth_pubkey_file($session, $username, $pubkeyfile, $privkeyfile, $passphrase);
99    } else {
100        $result = \ssh2_auth_pubkey_file($session, $username, $pubkeyfile, $privkeyfile);
101    }
102    if ($result === false) {
103        throw Ssh2Exception::createFromPhpError();
104    }
105}
106
107
108/**
109 * Establish a connection to a remote SSH server.
110 *
111 * Once connected, the client should verify the server's hostkey using
112 * ssh2_fingerprint, then authenticate using either
113 * password or public key.
114 *
115 * @param string $host
116 * @param int $port
117 * @param array $methods methods may be an associative array with up to four parameters
118 * as described below.
119 *
120 *
121 * methods may be an associative array
122 * with any or all of the following parameters.
123 *
124 *
125 *
126 * Index
127 * Meaning
128 * Supported Values*
129 *
130 *
131 *
132 *
133 * kex
134 *
135 * List of key exchange methods to advertise, comma separated
136 * in order of preference.
137 *
138 *
139 * diffie-hellman-group1-sha1,
140 * diffie-hellman-group14-sha1, and
141 * diffie-hellman-group-exchange-sha1
142 *
143 *
144 *
145 * hostkey
146 *
147 * List of hostkey methods to advertise, comma separated
148 * in order of preference.
149 *
150 *
151 * ssh-rsa and
152 * ssh-dss
153 *
154 *
155 *
156 * client_to_server
157 *
158 * Associative array containing crypt, compression, and
159 * message authentication code (MAC) method preferences
160 * for messages sent from client to server.
161 *
162 *
163 *
164 *
165 * server_to_client
166 *
167 * Associative array containing crypt, compression, and
168 * message authentication code (MAC) method preferences
169 * for messages sent from server to client.
170 *
171 *
172 *
173 *
174 *
175 *
176 *
177 * * - Supported Values are dependent on methods supported by underlying library.
178 * See libssh2 documentation for additional
179 * information.
180 *
181 *
182 *
183 * client_to_server and
184 * server_to_client may be an associative array
185 * with any or all of the following parameters.
186 *
187 *
188 *
189 *
190 * Index
191 * Meaning
192 * Supported Values*
193 *
194 *
195 *
196 *
197 * crypt
198 * List of crypto methods to advertise, comma separated
199 * in order of preference.
200 *
201 * rijndael-cbc@lysator.liu.se,
202 * aes256-cbc,
203 * aes192-cbc,
204 * aes128-cbc,
205 * 3des-cbc,
206 * blowfish-cbc,
207 * cast128-cbc,
208 * arcfour, and
209 * none**
210 *
211 *
212 *
213 * comp
214 * List of compression methods to advertise, comma separated
215 * in order of preference.
216 *
217 * zlib and
218 * none
219 *
220 *
221 *
222 * mac
223 * List of MAC methods to advertise, comma separated
224 * in order of preference.
225 *
226 * hmac-sha1,
227 * hmac-sha1-96,
228 * hmac-ripemd160,
229 * hmac-ripemd160@openssh.com, and
230 * none**
231 *
232 *
233 *
234 *
235 *
236 *
237 *
238 * Crypt and MAC method "none"
239 *
240 * For security reasons, none is disabled by the underlying
241 * libssh2 library unless explicitly enabled
242 * during build time by using the appropriate ./configure options.  See documentation
243 * for the underlying library for more information.
244 *
245 *
246 *
247 * For security reasons, none is disabled by the underlying
248 * libssh2 library unless explicitly enabled
249 * during build time by using the appropriate ./configure options.  See documentation
250 * for the underlying library for more information.
251 * @param array $callbacks callbacks may be an associative array with any
252 * or all of the following parameters.
253 *
254 *
255 * Callbacks parameters
256 *
257 *
258 *
259 *
260 * Index
261 * Meaning
262 * Prototype
263 *
264 *
265 *
266 *
267 * ignore
268 *
269 * Name of function to call when an
270 * SSH2_MSG_IGNORE packet is received
271 *
272 * void ignore_cb($message)
273 *
274 *
275 * debug
276 *
277 * Name of function to call when an
278 * SSH2_MSG_DEBUG packet is received
279 *
280 * void debug_cb($message, $language, $always_display)
281 *
282 *
283 * macerror
284 *
285 * Name of function to call when a packet is received but the
286 * message authentication code failed.  If the callback returns
287 * TRUE, the mismatch will be ignored, otherwise the connection
288 * will be terminated.
289 *
290 * bool macerror_cb($packet)
291 *
292 *
293 * disconnect
294 *
295 * Name of function to call when an
296 * SSH2_MSG_DISCONNECT packet is received
297 *
298 * void disconnect_cb($reason, $message, $language)
299 *
300 *
301 *
302 *
303 * @return resource Returns a resource on success.
304 * @throws Ssh2Exception
305 *
306 */
307function ssh2_connect(string $host, int $port = 22, array $methods = null, array $callbacks = null)
308{
309    error_clear_last();
310    if ($callbacks !== null) {
311        $result = \ssh2_connect($host, $port, $methods, $callbacks);
312    } elseif ($methods !== null) {
313        $result = \ssh2_connect($host, $port, $methods);
314    } else {
315        $result = \ssh2_connect($host, $port);
316    }
317    if ($result === false) {
318        throw Ssh2Exception::createFromPhpError();
319    }
320    return $result;
321}
322
323
324/**
325 * Close a connection to a remote SSH server.
326 *
327 * @param resource $session An SSH connection link identifier, obtained from a call to
328 * ssh2_connect.
329 * @throws Ssh2Exception
330 *
331 */
332function ssh2_disconnect($session): void
333{
334    error_clear_last();
335    $result = \ssh2_disconnect($session);
336    if ($result === false) {
337        throw Ssh2Exception::createFromPhpError();
338    }
339}
340
341
342/**
343 * Execute a command at the remote end and allocate a channel for it.
344 *
345 * @param resource $session An SSH connection link identifier, obtained from a call to
346 * ssh2_connect.
347 * @param string $command
348 * @param string $pty
349 * @param array $env env may be passed as an associative array of
350 * name/value pairs to set in the target environment.
351 * @param int $width Width of the virtual terminal.
352 * @param int $height Height of the virtual terminal.
353 * @param int $width_height_type width_height_type should be one of
354 * SSH2_TERM_UNIT_CHARS or
355 * SSH2_TERM_UNIT_PIXELS.
356 * @return resource Returns a stream on success.
357 * @throws Ssh2Exception
358 *
359 */
360function ssh2_exec($session, string $command, string $pty = null, array $env = null, int $width = 80, int $height = 25, int $width_height_type = SSH2_TERM_UNIT_CHARS)
361{
362    error_clear_last();
363    if ($width_height_type !== SSH2_TERM_UNIT_CHARS) {
364        $result = \ssh2_exec($session, $command, $pty, $env, $width, $height, $width_height_type);
365    } elseif ($height !== 25) {
366        $result = \ssh2_exec($session, $command, $pty, $env, $width, $height);
367    } elseif ($width !== 80) {
368        $result = \ssh2_exec($session, $command, $pty, $env, $width);
369    } elseif ($env !== null) {
370        $result = \ssh2_exec($session, $command, $pty, $env);
371    } elseif ($pty !== null) {
372        $result = \ssh2_exec($session, $command, $pty);
373    } else {
374        $result = \ssh2_exec($session, $command);
375    }
376    if ($result === false) {
377        throw Ssh2Exception::createFromPhpError();
378    }
379    return $result;
380}
381
382
383/**
384 *
385 *
386 * @param resource $pkey Publickey Subsystem resource created by ssh2_publickey_init.
387 * @param string $algoname Publickey algorithm (e.g.): ssh-dss, ssh-rsa
388 * @param string $blob Publickey blob as raw binary data
389 * @param bool $overwrite If the specified key already exists, should it be overwritten?
390 * @param array $attributes Associative array of attributes to assign to this public key.
391 * Refer to ietf-secsh-publickey-subsystem for a list of supported attributes.
392 * To mark an attribute as mandatory, precede its name with an asterisk.
393 * If the server is unable to support an attribute marked mandatory,
394 * it will abort the add process.
395 * @throws Ssh2Exception
396 *
397 */
398function ssh2_publickey_add($pkey, string $algoname, string $blob, bool $overwrite = false, array $attributes = null): void
399{
400    error_clear_last();
401    if ($attributes !== null) {
402        $result = \ssh2_publickey_add($pkey, $algoname, $blob, $overwrite, $attributes);
403    } else {
404        $result = \ssh2_publickey_add($pkey, $algoname, $blob, $overwrite);
405    }
406    if ($result === false) {
407        throw Ssh2Exception::createFromPhpError();
408    }
409}
410
411
412/**
413 * Request the Publickey subsystem from an already connected SSH2 server.
414 *
415 * The publickey subsystem allows an already connected and authenticated
416 * client to manage the list of authorized public keys stored on the
417 * target server in an implementation agnostic manner.
418 * If the remote server does not support the publickey subsystem,
419 * the ssh2_publickey_init function will return FALSE.
420 *
421 * @param resource $session
422 * @return resource Returns an SSH2 Publickey Subsystem resource for use
423 * with all other ssh2_publickey_*() methods.
424 * @throws Ssh2Exception
425 *
426 */
427function ssh2_publickey_init($session)
428{
429    error_clear_last();
430    $result = \ssh2_publickey_init($session);
431    if ($result === false) {
432        throw Ssh2Exception::createFromPhpError();
433    }
434    return $result;
435}
436
437
438/**
439 * Removes an authorized publickey.
440 *
441 * @param resource $pkey Publickey Subsystem Resource
442 * @param string $algoname Publickey algorithm (e.g.): ssh-dss, ssh-rsa
443 * @param string $blob Publickey blob as raw binary data
444 * @throws Ssh2Exception
445 *
446 */
447function ssh2_publickey_remove($pkey, string $algoname, string $blob): void
448{
449    error_clear_last();
450    $result = \ssh2_publickey_remove($pkey, $algoname, $blob);
451    if ($result === false) {
452        throw Ssh2Exception::createFromPhpError();
453    }
454}
455
456
457/**
458 * Copy a file from the remote server to the local filesystem using the SCP protocol.
459 *
460 * @param resource $session An SSH connection link identifier, obtained from a call to
461 * ssh2_connect.
462 * @param string $remote_file Path to the remote file.
463 * @param string $local_file Path to the local file.
464 * @throws Ssh2Exception
465 *
466 */
467function ssh2_scp_recv($session, string $remote_file, string $local_file): void
468{
469    error_clear_last();
470    $result = \ssh2_scp_recv($session, $remote_file, $local_file);
471    if ($result === false) {
472        throw Ssh2Exception::createFromPhpError();
473    }
474}
475
476
477/**
478 * Copy a file from the local filesystem to the remote server using the SCP protocol.
479 *
480 * @param resource $session An SSH connection link identifier, obtained from a call to
481 * ssh2_connect.
482 * @param string $local_file Path to the local file.
483 * @param string $remote_file Path to the remote file.
484 * @param int $create_mode The file will be created with the mode specified by
485 * create_mode.
486 * @throws Ssh2Exception
487 *
488 */
489function ssh2_scp_send($session, string $local_file, string $remote_file, int $create_mode = 0644): void
490{
491    error_clear_last();
492    $result = \ssh2_scp_send($session, $local_file, $remote_file, $create_mode);
493    if ($result === false) {
494        throw Ssh2Exception::createFromPhpError();
495    }
496}
497
498
499/**
500 * Attempts to change the mode of the specified file to that given in
501 * mode.
502 *
503 * @param resource $sftp An SSH2 SFTP resource opened by ssh2_sftp.
504 * @param string $filename Path to the file.
505 * @param int $mode Permissions on the file. See the chmod for more details on this parameter.
506 * @throws Ssh2Exception
507 *
508 */
509function ssh2_sftp_chmod($sftp, string $filename, int $mode): void
510{
511    error_clear_last();
512    $result = \ssh2_sftp_chmod($sftp, $filename, $mode);
513    if ($result === false) {
514        throw Ssh2Exception::createFromPhpError();
515    }
516}
517
518
519/**
520 * Creates a directory on the remote file server with permissions set to
521 * mode.
522 *
523 * This function is similar to using mkdir with the
524 * ssh2.sftp:// wrapper.
525 *
526 * @param resource $sftp An SSH2 SFTP resource opened by ssh2_sftp.
527 * @param string $dirname Path of the new directory.
528 * @param int $mode Permissions on the new directory.
529 * @param bool $recursive If recursive is TRUE any parent directories
530 * required for dirname will be automatically created as well.
531 * @throws Ssh2Exception
532 *
533 */
534function ssh2_sftp_mkdir($sftp, string $dirname, int $mode = 0777, bool $recursive = false): void
535{
536    error_clear_last();
537    $result = \ssh2_sftp_mkdir($sftp, $dirname, $mode, $recursive);
538    if ($result === false) {
539        throw Ssh2Exception::createFromPhpError();
540    }
541}
542
543
544/**
545 * Renames a file on the remote filesystem.
546 *
547 * @param resource $sftp An SSH2 SFTP resource opened by ssh2_sftp.
548 * @param string $from The current file that is being renamed.
549 * @param string $to The new file name that replaces from.
550 * @throws Ssh2Exception
551 *
552 */
553function ssh2_sftp_rename($sftp, string $from, string $to): void
554{
555    error_clear_last();
556    $result = \ssh2_sftp_rename($sftp, $from, $to);
557    if ($result === false) {
558        throw Ssh2Exception::createFromPhpError();
559    }
560}
561
562
563/**
564 * Removes a directory from the remote file server.
565 *
566 * This function is similar to using rmdir with the
567 * ssh2.sftp:// wrapper.
568 *
569 * @param resource $sftp An SSH2 SFTP resource opened by ssh2_sftp.
570 * @param string $dirname
571 * @throws Ssh2Exception
572 *
573 */
574function ssh2_sftp_rmdir($sftp, string $dirname): void
575{
576    error_clear_last();
577    $result = \ssh2_sftp_rmdir($sftp, $dirname);
578    if ($result === false) {
579        throw Ssh2Exception::createFromPhpError();
580    }
581}
582
583
584/**
585 * Creates a symbolic link named link on the remote
586 * filesystem pointing to target.
587 *
588 * @param resource $sftp An SSH2 SFTP resource opened by ssh2_sftp.
589 * @param string $target Target of the symbolic link.
590 * @param string $link
591 * @throws Ssh2Exception
592 *
593 */
594function ssh2_sftp_symlink($sftp, string $target, string $link): void
595{
596    error_clear_last();
597    $result = \ssh2_sftp_symlink($sftp, $target, $link);
598    if ($result === false) {
599        throw Ssh2Exception::createFromPhpError();
600    }
601}
602
603
604/**
605 * Deletes a file on the remote filesystem.
606 *
607 * @param resource $sftp An SSH2 SFTP resource opened by ssh2_sftp.
608 * @param string $filename
609 * @throws Ssh2Exception
610 *
611 */
612function ssh2_sftp_unlink($sftp, string $filename): void
613{
614    error_clear_last();
615    $result = \ssh2_sftp_unlink($sftp, $filename);
616    if ($result === false) {
617        throw Ssh2Exception::createFromPhpError();
618    }
619}
620
621
622/**
623 * Request the SFTP subsystem from an already connected SSH2 server.
624 *
625 * @param resource $session An SSH connection link identifier, obtained from a call to
626 * ssh2_connect.
627 * @return resource This method returns an SSH2 SFTP resource for use with
628 * all other ssh2_sftp_*() methods and the
629 * ssh2.sftp:// fopen wrapper.
630 * @throws Ssh2Exception
631 *
632 */
633function ssh2_sftp($session)
634{
635    error_clear_last();
636    $result = \ssh2_sftp($session);
637    if ($result === false) {
638        throw Ssh2Exception::createFromPhpError();
639    }
640    return $result;
641}
642