Compare commits

...

209 commits

Author SHA1 Message Date
Bill Church
9c0ba04b31
Update action-test.yml 2024-08-26 07:58:02 -04:00
Bill Church
e499287079
Update action-test.yml 2024-08-26 07:57:04 -04:00
Bill Church
2a9a6c3562
Update docker-multiplatform-tag.yml 2024-08-22 14:03:09 -04:00
Bill Church
ad5d38259c
Update docker-multiplatform-tag.yml 2024-08-22 13:49:22 -04:00
Bill Church
7c1f8fa48e
Update docker-multiplatform-tag.yml 2024-08-22 13:47:08 -04:00
Bill Church
8dd4d0fda4
Create docker-multiplatform-tag.yml 2024-08-22 13:46:42 -04:00
Bill Church
5bbfcee0b6
chore: testing 2024-07-08 16:48:17 -04:00
Bill Church
cb5c1fa809
chore: update dev env 2024-04-27 10:41:44 +00:00
Bill Church
64e86994f7
chore: bump version 2023-08-22 18:55:53 +00:00
Bill Church
a97003bac2
chore: update release workflow 2023-08-22 18:55:53 +00:00
Bill Church
2576a495cf
chore: remove json-merger add ncu 2023-08-22 18:55:52 +00:00
Bill Church
d2ea50a0f2
chore: update dev environment 2023-08-22 18:55:52 +00:00
Bill Church
3246df75b6
fix: cols and rows were not properly assigned for terminal (#337)
* fix: set correct vars and cols property

* fix: add cols and rows to session.ssh property

* style: remove const assignment

---------

Co-authored-by: w-v <wtv@protonmail.ch>
Co-authored-by: bc 064 <87337961+bcvort@users.noreply.github.com>
2023-08-22 09:16:10 -04:00
Bill Church
acb4e42fde
docs: update confusion around docker configs #317 2023-02-06 12:37:19 -05:00
Bill Church
c3e54ef0d8
chore: dev env update 2023-02-06 09:48:25 -05:00
Bill Church
d9b6e47e88
chore(main): release webssh2 0.5.0-pre-4 (#309) 2022-08-07 08:14:28 -04:00
Bill Church
8b56826363
chore: release 0.4.7-pre-5
Release-As: 0.4.7-pre-5
2022-08-07 12:13:19 +00:00
Bill Church
476b566c08
feat: test change for release 2022-08-07 12:10:36 +00:00
Bill Church
298f45178f
chore: update workflow 2022-08-07 12:07:22 +00:00
Bill Church
adc964e823
chore: update workflow 2022-08-07 12:03:32 +00:00
Bill Church
3d06d74645
chore: update workflow 2022-08-07 12:01:02 +00:00
Bill Church
8f19909cc1
Merge branch 'main' of github.com:billchurch/webssh2 2022-08-07 11:55:26 +00:00
Bill Church
3fdba6e880
chore: update workflow to publish to npm 2022-08-07 11:55:08 +00:00
Bill Church
8c64f8e026
chore(main): release webssh2 0.4.7-pre-4 (#308) 2022-08-03 10:39:36 -04:00
Bill Church
ad9f303380
docs: add LICENSE to /app 2022-08-03 14:35:32 +00:00
Bill Church
7d4ba87bc1
chore: release 0.4.7-pre-4
Release-As: 0.4.7-pre-4
2022-08-03 14:31:52 +00:00
Bill Church
8585aba89f
chore: update changelog 2022-08-03 14:30:22 +00:00
Bill Church
3b8c7a770e
chore: update workflows 2022-08-03 14:29:47 +00:00
Bill Church
9d5a0cd12c
chore(main): release webssh2 0.4.7-pre-3 (#307) 2022-08-03 10:25:12 -04:00
Bill Church
0322b1694a
chore: update release-please workflow 2022-08-03 14:22:19 +00:00
Bill Church
3b460dda66
Merge branch 'main' of github.com:billchurch/webssh2 2022-08-03 14:16:42 +00:00
Bill Church
0c78c1f31c
chore: release 0.4.7-pre-3
Release-As: 0.4.7-pre-3
2022-08-03 14:16:30 +00:00
Bill Church
7985bd0143
chore(main): release webssh2 0.4.7-pre-2 (#305) 2022-08-03 10:13:57 -04:00
Bill Church
1862acceb5
Merge branch 'main' of github.com:billchurch/webssh2 2022-08-03 14:13:19 +00:00
Bill Church
0bcc37a0f7
chore: update release please workflow fixes #283 2022-08-03 14:12:21 +00:00
Bill Church
b29242dfd4
chore: release 0.4.7-pre-3
Release-As: 0.4.7-pre-3
2022-08-03 14:11:57 +00:00
Bill Church
a284ca07ca
chore: update package(-lock).json 2022-08-03 14:11:57 +00:00
Bill Church
f048b46667
chore: update Dockerfile 2022-08-03 14:11:56 +00:00
Bill Church
31f7728602
chore: update .dockerignore 2022-08-03 14:11:55 +00:00
Bill Church
e3c11cce16
Update SECURITY.md 2022-08-03 14:11:55 +00:00
Bill Church
2159709812
chore: update workflows 2022-08-03 14:11:54 +00:00
Bill Church
b36e40357d
chore: update workflows 2022-08-03 14:11:53 +00:00
Bill Church
8749c21f4d
chore: update bug report 2022-08-03 14:11:53 +00:00
Bill Church
0ea6c16ac4
chore: update bug reporting 2022-08-03 14:11:52 +00:00
Bill Church
abb6b71e62
chore: update bug reporter 2022-08-03 14:11:51 +00:00
Bill Church
6370f83466
chore: update bug reporter 2022-08-03 14:11:51 +00:00
Bill Church
1717d42faf
chore: update bug templates 2022-08-03 14:11:50 +00:00
Bill Church
01720cd9e0
Update issue templates 2022-08-03 14:11:50 +00:00
Bill Church
b3faa1d7b5
chore: update bug report template 2022-08-03 14:11:49 +00:00
Bill Church
b1384788f5
Delete ISSUE_TEMPLATE 2022-08-03 14:11:48 +00:00
Bill Church
b238df4f49
Create ISSUE_TEMPLATE 2022-08-03 14:11:48 +00:00
Bill Church
10e59b25f9
Delete ISSUE_TEMPLATE.md 2022-08-03 14:11:47 +00:00
Bill Church
13db095885
Delete Build/Release directory 2022-08-03 14:11:46 +00:00
Bill Church
000b294999
Update README.md 2022-08-03 14:11:46 +00:00
Bill Church
e91454875b
Delete screenshots directory 2022-08-03 14:11:45 +00:00
Bill Church
942af6a91d
Delete bin directory 2022-08-03 14:11:45 +00:00
github-actions[bot]
37a3dac008
chore(main): release webssh2 0.4.7-pre-2 (#304)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-03 14:11:44 +00:00
Bill Church
cb73084dc5
chore: test release workflows 2022-08-03 14:11:43 +00:00
github-actions[bot]
0e966a64e5
chore(main): release webssh2 0.4.7-pre-1 (#303)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-03 14:11:42 +00:00
Bill Church
da86943cb6
chore: release testing 2022-08-03 14:11:42 +00:00
Bill Church
ee235e2294
chore: release testing 2022-08-03 14:11:41 +00:00
github-actions[bot]
837bb2380d
chore(main): release webssh2 0.4.7-pre-0 (#302)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-03 14:11:40 +00:00
Bill Church
5f565d3aae
chore: update workflow 2022-08-03 14:11:39 +00:00
Bill Church
dbd46f4484
chore: update workflow 2022-08-03 14:11:39 +00:00
Bill Church
d756b11b60
Test branch (#300)
* chore: release workflow testing
2022-08-03 14:11:38 +00:00
Bill Church
85eeee0000
chore: bootstrap releases for path: . (#298) 2022-08-03 14:11:37 +00:00
Bill Church
64e093931a
chore: update release workflow 2022-08-03 14:11:37 +00:00
Bill Church
09ca7bd838
chore: update release workflow 2022-08-03 14:11:36 +00:00
Bill Church
7d88f7068b
Update SECURITY.md 2022-08-03 14:11:36 +00:00
Bill Church
2d0fff581e
Create SECURITY.md 2022-08-03 14:11:35 +00:00
Bill Church
206d725663
Dev (#296)
* chore: update ssh2 and development deps

* feat: take LISTEN, PORT, and other env vars #294

* chore: rebuild client files

* docs: update readme

* chore: bump version

* chore: setup gpg for dev container
2022-08-03 14:11:34 +00:00
Bill Church
73442fe8c2
chore: update release please workflow fixes #283 2022-08-03 14:06:36 +00:00
Bill Church
6c7d242679
chore: release 0.4.7-pre-3
Release-As: 0.4.7-pre-3
2022-08-03 14:04:53 +00:00
Bill Church
7c41f5dca0
chore: update package(-lock).json 2022-08-03 13:56:37 +00:00
Bill Church
5b827b6acf
chore: update Dockerfile 2022-08-03 13:54:48 +00:00
Bill Church
1db557a399
chore: update .dockerignore 2022-08-03 13:54:32 +00:00
Bill Church
41259a6971
Merge branch 'main' of github.com:billchurch/webssh2 2022-08-02 18:14:20 +00:00
Bill Church
657c4bd688
chore: update workflows 2022-08-02 18:14:16 +00:00
Bill Church
3b564c6d4b
chore: update workflows 2022-08-02 18:12:30 +00:00
Bill Church
28f8f9b5b3
Update SECURITY.md 2022-08-02 12:54:02 -04:00
Bill Church
0448c231ac
chore: update bug report 2022-08-02 16:52:32 +00:00
Bill Church
639ae09fe1
chore: update bug reporting 2022-08-02 16:51:02 +00:00
Bill Church
aa07c8447a
chore: update bug reporter 2022-08-02 16:47:27 +00:00
Bill Church
b4615658dd
chore: update bug reporter 2022-08-02 16:47:23 +00:00
Bill Church
7d6fea45cc
chore: update bug templates 2022-08-02 16:45:13 +00:00
Bill Church
bb243fb00d
Update issue templates 2022-08-02 12:44:35 -04:00
Bill Church
2bb81c05b5
chore: update bug report template 2022-08-02 16:42:44 +00:00
Bill Church
ec76f95510
Delete ISSUE_TEMPLATE 2022-08-02 12:40:15 -04:00
Bill Church
80e47c2a61
Create ISSUE_TEMPLATE 2022-08-02 12:38:47 -04:00
Bill Church
a2bd4b38af
Delete ISSUE_TEMPLATE.md 2022-08-02 12:38:24 -04:00
Bill Church
8e6563fa67
Delete Build/Release directory 2022-08-02 12:27:50 -04:00
Bill Church
2aa713fe20
Update README.md 2022-08-02 12:27:27 -04:00
Bill Church
92dac9a17e
Delete screenshots directory 2022-08-02 12:24:38 -04:00
Bill Church
ca62af669e
Delete bin directory 2022-08-02 12:24:24 -04:00
github-actions[bot]
784387cbc7
chore(main): release webssh2 0.4.7-pre-2 (#304)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-02 11:43:38 -04:00
Bill Church
0d4ebf715c
chore: test release workflows 2022-08-02 15:41:45 +00:00
github-actions[bot]
a3019ad7e3
chore(main): release webssh2 0.4.7-pre-1 (#303)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-02 11:24:09 -04:00
Bill Church
14ea80d54e
chore: release testing 2022-08-02 15:22:44 +00:00
Bill Church
da8e6573f9
chore: release testing 2022-08-02 15:21:35 +00:00
github-actions[bot]
1c358fabf7
chore(main): release webssh2 0.4.7-pre-0 (#302)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-02 11:05:46 -04:00
Bill Church
09f17906cb
chore: update workflow 2022-08-02 15:04:01 +00:00
Bill Church
75d41af8d6
chore: update workflow 2022-08-02 14:59:17 +00:00
Bill Church
3db0095947
Test branch (#300)
* chore: release workflow testing
2022-08-02 10:57:02 -04:00
Bill Church
d43da9993e
chore: bootstrap releases for path: . (#298) 2022-08-02 09:34:43 -04:00
Bill Church
d77f885d52
chore: update release workflow 2022-08-02 13:17:37 +00:00
Bill Church
a99a0d5959
chore: update release workflow 2022-08-02 13:14:19 +00:00
Bill Church
9dd4dc8868
Update SECURITY.md 2022-08-01 15:34:08 -04:00
Bill Church
7b3da3a1e3
Create SECURITY.md 2022-08-01 15:33:21 -04:00
Bill Church
c0e67d2d57
Dev (#296)
* chore: update ssh2 and development deps

* feat: take LISTEN, PORT, and other env vars #294

* chore: rebuild client files

* docs: update readme

* chore: bump version

* chore: setup gpg for dev container
2022-08-01 15:27:44 -04:00
Bill Church
0bbc99a1ba chore: dotenv module 2022-08-01 14:11:54 +00:00
Bill Church
2bc9dc9382 docs: update readme 2022-08-01 13:49:48 +00:00
Bill Church
97f3088780 feat: add fontFamily, letterSpacing, lineHeight 2022-07-31 01:34:52 +00:00
Bill Church
140e1e24b1 feat: reorder viewport setup at ssh handshake #292 2022-07-30 20:49:20 +00:00
Bill Church
2289c6736b docs: update docs 2022-07-30 20:45:57 +00:00
Bill Church
1965a7460d chore: version bump 2022-07-30 20:14:12 +00:00
Bill Church
5e78812974 feat: add fontSize option #292 2022-07-30 20:13:36 +00:00
Bill Church
6fa65a3f85 chore: updare workflows 2022-07-30 19:38:36 +00:00
Bill Church
2c2e454c08 chore: update workflows 2022-07-30 19:37:39 +00:00
Bill Church
2d77dae40e chore: workflow update 2022-07-30 19:34:14 +00:00
Bill Church
a8457e96bf chore: update workflow 2022-07-30 19:32:31 +00:00
Bill Church
60929d53c2 chore: debug workflow 2022-07-30 19:06:39 +00:00
Bill Church
4d24a79d7d chore: debug workflow 2022-07-30 19:05:25 +00:00
Bill Church
f8c6eda108 Merge branch 'main' of github.com:billchurch/webssh2 2022-07-30 18:58:53 +00:00
Bill Church
19a60abc11 update workflow 2022-07-30 18:58:26 +00:00
Bill Church
7d12e1009c
Update README.md 2022-07-30 14:53:21 -04:00
Bill Church
8b451a344b chore: update workflow 2022-07-30 18:45:02 +00:00
Bill Church
dcfd7d671a chore: pkg maint 2022-07-30 18:23:35 +00:00
Bill Church
48d1f6ccca chore: ci stuff 2022-07-30 18:19:20 +00:00
Bill Church
420332da8d chore: update docker workflow 2022-07-30 16:13:59 +00:00
Bill Church
3c1bba597d chore: update dev environment 2022-07-30 16:11:23 +00:00
Bill Church
897c161c88
Update README.md 2022-07-30 12:06:38 -04:00
Bill Church
29c3bb82ea chore: update workflow 2022-07-30 11:40:44 -04:00
Bill Church
d7a245d974 chore: update workflow 2022-07-30 11:39:46 -04:00
Bill Church
8c8ca7da4a chore: bump version 0.4.7-alpha-1 2022-07-30 11:19:24 -04:00
Bill Church
ec809d829a chore: workflow testing 2022-07-30 11:07:04 -04:00
Bill Church
6d5540bf77 chore: test workflow 2022-07-30 11:03:18 -04:00
Bill Church
71a272c526 chore: worklfow testing 2022-07-30 11:01:23 -04:00
Bill Church
3b0cb975ef chore: update docker build workflow 2022-07-30 10:55:19 -04:00
Bill Church
f041c779e9 fix: docker multiplatform build on push fixes #293 2022-07-30 10:52:56 -04:00
Bill Church
d1f945b09e chore: workflow testing 2022-07-30 10:34:51 -04:00
Bill Church
b90499ca5d chore: workflow testing 2022-07-30 10:31:18 -04:00
Bill Church
363aa4e2df test: workflow testing [CI Skip] 2022-07-30 10:22:51 -04:00
Bill Church
58a0412091
test: workflow 2022-07-29 16:06:35 -04:00
Bill Church
9ff17b87ba
test: workflow 2022-07-29 16:04:53 -04:00
Bill Church
b2c6c555d7
test: workflow 2022-07-29 16:01:33 -04:00
Bill Church
1706c44e3b
test: workflow 2022-07-29 15:58:55 -04:00
Bill Church
f2e1beba96
test: workflow 2022-07-29 15:43:41 -04:00
Bill Church
e4697f4e5c
test: workflow 2022-07-29 15:42:59 -04:00
Bill Church
1c4793b202
test: workflow 2022-07-29 12:46:36 -04:00
Bill Church
673435c624
test: workflow 2022-07-29 12:37:03 -04:00
Bill Church
f87607465b
test: workflow 2022-07-29 09:49:27 -04:00
Bill Church
464d56e1ab
test: workflow 2022-07-29 09:48:59 -04:00
Bill Church
be279047e9
test: workflow 2022-07-29 09:46:51 -04:00
Bill Church
fe80e6a97e
test: workflow 2022-07-29 09:46:04 -04:00
Bill Church
7209bb9324
test: workflow testing 2022-07-29 09:39:16 -04:00
Bill Church
3fae0951ff
test: workflow test 2022-07-29 09:37:34 -04:00
Bill Church
2deb5d9cde
test: rename test workflow 2022-07-29 09:35:57 -04:00
Bill Church
e6b48dff7e
test: workflow testing 2022-07-29 09:34:26 -04:00
Bill Church
1edfd5e748
chore: testing 2022-07-29 09:06:54 -04:00
Bill Church
63f36432cb
chore: update workflow 2022-07-29 08:50:40 -04:00
Bill Church
9b3371bbb9
chore: update workflow 2022-07-29 08:48:01 -04:00
Bill Church
3dc6fc491b
chore: update dockerbuild 2022-07-29 08:45:40 -04:00
Bill Church
a41a971300
chore: update muiltiplatform with correct branch name 2022-07-29 08:35:49 -04:00
Bill Church
6e3a340e23
chore: add multiplatform support to docker builds 2022-07-29 08:29:42 -04:00
dependabot[bot]
28b295dc86
build(deps): bump terser from 5.7.1 to 5.14.2 in /app (#291) 2022-07-20 06:28:29 -04:00
Bill Church
b189dbe9d5 chore: docker main tag 2022-07-08 16:51:30 -04:00
Bill Church
7ba5143133 chore: rename workflows 2022-07-08 16:19:29 -04:00
Bill Church
c19fb9397c chore: push docker image on new tag #287 2022-07-08 16:14:02 -04:00
Bill Church
4f3e806708 chore: docker-image workflow for #287 2022-07-08 16:08:46 -04:00
Bill Church
a06b50dd2a
Create docker-image.yml 2022-07-08 15:51:56 -04:00
Bill Church
dc089a8f41 chore: update dockerfile node 16 alpine 2022-07-08 15:40:59 -04:00
Bill Church
05e69507ac BREAKING CHANGE: remove internet explorer compat 2022-07-08 15:30:53 -04:00
Bill Church
6ef27725d3 chore: formatting 2022-07-08 15:26:43 -04:00
Bill Church
841dbee74c chore: light code cleanup 2022-07-08 14:29:52 -04:00
Bill Church
cc7c6b4210 chore: remove unused module 2022-07-07 18:36:57 -04:00
Bill Church
46c1560e3c feat: add additional params for POST requests #290 2022-07-07 18:34:55 -04:00
Bill Church
0a4e419fb3 feat: add additional vars to POST requests #290 2022-07-07 18:34:17 -04:00
Bill Church
5b8f88cfef feat: credentials over http post for #290 2022-07-07 11:21:49 -04:00
zhangchao
40cbb35616
fix: Fix the parameter passing problem of setDefaultCredentials to make it perform data initialization normally (#288)
Co-authored-by: wooc <wooc@hwj-robots.com>
2022-07-05 11:24:39 -04:00
Bill Church
e75392b879 refactor: light refactoring 2022-05-20 15:12:01 -04:00
Bill Church
0dcaa6e150 feat!: validate referer to /reauth is valid 2022-05-20 15:05:29 -04:00
Bill Church
e0742db22f refactor: clean up shutdown and move sockets 2022-05-19 16:17:56 -04:00
Bill Church
3f22c8b8e0 refactor: move some functions out of app.js 2022-05-19 12:10:41 -04:00
Bill Church
9dfa8031c0 refactor: cleanup basic auth code 2022-05-19 10:13:26 -04:00
Bill Church
78dafebb2b package: remove colors module 2022-05-19 09:05:18 -04:00
Bill Church
8aebdc54a5 chore: rebuild client 2022-05-18 22:39:13 -04:00
Bill Church
09e2f9bc39 package: bump socket.io@4.5.1, express@4.18.1 2022-05-18 22:37:39 -04:00
Bill Church
84c09ec8a1 package!: bump xterm to 4.18.0 2022-05-18 22:32:59 -04:00
Bill Church
57af568586 refactor: remove unneccessary variable assignment 2022-05-18 22:13:19 -04:00
Bill Church
50cfcb9778 feat!: consistent logging messages see #286 2022-05-18 21:50:33 -04:00
Bill Church
9fa6c50d76 chore: jsconfig file 2022-05-18 21:46:25 -04:00
Bill Church
53a601cadc package: bump debug to v 4.3.4 2022-05-18 15:58:17 -04:00
Bill Church
8d93ffab91 package: bump ssh2 to v1.10.0 2022-05-18 12:22:06 -04:00
Bill Church
7c9e00cdfe refactor: add debug for client socket.emit events 2022-05-17 15:48:53 -04:00
Bill Church
9c99b0940e
feat!: config system changes #284 (#285) 2022-05-17 15:24:32 -04:00
BIll Church
ef40aa0266 docs: correct paths for BUILDING.md 2022-05-17 10:39:08 -04:00
BIll Church
5e48d42e61 docs: update readme 2022-05-17 10:37:45 -04:00
BIll Church
e6864f595b docs: update README.md 2022-05-17 10:34:51 -04:00
Bill Church
1e2e73e617
Update README.md 2022-05-17 09:55:03 -04:00
Bill Church
dd2f8217be
Update README.md 2022-05-17 09:54:01 -04:00
Bill Church
486e5dae0c refactor: socket.js 2022-05-13 10:13:14 -04:00
Bill Church
3438c93a14 refactor: socket.js 2022-05-11 14:25:17 -04:00
Bill Church
5cc1a6f072 refactor: remove comments from client index.ts 2022-05-11 13:25:05 -04:00
Bill Church
6b1066975a refactor: socket.js 2022-05-11 11:41:09 -04:00
Bill Church
0787aa695c refactor: socket.js 2022-05-11 10:44:37 -04:00
Bill Church
522278fa4e refactor: app.js 2022-05-11 10:44:07 -04:00
Bill Church
d835d919f3 refactor: client files 2022-05-11 10:36:47 -04:00
Bill Church
ffab5345dc fix: invalid css in style.css 2022-05-11 10:00:56 -04:00
Bill Church
f457a4a520 chore: update changelog 2022-04-17 10:57:43 -04:00
53 changed files with 8001 additions and 8697 deletions

View file

@ -1,16 +0,0 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.177.0/containers/typescript-node/.devcontainer/base.Dockerfile
# [Choice] Node.js version: 16, 14, 12
ARG VARIANT="16-buster"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment if you want to install an additional version of node using nvm
# ARG EXTRA_NODE_VERSION=10
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
# [Optional] Uncomment if you want to install more global node packages
# RUN su node -c "npm install -g <your-package-list -here>"

View file

@ -1,31 +1,37 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.177.0/containers/typescript-node
{ {
"name": "Node.js & TypeScript", "name": "Node.js & TypeScript",
"build": { "image": "mcr.microsoft.com/devcontainers/base:jammy",
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 12, 14, 16
"args": {
"VARIANT": "14"
}
},
// Set *default* container specific settings.json values on container create. "mounts": [
"settings": { "source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh/personal_id_rsa.pub,target=/home/vscode/.hostssh/id_rsa.pub,readonly,type=bind,consistency=cached"
"terminal.integrated.shell.linux": "/bin/bash" ],
"features": {
"ghcr.io/devcontainers-contrib/features/node-asdf:0": {},
}, },
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Add the IDs of extensions you want installed when the container is created. // Add the IDs of extensions you want installed when the container is created.
"extensions": [ "extensions": [
"dbaeumer.vscode-eslint" "ms-vscode-remote.remote-containers",
], "dbaeumer.vscode-eslint",
"GitHub.copilot",
"GitHub.copilot-chat",
"esbenp.prettier-vscode",
"rvest.vs-code-prettier-eslint",
"bierner.markdown-mermaid",
"stylelint.vscode-stylelint"
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally. // Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [], // "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created. // Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install", "postCreateCommand": "/bin/bash ./.devcontainer/scripts/tools.sh >> ~/post-create-tools.log",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node" "remoteUser": "vscode"
} }

View file

@ -0,0 +1,12 @@
#!/bin/bash
mkdir -p ~/.ssh && \
touch ~/.ssh/known_hosts && \
sudo tee ~/.ssh/config > /dev/null << EOF
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.hostssh/id_rsa.pub
EOF
sudo chown -R vscode:vscode ~/.ssh

View file

@ -1,3 +1,9 @@
.git .git
.cache .cache
app/node_modules app/node_modules
app/client/src
app/scripts
app/.*
app/*.sample
app/client/tsconfig.json
app/CHANGELOG.md

75
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View file

@ -0,0 +1,75 @@
name: Bug Report
description: File a bug report
title: "[Bug]: "
labels: ["bug", "triage"]
assignees:
- billchurch
body:
- type: markdown
attributes:
value: |
Depending on the type of issue, please include the follwing information:
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
value: "A bug happened!"
validations:
required: true
- type: input
id: node_ver
attributes:
label: Node Version
description: version of Node this problem occurs on
placeholder: npm -v
validations:
required: true
- type: input
id: npm_ver
attributes:
label: NPM Version
description: version of NPM this problem occurs on
placeholder: npm -v
validations:
required: true
- type: input
id: server_ver
attributes:
label: Server OS Version
description: Server OS Version / Distribution / Processor Architecture
placeholder: uname -a;cat /etc/os-release
validations:
required: true
- type: input
id: webssh2_ver
attributes:
label: WebSSH2 release version
description: Version of WebSSH you are using
placeholder: grep version app/package.json
validations:
required: true
- type: input
id: sshhost_ver
attributes:
label: OS and Version of SSH server
description: OS and Version of SSH server connecting to
placeholder: 'on target server run: uname -a;sshd -v'
validations:
required: false
- type: input
id: browser_ver
attributes:
label: Browser Version
description: Information from brwoser's About... or a screenshot of the about screen.
placeholder:
validations:
required: false
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell

10
.github/ISSUE_TEMPLATE/custom.md vendored Normal file
View file

@ -0,0 +1,10 @@
---
name: Question
about: General how-to questions
title: ''
labels: ''
assignees: ''
---

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

65
.github/workflows/action-test.yml vendored Normal file
View file

@ -0,0 +1,65 @@
name: Manually Release Previous Tag
on:
workflow_dispatch:
inputs:
tag:
description: 'Repo Branch/Tag'
default: 'main'
type: 'string'
required: true
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v3
with:
ref: ${{ inputs.tag }}
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=${{ secrets.DOCKER_USERNAME }}/${GITHUB_REPOSITORY#*/}
VERSION=${{ inputs.tag }}
VERSION="${VERSION//v}"
TAGS="${DOCKER_IMAGE}:${VERSION},${DOCKER_IMAGE}"
# If the VERSION looks like a version number, assume that
# this is the most recent version of the image and also
# tag it 'latest'.
if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
TAGS="$TAGS,${DOCKER_IMAGE}"
fi
# Set output parameters.
echo ::set-output name=tags::${TAGS}
echo ::set-output name=docker_image::${DOCKER_IMAGE}
- name: Set up QEMU
uses: docker/setup-qemu-action@master
with:
platforms: all
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@master
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/ppc64le
push: true
tags: ${{ steps.prep.outputs.tags }}

View file

@ -0,0 +1,69 @@
---
name: 'Build Docker On Tag'
on:
push:
branches:
- bigip-server
tags:
- 'v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
workflow_dispatch: # Allows manual triggering from the GitHub UI
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v3
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=${{ secrets.DOCKER_USERNAME }}/${GITHUB_REPOSITORY#*/}
# If this is a git tag, use the tag name as a docker tag
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
TAGS="${DOCKER_IMAGE}:${VERSION}"
fi
# If this is a git branch, use the branch name as a docker tag
if [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=${GITHUB_REF#refs/heads/}
TAGS="${DOCKER_IMAGE}:${VERSION}"
fi
# If the VERSION looks like a version number, also tag as 'latest'
if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
TAGS="$TAGS,${DOCKER_IMAGE}:latest"
fi
# Set output parameters
echo ::set-output name=tags::${TAGS}
echo ::set-output name=docker_image::${DOCKER_IMAGE}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build
uses: docker/build-push-action@v4
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/ppc64le
push: true
tags: ${{ steps.prep.outputs.tags }}

View file

@ -0,0 +1,67 @@
---
name: 'Build Docker Images'
on:
release:
types: [published]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: 'Checkout'
uses: actions/checkout@v3
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=${{ secrets.DOCKER_USERNAME }}/${GITHUB_REPOSITORY#*/}
# If this is git tag, use the tag name as a docker tag
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/webssh2-v}
TAGS="${DOCKER_IMAGE}:${VERSION}"
fi
# If this is git branch, use the branch name as a docker tag
if [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=${GITHUB_REF#refs/heads/}
TAGS="${DOCKER_IMAGE}:${VERSION}"
fi
# If the VERSION looks like a version number, assume that
# this is the most recent version of the image and also
# tag it 'latest'. This is done by just specifying the ${DOCKER_IMAGE}
# without a tag.
if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
TAGS="$TAGS,${DOCKER_IMAGE}"
fi
# Set output parameters.
echo ::set-output name=tags::${TAGS}
echo ::set-output name=docker_image::${DOCKER_IMAGE}
- name: Set up QEMU
uses: docker/setup-qemu-action@master
with:
platforms: all
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@master
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build
uses: docker/build-push-action@v2
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/ppc64le
push: true
tags: ${{ steps.prep.outputs.tags }}

47
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,47 @@
---
name: 'Create Release'
on:
push:
branches:
- main
paths-ignore:
- '.github/**'
- '.devcontainer/**'
- '.**'
- '**.md'
jobs:
release:
runs-on: ubuntu-latest
outputs:
paths_released: ${{ steps.manifest_release.outputs.paths_released }}
steps:
- uses: google-github-actions/release-please-action@v3
id: manifest_release
with:
token: ${{ secrets.RELEASE_PLEASE_UAT }}
command: manifest
package-name: webssh2
path: app
default-branch: main
release-type: node
publish:
runs-on: ubuntu-20.04
needs: release
strategy:
fail-fast: false
matrix:
path: ${{fromJson(needs.release.outputs.paths_released)}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 16
registry-url: 'https://registry.npmjs.org'
- name: publish-to-npm
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
run: |
cd ${{ matrix.path }}
npm install
npx lerna bootstrap
npx lerna publish from-package --no-push --no-private --yes

View file

@ -0,0 +1,3 @@
{
"app": "0.5.0-pre-4"
}

View file

@ -2,12 +2,12 @@
To rebuild the client files, you need at least Node v14. To rebuild the client files, you need at least Node v14.
The source of the client files are located in `./app/client/source` The source of the client files are located in `./app/client/src`
`npm run build` will compile the source files there into `./app/client/public/`. This directory is considered to be volitile and is deleted every time `npm run build` is invoked. `npm run build` will compile the source files there into `./app/client/public/`. This directory is considered to be volitile and is deleted every time `npm run build` is invoked.
WebPack is used for building and the configuration is located in `./app/scripts` WebPack is used for building and the configuration is located in `./app/scripts`
If one wishes to make changes to the javascript, the html, or the css it should be done in `./app/client/source` and then complied using `npm run build` If one wishes to make changes to the javascript, the html, or the css it should be done in `./app/client/src` and then complied using `npm run build`
For development purposes, you may also utilize `npm run builddev` which will not minimize the source and allow you to more easily troubleshoot while making customizations. For development purposes, you may also utilize `npm run builddev` which will not minimize the source and allow you to more easily troubleshoot while making customizations.

View file

@ -1 +0,0 @@
e2e70f7d2949b6c8fe0299f888a3725763a62c01a1faea1fb729babc2ed51c92 Build/Release/BIG-IP-ILX-WebSSH2-0.2.8.tgz

View file

@ -1,378 +1,3 @@
# Change Log # Changelog Moved
## 0.4.5 [20220331]
### Fixes
- Update socket.io to 4.2.0
- Update read-config-ng to 3.0.4
## 0.4.4 [20211209] See [app/CHANGELOG.md](app/CHANGELOG.md)
### Fixes
- Add ./node_modules to .dockerignore [#240](../../issues/240) thanks @UncleSamSwiss
- validator to 13.7.0 [to mitigate potential Regular Expression Denial of Service (ReDoS)](https://snyk.io/vuln/SNYK-JS-VALIDATOR-1090600)
- cidr-matcher should be [re-installed to pickup >json-schema@4.0.0 due to prototype pollution vulnerability](https://snyk.io/vuln/SNYK-JS-JSONSCHEMA-1920922)
- Update xterm.js to 4.15.0 [#261](../../issues/261)
- Replace deprecated term.setOptions with term.options
### Changes
- update README.md for additional Docker methods thanks @Utopiah
## 0.4.3 [20211019]
- update dependencies
- ssh2 to 1.4.0 [to mitigate potential command injection in windows](https://snyk.io/vuln/SNYK-JS-SSH2-1656673)
## 0.4.2 [20210813]
### changes
- update dependencies
- socket.io to 4.1.1
- read-config-ng to 3.0.2
- debug to 4.3.1
## 0.4.1 [20210703]
### Fixes
- lost comma in config.json.sample 71fe377
### Changes
- bump ws@7.4.6 to [mitigate potential ReDoS vulnerability](https://github.com/websockets/ws/releases/tag/7.4.6)
- dev: update CI tools
- dev: update dev tools
- dev: update build tools
## 0.4.0 [20210519]
### BREAKING
- Disabled ssh.serverlog.client option, this disables the POC which allowed for logging of the data sent between the client/server to the console.log.
- Dropping support for node versions under 14
### Changes
- Removed HTML menu code from ./app/server/socket.js, the menu is now fully laid out in the ./app/client/src/index.html and the option elements are hidden by default. Not sure why it wasn't done this way from the start, but there it is.
- Updated socket.io to v4.1.1
- Client javascript `./app/client/src/js/index.ts` is now built on TypeScript (`npm run build` will generate javascript for client and place into `app/client/public/webssh2.bundle.js` as before)
- Build environment changes
- removed unused xterm-addon-search, xterm-addon-weblinks, standard, postcss-discard-comments
- added prettier 2.3.0, typescript modules, socket.io-client 4.1.1, airbnb linting tools
### Added
- Lookup ip address for hostname in URL, fixes #199 thanks to @zwiy
- Ability to override `Authorization: Basic` header and replace with credentials specified in `config.json` fixes #243. New config.json option `user.overridebasic`
### CONTRIBUTING
In this release, we're trying our best to conform to the [Airbnb Javascript Style Guide](https://airbnb.io/projects/javascript/). I'm hoping this will make contributions easier and keep the code readable. I love shortcuts more than anyone but I've found when making changes to code I've not looked at in a while, it can take me a few momements to deconstruct what was being done due to readbility issues. While I don't agree with every decision in the style guide (semi-colons, yuk), it is a good base to keep the code consistent.
If you've not used it before, I recommend installing the [vscode extensions](https://blog.echobind.com/integrating-prettier-eslint-airbnb-style-guide-in-vscode-47f07b5d7d6a) for that and [Prettier](https://prettier.io/) and getting familiar. The autocorrections are great (especially if you hate dealing with semi-colons...)
As of 0.4.0-testing-0, the client code is written in [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html). It's not that much different from JavaScript, and the introduction strong typing will ultimately help to produce better code. Eventually we want to move the whole project to TypeScript but that make take a bit more time. Take a moment to look at ./app/client/src/js/index.ts to see what TypeScript looks like.
## 0.3.1 [20210513]
### BREAKING
- Ability to configure CORS settings for socket.io see [#240](../../issues/240) for more information on how this may break existing deployments. Default settings in example `config.json` are currently permissive `http.origins: ["*:*"]` please note that if a `config.json` is not present, the default is `http.origins: ["localhost:2222"]
### Added
- Safe Shutdown Feature - thanks to @edgarogh
- Sending SIGINT or SIGTERM to node process responsible for WebSSH2 or Docker process will result in a "safe" shutdown
- Timer is configured in config.safeShutdownDuration
- feat: Use docker build to create multi-arch images (#202)
### Fixed
- obey host ssh.host in config fixes #190
### Changed
- `config.json.sample`: `allowreauth` now defaults to `false` fixes #238
- update ssh2 to 0.8.8 -> 0.8.9 - [comparison at ssh2 repo](https://github.com/mscdex/ssh2/compare/v0.8.8...v0.8.9)
- update xterm to 4.12.0 [comparison at xtermjs repo](https://github.com/xtermjs/xterm.js/compare/4.4.0...4.12.0)
- update read-config-ng to 3.0.2
- update morgan to 1.10.0
- update debug to 4.3.1
- update express-session to 1.17.1
- update validator to 13.6.0
- development tools updates (build environment requires minimum of Node 10, only needed for customization)
- update @fortawesome/fontawesome-svg-core to 1.2.35
- update @fortawesome/free-solid-svg-icons to 5.15.3
- update copy-webpack-plugin to 8.1.1
- update cross-env to 7.0.3
- update css-loader to 5.2.4
- update file-loader to 6.2.0
- update mini-css-extract-plugin to 1.6.0
- update postcss-discard-comments to 5.0.0
- update snazzy to 9.0.0
- update standard to 16.0.3
- update standard-version to 9.3.0
- update style-loader to 2.0.0
- update terser-webpack-plugin to 5.1.1
- update url-loader to 4.1.1
- update webpack to 5.37.0
- update webpack-cli to 4.7.0
- update webpack-merge to 5.7.3
- update webpack-stream to 6.1.2
- update xterm-addon-fit to 0.5.0
- update xterm-addon-search to 0.8.0
- update xterm-addon-web-links to 0.4.0
- update ssri from 6.0.1 to 6.0.2 [#233](../../pull/233)
- update hosted-git-info from 2.8.5 to 2.8.9 [#237](../../pull/237)
- update lodash from 4.17.19 to 4.17.21 [#236](../../pull/236)
- update handlebars from 4.7.6 to 4.7.7 [#235](../../pull/235)
- update y18n from 4.0.0 to 4.0.1 [#230](../../pull/230)
- update elliptic from 6.5.3 to 6.5.4 [#228](../../pull/222833)
- update ini from 1.3.5 to 1.3.8 [#217](../../pull/217)
## 0.3.0 [20200315]
🍀🍀🍀
### Added
- Add configuration option to restrict connections to specified subnets thanks to @Mierdin
- favicon
- added module `serve-favicon` to serve favicon from root if pre-fetched by browser
- added `link rel=icon` line in client.htm to serve favico.ico out of /ssh/
### Changed
- Using new repo for read-config -> read-config-ng-
- removed express compression feature, added no real value.
- module updates
- ssh2 to 0.8.6 -> 0.8.8 - [comparison at ssh2 repo](https://github.com/mscdex/ssh2/compare/v0.8.6...v0.8.8)
- xterm 4.2.0 -> 4.4.0 - [comparison at xtermjs repo](https://github.com/xtermjs/xterm.js/compare/4.2.0...4.4.0)
- read-config-ng 3.0.1 - (taking over abandoned repo)n
- development module updates (does not impact production, only for development and rebuilding)
- fortawesome/fontawesome-svg-core 1.2.27
- fortawesome/free-solid-svg-icons 5.12.1
- standard-version 7.1.0
- webpack 4.42.0
- webpack-cli 3.3.11
- terser-webpack-plugin 2.3.5
- copy-webpack-plugin 5.1.1
- cross-env 7.0.2
- css-loader 3.4.2
- file-loader 5.1.0
- style-loader 1.1.3
- url-loader 3.0.0
### Potentially Breaking Changes
- Move all child resources to start from under /ssh
- /socket.io -> /ssh/socket.io
- /webssh2.css -> /ssh/webssh2.css
- /webssh2.bundle.js -> /ssh/webssh2.bundle.js
- /reauth -> /ssh/reauth
- perhaps more
### Fixes
- Typo in config.json.sample, thanks @wuchihsu, fixes #173
### Housekeeping
- Removed irrelavant build scripts from /scripts
## 0.2.9 [2019-06-13]
### Changes
- Missing require('fs') in `server/app.js` See issue [#135](../../issues/135)
- Patched read-config to mitigate vulnerability in js-yaml
- issue not exploitable on webssh2 implementation
- patched anyway
- sending my patch upstream to read-config, webssh2 package.json points to patched version in my repository https://github.com/billchurch/nodejs-read-config
- See https://github.com/nodeca/js-yaml/issues/475 for more detail
## 0.2.8 [2019-05-25]
### Changes
- Fixes issue if no password is entered, browser must be closed and restart to attempt to re-auth. See issue [#118](../../issues/118). Thanks @smilesm2 for the idea.
- fixes broken `npm run (build|builddev)`
- update font-awesome fonts to 5.6.3
- update webpack and dependancies
- update xterm to 3.8.0
### Fixes
- ILX workspace may not always import properly due to symbolic links (specifically ./node_modules/.bin). This is removed from the ILX package
## 0.2.7 [2018-11-11]
### Changes
- `config.reauth` was not respected if initial auth presented was incorrect, regardless of `reauth` setting in `config.json` reauth would always be attempted. fixes [#117](../../issues/117)
- **BREAKING** moved app files to /app, this may be a breaking change
- Updated dockerfile for new app path
- Updated app dependancies
- xterm v3.8.0
- https://github.com/xtermjs/xterm.js/releases/tag/3.8.0
- basic-auth v2.0.1
- https://github.com/jshttp/basic-auth/releases/tag/v2.0.1
- express v4.16.4
- https://github.com/expressjs/express/releases/tag/4.16.4
- validator v10.9.0
- https://github.com/chriso/validator.js/releases/tag/10.9.0
- Updated dev dependancies
- snazzy v8.0.0
- standard v12.0.1
- uglifyjs-webpack-plugin v2.0.1
- ajv v6.5.5
- copy-webpack-plugin v4.6.0
- css-loader v1.0.1
- nodemon v1.18.6
- postcss-discard-comments v4.0.1
- snyk v1.108.2
- url-loader v1.1.2
- webpack v4.25.1
- webpack-cli v3.1.2
## 0.2.6 [2018-11-09]
### Changes
- Reauth didn't work if intial auth presented was incorrect, (see issue #112) fixed thanks @vvalchev
- Update node version supported to >=6 (PR #115) thanks @perlun
- Update packages
- developer dependencies
## 0.2.5 [2018-09-11]
### Added
- Reauth function thanks to @vbeskrovny and @vvalchev (9bbc116)
- Controlled by `config.json` option `options.allowreauth` true presents reauth dialog and false hides dialog
### Changed
- `options.challengeButton` enabled
- previously this configuration option did nothing, this now enables the Credentials button site-wide regardless of the `allowreplay` header value
- Updated debug module to v4
## 0.2.4 [2018-07-18]
### Added
- Browser title window now changes with xterm escape sequences (see http://tldp.org/HOWTO/Xterm-Title-3.html)
- Added bellStyle options
- `GET var`: **bellStyle** - _string_ - Style of terminal bell: ("sound"|"none"). **Default:** "sound". **Enforced Values:** "sound "none"
- `config.json`: **terminal.bellStyle** - _string_ - Style of terminal bell: (sound|none). **Default:** "sound".
- `workspace` folder on GITHUB for BIG-IP specific fixes/changes
### Changed
- Updated xterm.js to 3.1.0
- https://github.com/xtermjs/xterm.js/releases/tag/3.1.0
- Default listen IP in `config.json` changed back to 127.0.0.1
### Fixed
- ESC]0; is now removed from log files when using the browser-side logging feature
## 0.2.3 unreleased
### Fixed
- ESC]0; is now removed from log files when using the browser-side logging feature
## 0.2.0 [2018-02-10]
Mostly client (browser) related changes in this release
### Added
- Menu system
- Fontawesome icons
- Resizing browser window sends resize events to terminal container as well as SSH session (pty)
- New terminal options (config.json as well as GET vars)
- terminal.cursorBlink - boolean - Cursor blinks (true), does not (false) Default: true.
- terminal.scrollback - integer - Lines in the scrollback buffer. Default: 10000.
- terminal.tabStopWidth - integer - Tab stops at n characters Default: 8.
- New serverside (nodejs) terminal configuration options (cursorBlink, scrollback, tabStopWidth)
- Logging of MRH session (unassigned if not present)
- Express compression feature
### Changed
- Updated xterm.js to 3.0.2
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.2
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.1
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.0
- Moved javascript events out of html into javascript
- Changed asset packaging from grunt to Webpack to be inline with xterm.js direction
- Moved logging and credentials buttons to menu system
- Removed non-minified options (if you need to disable minification, modify webpack scripts and 'npm run build')
### Fixed
- Resolved loss of terminal foucs when interacting with option buttons (Logging, etc...)
## 0.1.4 [2018-01-30]
### Changed
- Moved socket and util out of folders into .js in root.
- added keepaliveInterval and keepaliveCountMax config options
## 0.1.3 [2017-09-28]
### Changed
- Upgrade to debug@3.1 to eliminate ReDoS in %o formatter
- Upgrade Express to 4.15.5 for ReDOS
- Upgrade basic-auth to v2.0
## 0.1.2 [2017-07-31]
### Added
- ssh.readyTimeout option in config.json (time in ms, default 20000, 20sec)
### Changed
- Updated xterm.js to 2.9.2 from 2.6.0
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.2
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.1
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.0
- See https://github.com/sourcelair/xterm.js/releases/tag/2.8.1
- See https://github.com/sourcelair/xterm.js/releases/tag/2.8.0
- See https://github.com/sourcelair/xterm.js/releases/tag/2.7.0
- Updated ssh2 to 0.5.5 to keep current, no fixes impacting WebSSH2
- ssh-streams to 0.1.19 from 0.1.16
- Updated validator.js to 8.0.0, no fixes impacting WebSSH2
- https://github.com/chriso/validator.js/releases/tag/8.0.0
- Updated Express to 4.15.4, no fixes impacting WebSSH2
- https://github.com/expressjs/express/releases/tag/4.15.4
- Updated Express-session to 1.15.5, no fixes impacting WebSSH2
- https://github.com/expressjs/session/releases/tag/v1.15.5
- Updated Debug to 3.0.0, no fixes impacting WebSSH2
- https://github.com/visionmedia/debug/releases/tag/3.0.0
- Running in strict mode ('use strict';)
## 0.1.1 [2017-06-03]
### Added
- `serverlog.client` and `serverlog.server` options added to `config.json` to enable logging of client commands to server log (only client portion implemented at this time)
- morgan express middleware for logging
### Changed
- Updated socket.io to 1.7.4
- continued refactoring, breaking up `index.js`
- revised error handling methods
- revised session termination methods
### Fixed
### Removed
- color console decorations from `util/index.js`
- SanatizeHeaders function from `util/index.js`
## 0.1.0 [2017-05-27]
### Added
- This ChangeLog.md file
- Support for UTF-8 characters (thanks @bara666)
- Snyk, Bithound, Travis CI
- Cross platform improvements (path mappings)
- Session fixup between Express and Socket.io
- Session secret settings in `config.json`
- env variable `DEBUG=ssh2` will put the `ssh2` module into debug mode
- env variable `DEBUG=WebSSH2` will output additional debug messages for functions
and events in the application (not including the ssh2 module debug)
- using Grunt to pull js and css source files from other modules `npm run build` to rebuild these if changed or updated.
- `useminified` option in `config.json` to enable using minified client side javascript (true) defaults to false (non-minified)
- sshterm= query option to specify TERM environment variable for host, valid strings are alpha-numeric with a hypen (validated). Otherwise the default ssh.term variable from `config.json` will be used.
- validation for host (v4,v6,fqdn,hostname), port (integer 2-65535), and header (sanitized) from URL input
### Changed
- error handling in public/client.js
- moved socket.io operations to their own file /socket/index.js, more changes like this to come (./socket/index.js)
- all session based variables are now under the req.session.ssh property or socket.request.ssh (./index.js)
- moved SSH algorithms to `config.json` and defined as a session variable (..session.ssh.algorithms)
-- prep for future feature to define algorithms in header or some other method to enable separate ciphers per host
- minified and combined all js files to a single js in `./public/webssh2.min.js` also included a sourcemap `./public/webssh2.min.js` which maps to `./public/webssh2.js` for easier troubleshooting.
- combined all css files to a single css in `./public/webssh2.css`
- minified all css files to a single css in `./public/webssh2.min.css`
- copied all unmodified source css and js to /public/src/css and /public/src/js respectively (for troubleshooting/etc)
- sourcemaps of all minified code (in /public/src and /public/src/js)
- renamed `client.htm` to `client-full.htm`
- created `client-min.htm` to serve minified javascript
- if header.text is null in `config.json` and header is not defined as a get parameter the Header will not be displayed. Both of these must be null / undefined and not specified as get parameters.
### Fixed
- Multiple errors may overwrite status bar which would cause confusion as to what originally caused the error. Example, ssh server disconnects which prompts a cascade of events (conn.on('end'), socket.on('disconnect'), conn.on('close')) and the original reason (conn.on('end')) would be lost and the user would erroneously receive a WEBSOCKET error as the last event to fire would be the websocket connection closing from the app.
- ensure ssh session is closed when a browser disconnects from the websocket
- if headerBackground is changed, status background is changed to the same color (typo, fixed)
### Removed
- Express Static References directly to module source directories due to concatenating and minifying js/css
## 0.0.5 - [2017-03-23]
### Added
- Added experimental support for logging (see Readme)
### Fixed
- Terminal geometry now properly fills the browser screen and communicates this to the ssh session. Tested with IE 11 and recent versions of Chrome/Safari/Firefox.
## 0.0.4 - [2017-03-23]
### Added
- Set default terminal to xterm-color
- Mouse event support
- New config option, config.ssh.term to set terminal
### Changed
- Update to Xterm.js 2.4.0
- Minor code formatting cleanup
## 0.0.3 - [2017-02-16]
### Changed
- Update xterm to latest (2.3.0)
### Fixed
- Fixed misspelled config.ssh.port property
## 0.0.2 - [2017-02-01]
### Changed
- Moving terminal emulation to xterm.js
- updating module version dependencies
### Fixed
- Fixed issue with banners not being displayed properly from UNIX hosts when only lf is used
## 0.0.1 - [2016-06-28]
### Added
- Initial proof of concept and release. For historical purposes only.

View file

@ -1,7 +1,9 @@
FROM node:14.17-alpine FROM node:16-alpine
RUN apk update && apk add bash
WORKDIR /usr/src WORKDIR /usr/src
COPY app/ /usr/src/ COPY app/ /usr/src/
RUN npm install --production RUN npm ci --audit=false --bin-links=false --fund=false
EXPOSE 2222/tcp EXPOSE 2222/tcp
ENTRYPOINT [ "/usr/local/bin/node", "index.js" ] ENTRYPOINT [ "/usr/local/bin/node", "index.js" ]

View file

@ -1,15 +0,0 @@
Depending on the type of issue, please include the follwing information:
- Node and NPM Version
- `node -v`
- `npm -v`
- Server OS Version / Distribution / Processor Architecture
- `uname -a`
- `cat /etc/os-release`
- WebSSH2 release version
- `grep version app/package.json`
- OS and Version of SSH server connecting to
- `uname -a`
- `sshd -v`
- Browser Version and OS
- Information from brwoser's About... or a screenshot of the about screen.
- Any log or messages from the WebSSH2 output

133
README.md
View file

@ -1,8 +1,6 @@
# WebSSH2 # WebSSH2
<ignorestart> [![Build Status](https://travis-ci.com/billchurch/webssh2.svg?branch=main)](https://travis-ci.com/billchurch/webssh2) [![GitHub version](https://img.shields.io/github/v/release/billchurch/webssh2)](https://github.com/billchurch/webssh2/releases/latest) [![docker build images](https://github.com/billchurch/webssh2/actions/workflows/docker-multiplatform.yml/badge.svg)](https://github.com/billchurch/webssh2/actions/workflows/docker-multiplatform.yml)
[![Build Status](https://travis-ci.com/billchurch/webssh2.svg?branch=main)](https://travis-ci.com/billchurch/webssh2) [![GitHub version](https://img.shields.io/github/v/release/billchurch/webssh2)](https://github.com/billchurch/webssh2/releases/latest)
[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/billchurch) [![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/billchurch)
@ -10,37 +8,77 @@ Web SSH Client using ssh2, socket.io, xterm.js, and express
A bare bones example of an HTML5 web-based terminal emulator and SSH client. We use SSH2 as a client on a host to proxy a Websocket / Socket.io connection to a SSH2 server. A bare bones example of an HTML5 web-based terminal emulator and SSH client. We use SSH2 as a client on a host to proxy a Websocket / Socket.io connection to a SSH2 server.
<img width="600" height="340" alt="WebSSH2 v0.2.0 demo" src="https://github.com/billchurch/WebSSH2/raw/main/screenshots/demo-800.gif"> <img width="600" height="340" alt="WebSSH2 v0.2.0 demo" src="https://user-images.githubusercontent.com/1668075/182425293-acc8741e-cc92-4105-afdc-9538e1685d4b.gif">
# Requirements # Requirements
Node v6.x or above. If using <v6.x you should be able to run by replacing the "read-config" package to @1 like this (after a clone): Node v14.x or above. If using <v14.x you should be able to run by replacing the "read-config" package to @1 like this (after a clone):
`npm install --save read-config@1 `npm install --save read-config@1
` `
Just keep in mind that there is no intention to ensure compatability with Node < v6.x Just keep in mind that there is no intention to ensure compatability with Node < v14
# Instructions # Instructions
The instructions previously showed cloning directly from main, while normally safe may include "work in progress". It's recommended that after you clone, you switch to a particular tag.
To install: To install:
1. Clone to a location somewhere and then `cd app` and `npm install --production`. If you want to develop and rebuild javascript and other files utilize `npm install` instead. 1. Clone to a location somewhere
2. If desired, edit app/config.json to change the listener to your liking. There are also some default options which may be definied for a few of the variables. 2. Checkout to the `current` tag using `git checkout current` or choose a particular [release](https://github.com/billchurch/webssh2/releases/) tag
3. Run `npm start` 3. `cd app` and `npm install --production`. If you want to develop and rebuild javascript and other files utilize `npm install` instead.
4. Fire up a browser, navigate to IP/port of your choice and specify a host (https isn't used here because it's assumed it will be off-loaded to 4. If desired, edit app/config.json to change the listener to your liking. There are also some default options which may be definied for a few of the variables.
some sort of proxy):
5. Run `npm start`
6. Fire up a browser, navigate to IP/port of your choice and specify a host (https isn't used here because it's assumed it will be off-loaded to some sort of proxy):
http://localhost:2222/ssh/host/127.0.0.1 http://localhost:2222/ssh/host/127.0.0.1
You will be prompted for credentials to use on the SSH server via HTTP Basic authentcaiton. This is to permit usage with some SSO systems that can replay credentials over HTTP basic. You will be prompted for credentials to use on the SSH server via HTTP Basic authentcaiton. This is to permit usage with some SSO systems that can replay credentials over HTTP basic.
Alternatively in main for testing, you can send credentials via POST with the variables "username" and "userpassword".
# Customizing client files # Customizing client files
See [BUILDING.md](BUILDING.md) for more details. See [BUILDING.md](BUILDING.md) for more details.
# Docker Instructions # Docker
## NOTICE
Docker versions differ from what is in `main` and are release dependant.
Meaning billchurch/webssh2:latest is the latest official release. This does NOT sync with what is in `main` on this repo. `main` is development and will change until it gets a release tag.
On occasion, examples or instructions on `main` will drift from what is released. You should refer to the tag of the version you're using to ensure you are following the proper guidance.
That being said the most current release version is [0.4.6](https://github.com/billchurch/webssh2/tree/0.4.6), see that tag for details.
## Instructions
Some configuration options are available as [Environment Variables](#environment-variables). If there is a configuration option you require which does not have an environment variable please [open an issue requesting](../../issues/new/choose).
[webssh2 images are available in docker hub](https://hub.docker.com/repository/docker/billchurch/webssh2).
the `latest` tag will pull the most recent stable release, otherwise you can pull individual tags/releases/versions of this repo by using a particular version in the tag.
For instance:
```docker pull billchurch/webssh2:0.4.6```
or
```docker pull billchurch/webssh2:0.4.7-alpha.2```
or
```docker pull billchurch/webssh2```
for the most recent
If you want to play around localy:
Copy app/config.json.template to app/config.json and modify the latter: Copy app/config.json.template to app/config.json and modify the latter:
@ -74,20 +112,31 @@ Alternatively if you don't want to build either and mount the config at runtime
docker run --name webssh2 -d -p 2222:2222 -v `pwd`/app/config.json:/usr/src/config.json billchurch/webssh2 docker run --name webssh2 -d -p 2222:2222 -v `pwd`/app/config.json:/usr/src/config.json billchurch/webssh2
``` ```
<ignoreend>
# Options # Options
## GET request vars ## Environment Variables
Environment variables introduced in 0.4.7 will override anything specified in `config.json`. This is useful for settings that may be per-node, or in a container environment. These are optional and will default to whatever their peer config.json settings are
* **LISTEN** - _string_ - IP address node should listen on for client connections, defaults to `127.0.0.1`. Peer is **listen.ip**
* **PORT** - _integer_ - Port node should listen on for client connections, defaults to `2222`. Peer is **listen.port**
* **SOCKETIO_ORIGINS** - _array_ - COORS origins to allow connections from to socket.io server, defaults to `localhost:2222`. Changed in 0.3.1, to enable previous, less secure, default behavior of everything use `*:*` (not recommended). Check [#240](../../issues/240). Peer is **socketio.origins**
* **SOCKETIO_PATH** _string_ - Path to socket.io client files. Default: `/ssh/socket.io`. Peer is **socketio.path**
* **SOCKETIO_SERVECLIENT** _boolean_ - serve the socket.io client. This is built into the custom javascript, so you shouldn't need this. Kept as an option just in case. Default: `false`. Peer is **socketio.serveClient**
## POST request vars (in main branch for testing)
* **username** - _string_ - username to log into ssh with
* **userpassword** _string_ password to log into ssh with
* **port=** - _integer_ - port of SSH server (defaults to 22) * **port=** - _integer_ - port of SSH server (defaults to 22)
* **header=** - _string_ - optional header to display on page * **header=** - _string_ - optional header to display on page
* **sshterm=** - _string_ - optional specify terminal emulation to use, defaults to `ssh.term` in `config.json` or `vt100` if that is null
* **headerBackground=** - _string_ - optional background color of header to display on page * **headerBackground=** - _string_ - optional background color of header to display on page
* **sshterm=** - _string_ - optional specify terminal emulation to use, defaults to `ssh.term` in `config.json` or `vt100` if that is null
* **readyTimeout=** - _integer_ - How long (in milliseconds) to wait for the SSH handshake to complete. **Default:** 20000. **Enforced Values:** Min: 1, Max: 300000 * **readyTimeout=** - _integer_ - How long (in milliseconds) to wait for the SSH handshake to complete. **Default:** 20000. **Enforced Values:** Min: 1, Max: 300000
* **cursorBlink** - _boolean_ - Cursor blinks (true), does not (false) **Default:** true. * **cursorBlink** - _boolean_ - Cursor blinks (true), does not (false) **Default:** true.
@ -98,6 +147,42 @@ docker run --name webssh2 -d -p 2222:2222 -v `pwd`/app/config.json:/usr/src/conf
* **bellStyle** - _string_ - Style of terminal bell: ("sound"|"none"). **Default:** "sound". **Enforced Values:** "sound", "none" * **bellStyle** - _string_ - Style of terminal bell: ("sound"|"none"). **Default:** "sound". **Enforced Values:** "sound", "none"
* **fontSize** - _number_ - Size of terminal font. **Default:** 12
* **fontFamily** - _string_ - Font family
* **letterSpacing** - _number_ - Letter spacing
* **lineHeight** - _number_ - Line height
## GET request vars
* **port=** - _integer_ - port of SSH server (defaults to 22)
* **header=** - _string_ - optional header to display on page
* **headerBackground=** - _string_ - optional background color of header to display on page
* **sshterm=** - _string_ - optional specify terminal emulation to use, defaults to `ssh.term` in `config.json` or `vt100` if that is null
* **readyTimeout=** - _integer_ - How long (in milliseconds) to wait for the SSH handshake to complete. **Default:** 20000. **Enforced Values:** Min: 1, Max: 300000
* **cursorBlink** - _boolean_ - Cursor blinks (true), does not (false) **Default:** true.
* **scrollback** - _integer_ - Lines in the scrollback buffer. **Default:** 10000. **Enforced Values:** Min: 1, Max: 200000
* **tabStopWidth** - _integer_ - Tab stops at _n_ characters **Default:** 8. **Enforced Values:** Min: 1, Max: 100
* **bellStyle** - _string_ - Style of terminal bell: ("sound"|"none"). **Default:** "sound". **Enforced Values:** "sound", "none"
* **fontSize** - _number_ - Size of terminal font. **Default:** "12"
* **fontFamily** - _string_ - Font family
* **letterSpacing** - _number_ - Letter spacing
* **lineHeight** - _integer_ - Line height
## Headers ## Headers
* **allowreplay** - _boolean_ - Allow use of password replay feature, example `allowreplay: true` * **allowreplay** - _boolean_ - Allow use of password replay feature, example `allowreplay: true`
@ -111,7 +196,11 @@ docker run --name webssh2 -d -p 2222:2222 -v `pwd`/app/config.json:/usr/src/conf
* **listen.port** - _integer_ - Port node should listen on for client connections, defaults to `2222` * **listen.port** - _integer_ - Port node should listen on for client connections, defaults to `2222`
* **http.origins** - _array_ - COORS origins to allow connections from to socket.io server, defaults to `localhost:2222`. Changed in 0.3.1, to enable previous, less secure, default behavior of everything use `*:*` (not recommended). Check [#240](../../issues/240) * **socketio.serveClient** - _boolean_ - serve the socket.io client. This is built into the custom javascript, so you shouldn't need this. Kept as an option just in case. Default: `false`
* **socketio.path** - _string_ - Path to socket.io client files. Default: `/ssh/socket.io`
* **socketio.origins** - _array_ - COORS origins to allow connections from to socket.io server, defaults to `localhost:2222`. Changed in 0.3.1, to enable previous, less secure, default behavior of everything use `*:*` (not recommended). Check [#240](../../issues/240)
* **user.name** - _string_ - Specify user name to authenticate with. In normal cases this should be left to the default `null` setting. * **user.name** - _string_ - Specify user name to authenticate with. In normal cases this should be left to the default `null` setting.
@ -141,6 +230,14 @@ docker run --name webssh2 -d -p 2222:2222 -v `pwd`/app/config.json:/usr/src/conf
* **terminal.bellStyle** - _string_ - Style of terminal bell: (sound|none). **Default:** "sound". * **terminal.bellStyle** - _string_ - Style of terminal bell: (sound|none). **Default:** "sound".
* **terminal.fontSize** - _number_ - Size of terminal font. **Default:** 14.
* **terminal.fontFamily** - _string_ - Font family
* **terminal.letterSpacing** - _number_ - Letter spacing
* **terminal.lineHeight** - _number_ - Line height
* **header.text** - _string_ - Specify header text, defaults to `My Header` but may also be set to `null`. When set to `null` no header bar will be displayed on the client. * **header.text** - _string_ - Specify header text, defaults to `My Header` but may also be set to `null`. When set to `null` no header bar will be displayed on the client.
* **header.background** - _string_ - Header background, defaults to `green`. * **header.background** - _string_ - Header background, defaults to `green`.

16
SECURITY.md Normal file
View file

@ -0,0 +1,16 @@
# Security Policy
## Supported Versions
The following versions will get security updates.
| Version | Supported |
| ------- | ------------------ |
| 0.4.x | :white_check_mark: |
| 0.3.x | :x: |
| 0.2.x | :x: |
| 0.1.x | :x: |
## Reporting a Vulnerability
If you find a vulnerability, simply [open an issue](../../issues/new) with the details, use the label `security`.

1
app/.npmrc Normal file
View file

@ -0,0 +1 @@
tag-version-prefix=""

View file

@ -2,6 +2,60 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [0.5.0-pre-4](https://github.com/billchurch/webssh2/compare/webssh2-v0.4.7-pre-4...webssh2-v0.5.0-pre-4) (2022-08-07)
### Features
* test change for release ([476b566](https://github.com/billchurch/webssh2/commit/476b566c08a84bd35aaccf847253875b2c3afb10))
## [0.4.7-pre-4](https://github.com/billchurch/webssh2/compare/webssh2-v0.4.7-pre-3...webssh2-v0.4.7-pre-4) (2022-08-03)
### Miscellaneous Chores
* release 0.4.7-pre-4 ([7d4ba87](https://github.com/billchurch/webssh2/commit/7d4ba87bc1c198600ea33ee220553ef46ea2a103))
## [0.4.7-pre-3](https://github.com/billchurch/webssh2/compare/webssh2-v0.4.7-pre-2...webssh2-v0.4.7-pre-3) (2022-08-03)
### Miscellaneous Chores
* release 0.4.7-pre-3 ([0c78c1f](https://github.com/billchurch/webssh2/commit/0c78c1f31cc6380b7f0706822fc418cfede11413))
## [0.4.7-pre-2](https://github.com/billchurch/webssh2/compare/webssh2-v0.4.6...webssh2-v0.4.7-pre-2) (2022-08-02)
### ⚠ BREAKING CHANGES
* validate referer to /reauth is valid
* bump xterm to 4.18.0
* consistent logging messages see #286
* config system changes #284 (#285)
### Features
* add additional params for POST requests [#290](https://github.com/billchurch/webssh2/issues/290) ([46c1560](https://github.com/billchurch/webssh2/commit/46c1560e3c126376e18124e14e5c7fb8c029a0a1))
* add additional vars to POST requests [#290](https://github.com/billchurch/webssh2/issues/290) ([0a4e419](https://github.com/billchurch/webssh2/commit/0a4e419fb371ae95340fa890497022a2aa9d063a))
* add fontFamily, letterSpacing, lineHeight ([97f3088](https://github.com/billchurch/webssh2/commit/97f3088780744e13a6724a4967a4896aac3f20d8))
* add fontSize option [#292](https://github.com/billchurch/webssh2/issues/292) ([5e78812](https://github.com/billchurch/webssh2/commit/5e788129744d326e78ec91bda86ed5cecfd70d3f))
* config system changes [#284](https://github.com/billchurch/webssh2/issues/284) ([#285](https://github.com/billchurch/webssh2/issues/285)) ([9c99b09](https://github.com/billchurch/webssh2/commit/9c99b0940ec726193deae3c4999d25a297874d67))
* consistent logging messages see [#286](https://github.com/billchurch/webssh2/issues/286) ([50cfcb9](https://github.com/billchurch/webssh2/commit/50cfcb97788cbd3409b4605adceef3d47e370e38))
* credentials over http post for [#290](https://github.com/billchurch/webssh2/issues/290) ([5b8f88c](https://github.com/billchurch/webssh2/commit/5b8f88cfef1745c88748277217204e6c38c7ff7e))
* reorder viewport setup at ssh handshake [#292](https://github.com/billchurch/webssh2/issues/292) ([140e1e2](https://github.com/billchurch/webssh2/commit/140e1e24b14d6b74848e9d250c2b44f806ad627d))
* validate referer to /reauth is valid ([0dcaa6e](https://github.com/billchurch/webssh2/commit/0dcaa6e15062cdc3252ce52abd9057caf4c00a30))
### Bug Fixes
* Fix the parameter passing problem of setDefaultCredentials to make it perform data initialization normally ([#288](https://github.com/billchurch/webssh2/issues/288)) ([40cbb35](https://github.com/billchurch/webssh2/commit/40cbb35616fa17c1c36520690f40ebce0b488153))
* invalid css in style.css ([ffab534](https://github.com/billchurch/webssh2/commit/ffab5345dcb568fa2bb50a96f403174ad3728286))
### package
* bump xterm to 4.18.0 ([84c09ec](https://github.com/billchurch/webssh2/commit/84c09ec8a1909e4bbd0051debdbb905276a4245e))
### [0.4.6](https://github.com/billchurch/WebSSH2/compare/v0.2.10-0...v0.4.6) (2022-04-17) ### [0.4.6](https://github.com/billchurch/WebSSH2/compare/v0.2.10-0...v0.4.6) (2022-04-17)
@ -24,3 +78,384 @@ All notable changes to this project will be documented in this file. See [standa
* update config.json.sample ([#177](https://github.com/billchurch/WebSSH2/issues/177)) ([42f973b](https://github.com/billchurch/WebSSH2/commit/42f973b4796f7f50237dc8ce613e477aa89352ca)) * update config.json.sample ([#177](https://github.com/billchurch/WebSSH2/issues/177)) ([42f973b](https://github.com/billchurch/WebSSH2/commit/42f973b4796f7f50237dc8ce613e477aa89352ca))
* update read-config-ng to 3.0.5, fixes [#277](https://github.com/billchurch/WebSSH2/issues/277) ([3e82c0d](https://github.com/billchurch/WebSSH2/commit/3e82c0dc4d31d1c97a7cf98139ef8e6dc0213b22)) * update read-config-ng to 3.0.5, fixes [#277](https://github.com/billchurch/WebSSH2/issues/277) ([3e82c0d](https://github.com/billchurch/WebSSH2/commit/3e82c0dc4d31d1c97a7cf98139ef8e6dc0213b22))
* update xterm.js fixes [#261](https://github.com/billchurch/WebSSH2/issues/261) ([c801ef9](https://github.com/billchurch/WebSSH2/commit/c801ef9e5826e13a403a6462241cf8a4ff456d45)) * update xterm.js fixes [#261](https://github.com/billchurch/WebSSH2/issues/261) ([c801ef9](https://github.com/billchurch/WebSSH2/commit/c801ef9e5826e13a403a6462241cf8a4ff456d45))
## 0.4.5 [20220417]
### Fixes
- update read-config-ng to 3.0.5, fixes [#277](../../issues/277)
## 0.4.5 [20220331]
### Fixes
- Update socket.io to 4.2.0
- Update read-config-ng to 3.0.4
## 0.4.4 [20211209]
### Fixes
- Add ./node_modules to .dockerignore [#240](../../issues/240) thanks @UncleSamSwiss
- validator to 13.7.0 [to mitigate potential Regular Expression Denial of Service (ReDoS)](https://snyk.io/vuln/SNYK-JS-VALIDATOR-1090600)
- cidr-matcher should be [re-installed to pickup >json-schema@4.0.0 due to prototype pollution vulnerability](https://snyk.io/vuln/SNYK-JS-JSONSCHEMA-1920922)
- Update xterm.js to 4.15.0 [#261](../../issues/261)
- Replace deprecated term.setOptions with term.options
### Changes
- update README.md for additional Docker methods thanks @Utopiah
## 0.4.3 [20211019]
- update dependencies
- ssh2 to 1.4.0 [to mitigate potential command injection in windows](https://snyk.io/vuln/SNYK-JS-SSH2-1656673)
## 0.4.2 [20210813]
### changes
- update dependencies
- socket.io to 4.1.1
- read-config-ng to 3.0.2
- debug to 4.3.1
## 0.4.1 [20210703]
### Fixes
- lost comma in config.json.sample 71fe377
### Changes
- bump ws@7.4.6 to [mitigate potential ReDoS vulnerability](https://github.com/websockets/ws/releases/tag/7.4.6)
- dev: update CI tools
- dev: update dev tools
- dev: update build tools
## 0.4.0 [20210519]
### BREAKING
- Disabled ssh.serverlog.client option, this disables the POC which allowed for logging of the data sent between the client/server to the console.log.
- Dropping support for node versions under 14
### Changes
- Removed HTML menu code from ./app/server/socket.js, the menu is now fully laid out in the ./app/client/src/index.html and the option elements are hidden by default. Not sure why it wasn't done this way from the start, but there it is.
- Updated socket.io to v4.1.1
- Client javascript `./app/client/src/js/index.ts` is now built on TypeScript (`npm run build` will generate javascript for client and place into `app/client/public/webssh2.bundle.js` as before)
- Build environment changes
- removed unused xterm-addon-search, xterm-addon-weblinks, standard, postcss-discard-comments
- added prettier 2.3.0, typescript modules, socket.io-client 4.1.1, airbnb linting tools
### Added
- Lookup ip address for hostname in URL, fixes #199 thanks to @zwiy
- Ability to override `Authorization: Basic` header and replace with credentials specified in `config.json` fixes #243. New config.json option `user.overridebasic`
### CONTRIBUTING
In this release, we're trying our best to conform to the [Airbnb Javascript Style Guide](https://airbnb.io/projects/javascript/). I'm hoping this will make contributions easier and keep the code readable. I love shortcuts more than anyone but I've found when making changes to code I've not looked at in a while, it can take me a few momements to deconstruct what was being done due to readbility issues. While I don't agree with every decision in the style guide (semi-colons, yuk), it is a good base to keep the code consistent.
If you've not used it before, I recommend installing the [vscode extensions](https://blog.echobind.com/integrating-prettier-eslint-airbnb-style-guide-in-vscode-47f07b5d7d6a) for that and [Prettier](https://prettier.io/) and getting familiar. The autocorrections are great (especially if you hate dealing with semi-colons...)
As of 0.4.0-testing-0, the client code is written in [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html). It's not that much different from JavaScript, and the introduction strong typing will ultimately help to produce better code. Eventually we want to move the whole project to TypeScript but that make take a bit more time. Take a moment to look at ./app/client/src/js/index.ts to see what TypeScript looks like.
## 0.3.1 [20210513]
### BREAKING
- Ability to configure CORS settings for socket.io see [#240](../../issues/240) for more information on how this may break existing deployments. Default settings in example `config.json` are currently permissive `http.origins: ["*:*"]` please note that if a `config.json` is not present, the default is `http.origins: ["localhost:2222"]
### Added
- Safe Shutdown Feature - thanks to @edgarogh
- Sending SIGINT or SIGTERM to node process responsible for WebSSH2 or Docker process will result in a "safe" shutdown
- Timer is configured in config.safeShutdownDuration
- feat: Use docker build to create multi-arch images (#202)
### Fixed
- obey host ssh.host in config fixes #190
### Changed
- `config.json.sample`: `allowreauth` now defaults to `false` fixes #238
- update ssh2 to 0.8.8 -> 0.8.9 - [comparison at ssh2 repo](https://github.com/mscdex/ssh2/compare/v0.8.8...v0.8.9)
- update xterm to 4.12.0 [comparison at xtermjs repo](https://github.com/xtermjs/xterm.js/compare/4.4.0...4.12.0)
- update read-config-ng to 3.0.2
- update morgan to 1.10.0
- update debug to 4.3.1
- update express-session to 1.17.1
- update validator to 13.6.0
- development tools updates (build environment requires minimum of Node 10, only needed for customization)
- update @fortawesome/fontawesome-svg-core to 1.2.35
- update @fortawesome/free-solid-svg-icons to 5.15.3
- update copy-webpack-plugin to 8.1.1
- update cross-env to 7.0.3
- update css-loader to 5.2.4
- update file-loader to 6.2.0
- update mini-css-extract-plugin to 1.6.0
- update postcss-discard-comments to 5.0.0
- update snazzy to 9.0.0
- update standard to 16.0.3
- update standard-version to 9.3.0
- update style-loader to 2.0.0
- update terser-webpack-plugin to 5.1.1
- update url-loader to 4.1.1
- update webpack to 5.37.0
- update webpack-cli to 4.7.0
- update webpack-merge to 5.7.3
- update webpack-stream to 6.1.2
- update xterm-addon-fit to 0.5.0
- update xterm-addon-search to 0.8.0
- update xterm-addon-web-links to 0.4.0
- update ssri from 6.0.1 to 6.0.2 [#233](../../pull/233)
- update hosted-git-info from 2.8.5 to 2.8.9 [#237](../../pull/237)
- update lodash from 4.17.19 to 4.17.21 [#236](../../pull/236)
- update handlebars from 4.7.6 to 4.7.7 [#235](../../pull/235)
- update y18n from 4.0.0 to 4.0.1 [#230](../../pull/230)
- update elliptic from 6.5.3 to 6.5.4 [#228](../../pull/222833)
- update ini from 1.3.5 to 1.3.8 [#217](../../pull/217)
## 0.3.0 [20200315]
🍀🍀🍀
### Added
- Add configuration option to restrict connections to specified subnets thanks to @Mierdin
- favicon
- added module `serve-favicon` to serve favicon from root if pre-fetched by browser
- added `link rel=icon` line in client.htm to serve favico.ico out of /ssh/
### Changed
- Using new repo for read-config -> read-config-ng-
- removed express compression feature, added no real value.
- module updates
- ssh2 to 0.8.6 -> 0.8.8 - [comparison at ssh2 repo](https://github.com/mscdex/ssh2/compare/v0.8.6...v0.8.8)
- xterm 4.2.0 -> 4.4.0 - [comparison at xtermjs repo](https://github.com/xtermjs/xterm.js/compare/4.2.0...4.4.0)
- read-config-ng 3.0.1 - (taking over abandoned repo)n
- development module updates (does not impact production, only for development and rebuilding)
- fortawesome/fontawesome-svg-core 1.2.27
- fortawesome/free-solid-svg-icons 5.12.1
- standard-version 7.1.0
- webpack 4.42.0
- webpack-cli 3.3.11
- terser-webpack-plugin 2.3.5
- copy-webpack-plugin 5.1.1
- cross-env 7.0.2
- css-loader 3.4.2
- file-loader 5.1.0
- style-loader 1.1.3
- url-loader 3.0.0
### Potentially Breaking Changes
- Move all child resources to start from under /ssh
- /socket.io -> /ssh/socket.io
- /webssh2.css -> /ssh/webssh2.css
- /webssh2.bundle.js -> /ssh/webssh2.bundle.js
- /reauth -> /ssh/reauth
- perhaps more
### Fixes
- Typo in config.json.sample, thanks @wuchihsu, fixes #173
### Housekeeping
- Removed irrelavant build scripts from /scripts
## 0.2.9 [2019-06-13]
### Changes
- Missing require('fs') in `server/app.js` See issue [#135](../../issues/135)
- Patched read-config to mitigate vulnerability in js-yaml
- issue not exploitable on webssh2 implementation
- patched anyway
- sending my patch upstream to read-config, webssh2 package.json points to patched version in my repository https://github.com/billchurch/nodejs-read-config
- See https://github.com/nodeca/js-yaml/issues/475 for more detail
## 0.2.8 [2019-05-25]
### Changes
- Fixes issue if no password is entered, browser must be closed and restart to attempt to re-auth. See issue [#118](../../issues/118). Thanks @smilesm2 for the idea.
- fixes broken `npm run (build|builddev)`
- update font-awesome fonts to 5.6.3
- update webpack and dependancies
- update xterm to 3.8.0
### Fixes
- ILX workspace may not always import properly due to symbolic links (specifically ./node_modules/.bin). This is removed from the ILX package
## 0.2.7 [2018-11-11]
### Changes
- `config.reauth` was not respected if initial auth presented was incorrect, regardless of `reauth` setting in `config.json` reauth would always be attempted. fixes [#117](../../issues/117)
- **BREAKING** moved app files to /app, this may be a breaking change
- Updated dockerfile for new app path
- Updated app dependancies
- xterm v3.8.0
- https://github.com/xtermjs/xterm.js/releases/tag/3.8.0
- basic-auth v2.0.1
- https://github.com/jshttp/basic-auth/releases/tag/v2.0.1
- express v4.16.4
- https://github.com/expressjs/express/releases/tag/4.16.4
- validator v10.9.0
- https://github.com/chriso/validator.js/releases/tag/10.9.0
- Updated dev dependancies
- snazzy v8.0.0
- standard v12.0.1
- uglifyjs-webpack-plugin v2.0.1
- ajv v6.5.5
- copy-webpack-plugin v4.6.0
- css-loader v1.0.1
- nodemon v1.18.6
- postcss-discard-comments v4.0.1
- snyk v1.108.2
- url-loader v1.1.2
- webpack v4.25.1
- webpack-cli v3.1.2
## 0.2.6 [2018-11-09]
### Changes
- Reauth didn't work if intial auth presented was incorrect, (see issue #112) fixed thanks @vvalchev
- Update node version supported to >=6 (PR #115) thanks @perlun
- Update packages
- developer dependencies
## 0.2.5 [2018-09-11]
### Added
- Reauth function thanks to @vbeskrovny and @vvalchev (9bbc116)
- Controlled by `config.json` option `options.allowreauth` true presents reauth dialog and false hides dialog
### Changed
- `options.challengeButton` enabled
- previously this configuration option did nothing, this now enables the Credentials button site-wide regardless of the `allowreplay` header value
- Updated debug module to v4
## 0.2.4 [2018-07-18]
### Added
- Browser title window now changes with xterm escape sequences (see http://tldp.org/HOWTO/Xterm-Title-3.html)
- Added bellStyle options
- `GET var`: **bellStyle** - _string_ - Style of terminal bell: ("sound"|"none"). **Default:** "sound". **Enforced Values:** "sound "none"
- `config.json`: **terminal.bellStyle** - _string_ - Style of terminal bell: (sound|none). **Default:** "sound".
- `workspace` folder on GITHUB for BIG-IP specific fixes/changes
### Changed
- Updated xterm.js to 3.1.0
- https://github.com/xtermjs/xterm.js/releases/tag/3.1.0
- Default listen IP in `config.json` changed back to 127.0.0.1
### Fixed
- ESC]0; is now removed from log files when using the browser-side logging feature
## 0.2.3 unreleased
### Fixed
- ESC]0; is now removed from log files when using the browser-side logging feature
## 0.2.0 [2018-02-10]
Mostly client (browser) related changes in this release
### Added
- Menu system
- Fontawesome icons
- Resizing browser window sends resize events to terminal container as well as SSH session (pty)
- New terminal options (config.json as well as GET vars)
- terminal.cursorBlink - boolean - Cursor blinks (true), does not (false) Default: true.
- terminal.scrollback - integer - Lines in the scrollback buffer. Default: 10000.
- terminal.tabStopWidth - integer - Tab stops at n characters Default: 8.
- New serverside (nodejs) terminal configuration options (cursorBlink, scrollback, tabStopWidth)
- Logging of MRH session (unassigned if not present)
- Express compression feature
### Changed
- Updated xterm.js to 3.0.2
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.2
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.1
- See https://github.com/xtermjs/xterm.js/releases/tag/3.0.0
- Moved javascript events out of html into javascript
- Changed asset packaging from grunt to Webpack to be inline with xterm.js direction
- Moved logging and credentials buttons to menu system
- Removed non-minified options (if you need to disable minification, modify webpack scripts and 'npm run build')
### Fixed
- Resolved loss of terminal foucs when interacting with option buttons (Logging, etc...)
## 0.1.4 [2018-01-30]
### Changed
- Moved socket and util out of folders into .js in root.
- added keepaliveInterval and keepaliveCountMax config options
## 0.1.3 [2017-09-28]
### Changed
- Upgrade to debug@3.1 to eliminate ReDoS in %o formatter
- Upgrade Express to 4.15.5 for ReDOS
- Upgrade basic-auth to v2.0
## 0.1.2 [2017-07-31]
### Added
- ssh.readyTimeout option in config.json (time in ms, default 20000, 20sec)
### Changed
- Updated xterm.js to 2.9.2 from 2.6.0
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.2
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.1
- See https://github.com/sourcelair/xterm.js/releases/tag/2.9.0
- See https://github.com/sourcelair/xterm.js/releases/tag/2.8.1
- See https://github.com/sourcelair/xterm.js/releases/tag/2.8.0
- See https://github.com/sourcelair/xterm.js/releases/tag/2.7.0
- Updated ssh2 to 0.5.5 to keep current, no fixes impacting WebSSH2
- ssh-streams to 0.1.19 from 0.1.16
- Updated validator.js to 8.0.0, no fixes impacting WebSSH2
- https://github.com/chriso/validator.js/releases/tag/8.0.0
- Updated Express to 4.15.4, no fixes impacting WebSSH2
- https://github.com/expressjs/express/releases/tag/4.15.4
- Updated Express-session to 1.15.5, no fixes impacting WebSSH2
- https://github.com/expressjs/session/releases/tag/v1.15.5
- Updated Debug to 3.0.0, no fixes impacting WebSSH2
- https://github.com/visionmedia/debug/releases/tag/3.0.0
- Running in strict mode ('use strict';)
## 0.1.1 [2017-06-03]
### Added
- `serverlog.client` and `serverlog.server` options added to `config.json` to enable logging of client commands to server log (only client portion implemented at this time)
- morgan express middleware for logging
### Changed
- Updated socket.io to 1.7.4
- continued refactoring, breaking up `index.js`
- revised error handling methods
- revised session termination methods
### Fixed
### Removed
- color console decorations from `util/index.js`
- SanatizeHeaders function from `util/index.js`
## 0.1.0 [2017-05-27]
### Added
- This ChangeLog.md file
- Support for UTF-8 characters (thanks @bara666)
- Snyk, Bithound, Travis CI
- Cross platform improvements (path mappings)
- Session fixup between Express and Socket.io
- Session secret settings in `config.json`
- env variable `DEBUG=ssh2` will put the `ssh2` module into debug mode
- env variable `DEBUG=WebSSH2` will output additional debug messages for functions
and events in the application (not including the ssh2 module debug)
- using Grunt to pull js and css source files from other modules `npm run build` to rebuild these if changed or updated.
- `useminified` option in `config.json` to enable using minified client side javascript (true) defaults to false (non-minified)
- sshterm= query option to specify TERM environment variable for host, valid strings are alpha-numeric with a hypen (validated). Otherwise the default ssh.term variable from `config.json` will be used.
- validation for host (v4,v6,fqdn,hostname), port (integer 2-65535), and header (sanitized) from URL input
### Changed
- error handling in public/client.js
- moved socket.io operations to their own file /socket/index.js, more changes like this to come (./socket/index.js)
- all session based variables are now under the req.session.ssh property or socket.request.ssh (./index.js)
- moved SSH algorithms to `config.json` and defined as a session variable (..session.ssh.algorithms)
-- prep for future feature to define algorithms in header or some other method to enable separate ciphers per host
- minified and combined all js files to a single js in `./public/webssh2.min.js` also included a sourcemap `./public/webssh2.min.js` which maps to `./public/webssh2.js` for easier troubleshooting.
- combined all css files to a single css in `./public/webssh2.css`
- minified all css files to a single css in `./public/webssh2.min.css`
- copied all unmodified source css and js to /public/src/css and /public/src/js respectively (for troubleshooting/etc)
- sourcemaps of all minified code (in /public/src and /public/src/js)
- renamed `client.htm` to `client-full.htm`
- created `client-min.htm` to serve minified javascript
- if header.text is null in `config.json` and header is not defined as a get parameter the Header will not be displayed. Both of these must be null / undefined and not specified as get parameters.
### Fixed
- Multiple errors may overwrite status bar which would cause confusion as to what originally caused the error. Example, ssh server disconnects which prompts a cascade of events (conn.on('end'), socket.on('disconnect'), conn.on('close')) and the original reason (conn.on('end')) would be lost and the user would erroneously receive a WEBSOCKET error as the last event to fire would be the websocket connection closing from the app.
- ensure ssh session is closed when a browser disconnects from the websocket
- if headerBackground is changed, status background is changed to the same color (typo, fixed)
### Removed
- Express Static References directly to module source directories due to concatenating and minifying js/css
## 0.0.5 - [2017-03-23]
### Added
- Added experimental support for logging (see Readme)
### Fixed
- Terminal geometry now properly fills the browser screen and communicates this to the ssh session. Tested with IE 11 and recent versions of Chrome/Safari/Firefox.
## 0.0.4 - [2017-03-23]
### Added
- Set default terminal to xterm-color
- Mouse event support
- New config option, config.ssh.term to set terminal
### Changed
- Update to Xterm.js 2.4.0
- Minor code formatting cleanup
## 0.0.3 - [2017-02-16]
### Changed
- Update xterm to latest (2.3.0)
### Fixed
- Fixed misspelled config.ssh.port property
## 0.0.2 - [2017-02-01]
### Changed
- Moving terminal emulation to xterm.js
- updating module version dependencies
### Fixed
- Fixed issue with banners not being displayed properly from UNIX hosts when only lf is used
## 0.0.1 - [2016-06-28]
### Added
- Initial proof of concept and release. For historical purposes only.

21
app/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Bill Church
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

BIN
app/bun.lockb Executable file

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -1,4 +0,0 @@
/*!
* Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
*/

View file

@ -36,6 +36,7 @@
*/ */
.xterm { .xterm {
cursor: text;
position: relative; position: relative;
user-select: none; user-select: none;
-ms-user-select: none; -ms-user-select: none;
@ -124,16 +125,13 @@
line-height: normal; line-height: normal;
} }
.xterm {
cursor: text;
}
.xterm.enable-mouse-events { .xterm.enable-mouse-events {
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
cursor: default; cursor: default;
} }
.xterm.xterm-cursor-pointer { .xterm.xterm-cursor-pointer,
.xterm .xterm-cursor-pointer {
cursor: pointer; cursor: pointer;
} }
@ -142,7 +140,7 @@
cursor: crosshair; cursor: crosshair;
} }
.xterm .xterm-accessibility, .xterm .xterm-accessibility:not(.debug),
.xterm .xterm-message { .xterm .xterm-message {
position: absolute; position: absolute;
left: 0; left: 0;
@ -151,6 +149,16 @@
right: 0; right: 0;
z-index: 10; z-index: 10;
color: transparent; color: transparent;
pointer-events: none;
}
.xterm .xterm-accessibility-tree:not(.debug) *::selection {
color: transparent;
}
.xterm .xterm-accessibility-tree {
user-select: text;
white-space: pre;
} }
.xterm .live-region { .xterm .live-region {
@ -162,21 +170,56 @@
} }
.xterm-dim { .xterm-dim {
opacity: 0.5; /* Dim should not apply to background, so the opacity of the foreground color is applied
* explicitly in the generated class and reset to 1 here */
opacity: 1 !important;
} }
.xterm-underline { .xterm-underline-1 { text-decoration: underline; }
text-decoration: underline; .xterm-underline-2 { text-decoration: double underline; }
.xterm-underline-3 { text-decoration: wavy underline; }
.xterm-underline-4 { text-decoration: dotted underline; }
.xterm-underline-5 { text-decoration: dashed underline; }
.xterm-overline {
text-decoration: overline;
} }
.xterm-overline.xterm-underline-1 { text-decoration: overline underline; }
.xterm-overline.xterm-underline-2 { text-decoration: overline double underline; }
.xterm-overline.xterm-underline-3 { text-decoration: overline wavy underline; }
.xterm-overline.xterm-underline-4 { text-decoration: overline dotted underline; }
.xterm-overline.xterm-underline-5 { text-decoration: overline dashed underline; }
.xterm-strikethrough { .xterm-strikethrough {
text-decoration: line-through; text-decoration: line-through;
} }
.xterm-screen .xterm-decoration-container .xterm-decoration {
z-index: 6;
position: absolute;
}
.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer {
z-index: 7;
}
.xterm-decoration-overview-ruler {
z-index: 8;
position: absolute;
top: 0;
right: 0;
pointer-events: none;
}
.xterm-decoration-top {
z-index: 2;
position: relative;
}
body, html { body, html {
font-family: helvetica, sans-serif, arial; font-family: helvetica, sans-serif, arial;
font-size: 1em; font-size: 1em;
color: #111;
background-color: rgb(0, 0, 0); background-color: rgb(0, 0, 0);
color: rgb(240, 240, 240); color: rgb(240, 240, 240);
height: 100%; height: 100%;
@ -201,7 +244,7 @@ body, html {
} }
#terminal-container { #terminal-container {
display: block; display: block;
width: calc(100% - 1 px); width: calc(100% - 1px);
margin: 0 auto; margin: 0 auto;
padding: 2px; padding: 2px;
height: calc(100% - 19px); height: calc(100% - 19px);
@ -314,7 +357,7 @@ body, html {
.dropup:hover .dropup-content { .dropup:hover .dropup-content {
display: block; display: block;
} }
.dropup:click .dropup-content { .dropup:active .dropup-content {
display: block; display: block;
} }
.dropup:hover .dropbtn { .dropup:hover .dropbtn {

View file

@ -1,7 +1,6 @@
body, html { body, html {
font-family: helvetica, sans-serif, arial; font-family: helvetica, sans-serif, arial;
font-size: 1em; font-size: 1em;
color: #111;
background-color: rgb(0, 0, 0); background-color: rgb(0, 0, 0);
color: rgb(240, 240, 240); color: rgb(240, 240, 240);
height: 100%; height: 100%;
@ -26,7 +25,7 @@ body, html {
} }
#terminal-container { #terminal-container {
display: block; display: block;
width: calc(100% - 1 px); width: calc(100% - 1px);
margin: 0 auto; margin: 0 auto;
padding: 2px; padding: 2px;
height: calc(100% - 19px); height: calc(100% - 19px);
@ -139,7 +138,7 @@ body, html {
.dropup:hover .dropup-content { .dropup:hover .dropup-content {
display: block; display: block;
} }
.dropup:click .dropup-content { .dropup:active .dropup-content {
display: block; display: block;
} }
.dropup:hover .dropbtn { .dropup:hover .dropbtn {

View file

@ -1,23 +1,15 @@
/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable import/no-extraneous-dependencies */
import { io } from 'socket.io-client'; import { io } from 'socket.io-client';
import { Terminal } from 'xterm'; import { Terminal } from '@xterm/xterm';
import { FitAddon } from 'xterm-addon-fit'; import { FitAddon } from '@xterm/addon-fit';
import { library, dom } from '@fortawesome/fontawesome-svg-core'; import { library, dom } from '@fortawesome/fontawesome-svg-core';
import { faBars, faClipboard, faDownload, faKey, faCog } from '@fortawesome/free-solid-svg-icons'; import { faBars, faClipboard, faDownload, faKey, faCog } from '@fortawesome/free-solid-svg-icons';
// for Internet Explorer compatibility... i know gross...
declare global {
interface Navigator {
msSaveBlob?: (blob: any, defaultName?: string) => boolean
msSaveOrOpenBlob?: (blob: any, defaultName?: string) => boolean
}
}
library.add(faBars, faClipboard, faDownload, faKey, faCog); library.add(faBars, faClipboard, faDownload, faKey, faCog);
dom.watch(); dom.watch();
const debug = require('debug')('WebSSH2'); const debug = require('debug')('WebSSH2');
require('xterm/css/xterm.css'); require('@xterm/xterm/css/xterm.css');
require('../css/style.css'); require('../css/style.css');
/* global Blob, logBtn, credentialsBtn, reauthBtn, downloadLogBtn */ // eslint-disable-line /* global Blob, logBtn, credentialsBtn, reauthBtn, downloadLogBtn */ // eslint-disable-line
@ -62,6 +54,7 @@ const socket = io({
// reauthenticate // reauthenticate
function reauthSession () { // eslint-disable-line function reauthSession () { // eslint-disable-line
debug('re-authenticating'); debug('re-authenticating');
socket.emit('control', 'reauth');
window.location.href = '/ssh/reauth'; window.location.href = '/ssh/reauth';
return false; return false;
} }
@ -78,7 +71,7 @@ function downloadLog () { // eslint-disable-line
[ [
sessionLog.replace( sessionLog.replace(
// eslint-disable-next-line no-control-regex // eslint-disable-next-line no-control-regex
/[\u001b\u009b][[\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><;]/g, /[\u001b\u009b][[\]()#;?]*(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-ORZcf-nqry=><;]/g,
'' ''
), ),
], ],
@ -87,9 +80,6 @@ function downloadLog () { // eslint-disable-line
type: 'text/plain', type: 'text/plain',
} }
); );
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, myFile);
} else {
const elem = window.document.createElement('a'); const elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob); elem.href = window.URL.createObjectURL(blob);
elem.download = myFile; elem.download = myFile;
@ -97,7 +87,6 @@ function downloadLog () { // eslint-disable-line
elem.click(); elem.click();
document.body.removeChild(elem); document.body.removeChild(elem);
} }
}
term.focus(); term.focus();
} }
// Set variable to toggle log data from client/server to a varialble // Set variable to toggle log data from client/server to a varialble
@ -107,7 +96,6 @@ function toggleLog () { // eslint-disable-line
sessionLogEnable = false; sessionLogEnable = false;
loggedData = true; loggedData = true;
logBtn.innerHTML = '<i class="fas fa-clipboard fa-fw"></i> Start Log'; logBtn.innerHTML = '<i class="fas fa-clipboard fa-fw"></i> Start Log';
// console.log(`stopping log, ${sessionLogEnable}`);
currentDate = new Date(); currentDate = new Date();
sessionLog = `${sessionLog}\r\n\r\nLog End for ${sessionFooter}: ${currentDate.getFullYear()}/${ sessionLog = `${sessionLog}\r\n\r\nLog End for ${sessionFooter}: ${currentDate.getFullYear()}/${
currentDate.getMonth() + 1 currentDate.getMonth() + 1
@ -121,7 +109,6 @@ function toggleLog () { // eslint-disable-line
logBtn.innerHTML = '<i class="fas fa-cog fa-spin fa-fw"></i> Stop Log'; logBtn.innerHTML = '<i class="fas fa-cog fa-spin fa-fw"></i> Stop Log';
downloadLogBtn.style.color = '#000'; downloadLogBtn.style.color = '#000';
downloadLogBtn.addEventListener('click', downloadLog); downloadLogBtn.addEventListener('click', downloadLog);
// console.log(`starting log, ${sessionLogEnable}`);
currentDate = new Date(); currentDate = new Date();
sessionLog = `Log Start for ${sessionFooter}: ${currentDate.getFullYear()}/${ sessionLog = `Log Start for ${sessionFooter}: ${currentDate.getFullYear()}/${
currentDate.getMonth() + 1 currentDate.getMonth() + 1
@ -134,7 +121,7 @@ function toggleLog () { // eslint-disable-line
// replay password to server, requires // replay password to server, requires
function replayCredentials () { // eslint-disable-line function replayCredentials () { // eslint-disable-line
socket.emit('control', 'replayCredentials'); socket.emit('control', 'replayCredentials');
// console.log('replaying credentials'); debug(`control: replayCredentials`);
term.focus(); term.focus();
return false; return false;
} }
@ -160,6 +147,7 @@ function drawMenu() {
function resizeScreen() { function resizeScreen() {
fitAddon.fit(); fitAddon.fit();
socket.emit('resize', { cols: term.cols, rows: term.rows }); socket.emit('resize', { cols: term.cols, rows: term.rows });
debug(`resize: ${JSON.stringify({ cols: term.cols, rows: term.rows })}`);
} }
window.addEventListener('resize', resizeScreen, false); window.addEventListener('resize', resizeScreen, false);
@ -177,15 +165,22 @@ socket.on('data', (data: string | Uint8Array) => {
socket.on('connect', () => { socket.on('connect', () => {
socket.emit('geometry', term.cols, term.rows); socket.emit('geometry', term.cols, term.rows);
debug(`geometry: ${term.cols}, ${term.rows}`);
}); });
socket.on( socket.on(
'setTerminalOpts', 'setTerminalOpts',
(data: { cursorBlink: any; scrollback: any; tabStopWidth: any; bellStyle: any }) => { (data: {
term.options.cursorBlink = data.cursorBlink; cursorBlink: boolean;
term.options.scrollback = data.scrollback; scrollback: number;
term.options.tabStopWidth = data.tabStopWidth; tabStopWidth: number;
term.options.bellStyle = data.bellStyle; bellStyle: 'none' | 'sound';
fontSize: number;
fontFamily: string;
letterSpacing: number;
lineHeight: number;
}) => {
term.options = data;
} }
); );

View file

@ -1,10 +1,12 @@
{ {
"listen": { "listen": {
"ip": "0.0.0.0", "ip": "0.0.0.0",
"port": 2222 "port": 2224
}, },
"http": { "socketio": {
"origins": ["*:*"] "serveClient": false,
"path": "/ssh/socket.io",
"origins": ["localhost:2222"],
}, },
"user": { "user": {
"name": null, "name": null,
@ -27,7 +29,8 @@
"cursorBlink": true, "cursorBlink": true,
"scrollback": 10000, "scrollback": 10000,
"tabStopWidth": 8, "tabStopWidth": 8,
"bellStyle": "sound" "bellStyle": "sound",
"fontSize": 14
}, },
"header": { "header": {
"text": null, "text": null,

View file

@ -5,7 +5,9 @@
* *
* WebSSH2 - Web to SSH2 gateway * WebSSH2 - Web to SSH2 gateway
* Bill Church - https://github.com/billchurch/WebSSH2 - May 2017 * Bill Church - https://github.com/billchurch/WebSSH2 - May 2017
* See LICENSE file
* *
* test change
*/ */
const { config } = require('./server/app'); const { config } = require('./server/app');

17
app/jsconfig.json Normal file
View file

@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES2020",
"jsx": "preserve",
"strictFunctionTypes": true
},
"exclude": [
"node_modules",
"**/node_modules/*"
],
"include": [
"server/*.js",
"index.js"
]
}

14022
app/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "webssh2", "name": "webssh2",
"version": "0.4.6", "version": "0.6.0-pre-1",
"ignore": [ "ignore": [
".gitignore" ".gitignore"
], ],
@ -34,16 +34,16 @@
"dependencies": { "dependencies": {
"basic-auth": "~2.0.1", "basic-auth": "~2.0.1",
"cidr-matcher": "^2.1.1", "cidr-matcher": "^2.1.1",
"colors": "~1.4.0", "debug": "^4.3.4",
"debug": "^4.3.2", "express": "^4.19.2",
"express": "~4.17.1", "express-session": "^1.18.0",
"express-session": "~1.17.1",
"morgan": "~1.10.0", "morgan": "~1.10.0",
"read-config-ng": "^3.0.5", "read-config-ng": "^3.0.7",
"serve-favicon": "^2.5.0", "serve-favicon": "^2.5.0",
"socket.io": "^4.2.0", "socket.io": "^4.7.5",
"ssh2": "~1.4.0", "ssh2": "^1.15.0",
"validator": "^13.7.0" "validator": "^13.11.0",
"winston": "^3.13.0"
}, },
"scripts": { "scripts": {
"start": "node index.js", "start": "node index.js",
@ -56,36 +56,34 @@
"release": "standard-version" "release": "standard-version"
}, },
"devDependencies": { "devDependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^5.15.3", "@fortawesome/free-solid-svg-icons": "^6.5.2",
"@typescript-eslint/eslint-plugin": "^4.23.0", "@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^4.23.0", "@typescript-eslint/parser": "^7.7.1",
"clean-webpack-plugin": "^3.0.0", "@xterm/addon-fit": "^0.10.0",
"copy-webpack-plugin": "^8.1.1", "@xterm/xterm": "^5.5.0",
"css-loader": "^5.2.4", "clean-webpack-plugin": "^4.0.0",
"eslint": "^7.26.0", "copy-webpack-plugin": "^12.0.2",
"eslint-config-airbnb-base": "^14.2.1", "css-loader": "^7.1.1",
"eslint-config-prettier": "^8.3.0", "eslint": "^8.56.0",
"eslint-plugin-import": "^2.22.1", "eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-prettier": "^3.4.0", "eslint-config-prettier": "^9.1.0",
"mini-css-extract-plugin": "^1.6.0", "eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"mini-css-extract-plugin": "^2.9.0",
"nodaemon": "0.0.5", "nodaemon": "0.0.5",
"prettier": "^2.3.0", "npm-check-updates": "^16.14.20",
"prettier": "^3.2.5",
"snazzy": "^9.0.0", "snazzy": "^9.0.0",
"snyk": "^1.787.0", "snyk": "^1.1290.0",
"socket.io-client": "^4.1.1", "socket.io-client": "^4.7.5",
"source-map-loader": "^2.0.1", "source-map-loader": "^5.0.0",
"standard-version": "^9.3.0", "standard-version": "^9.5.0",
"terser-webpack-plugin": "^5.1.2", "terser-webpack-plugin": "^5.3.10",
"ts-loader": "^9.1.2", "ts-loader": "^9.5.1",
"typescript": "^4.2.4", "typescript": "^5.4.5",
"webpack": "^5.37.0", "webpack": "^5.91.0",
"webpack-cli": "^4.7.0", "webpack-cli": "^5.1.4",
"webpack-merge": "^5.7.3", "webpack-merge": "^5.10.0"
"xterm": "^4.15.0",
"xterm-addon-fit": "^0.5.0"
},
"resolutions": {
"trim-newlines": "^3.0.1"
} }
} }

View file

@ -1,6 +1,6 @@
/* jshint esversion: 6, asi: true, node: true */ /* jshint esversion: 6, asi: true, node: true */
/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }], /* eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }],
no-console: ["error", { allow: ["warn", "error"] }] */ no-console: ["error", { allow: ["warn", "error", "info"] }] */
// app.js // app.js
// eslint-disable-next-line import/order // eslint-disable-next-line import/order
@ -13,152 +13,52 @@ const express = require('express');
const logger = require('morgan'); const logger = require('morgan');
const app = express(); const app = express();
const server = require('http').Server(app); const server = require('http').createServer(app);
const validator = require('validator');
const favicon = require('serve-favicon'); const favicon = require('serve-favicon');
const io = require('socket.io')(server, { const io = require('socket.io')(server, config.socketio);
serveClient: false, const session = require('express-session')(config.express);
path: '/ssh/socket.io',
origins: config.http.origins,
});
const session = require('express-session')({
secret: config.session.secret,
name: config.session.name,
resave: true,
saveUninitialized: false,
unset: 'destroy',
});
const appSocket = require('./socket');
const expressOptions = require('./expressOptions');
const myutil = require('./util');
myutil.setDefaultCredentials( const appSocket = require('./socket');
config.user.name, const { setDefaultCredentials, basicAuth } = require('./util');
config.user.password, const { webssh2debug } = require('./logging');
config.user.privatekey, const { reauth, connect, notfound, handleErrors } = require('./routes');
config.user.overridebasic
); setDefaultCredentials(config.user);
// safe shutdown // safe shutdown
let remainingSeconds = config.safeShutdownDuration;
let shutdownMode = false; let shutdownMode = false;
let shutdownInterval = 0; let shutdownInterval;
let connectionCount = 0; let connectionCount = 0;
// eslint-disable-next-line consistent-return // eslint-disable-next-line consistent-return
function safeShutdownGuard(req, res, next) { function safeShutdownGuard(req, res, next) {
if (shutdownMode) { if (!shutdownMode) return next();
res.status(503).end('Service unavailable: Server shutting down'); res.status(503).end('Service unavailable: Server shutting down');
} else {
return next();
}
} }
// clean stop
function stopApp(reason) {
shutdownMode = false;
// eslint-disable-next-line no-console
if (reason) console.log(`Stopping: ${reason}`);
if (shutdownInterval) clearInterval(shutdownInterval);
io.close();
server.close();
}
module.exports = { server, config };
// express // express
app.use(safeShutdownGuard); app.use(safeShutdownGuard);
app.use(session); app.use(session);
app.use(myutil.basicAuth);
if (config.accesslog) app.use(logger('common')); if (config.accesslog) app.use(logger('common'));
app.disable('x-powered-by'); app.disable('x-powered-by');
// static files
app.use('/ssh', express.static(publicPath, expressOptions));
// favicon from root if being pre-fetched by browser to prevent a 404
app.use(favicon(path.join(publicPath, 'favicon.ico'))); app.use(favicon(path.join(publicPath, 'favicon.ico')));
app.use(express.urlencoded({ extended: true }));
app.post('/ssh/host/:host?', connect);
app.post('/ssh', express.static(publicPath, config.express.ssh));
app.use('/ssh', express.static(publicPath, config.express.ssh));
app.use(basicAuth);
app.get('/ssh/reauth', reauth);
app.get('/ssh/host/:host?', connect);
app.use(notfound);
app.use(handleErrors);
app.get('/ssh/reauth', (req, res) => { // clean stop
const r = req.headers.referer || '/'; function stopApp(reason) {
res shutdownMode = false;
.status(401) if (reason) console.info(`Stopping: ${reason}`);
.send( clearInterval(shutdownInterval);
`<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${r}"></head><body bgcolor="#000"></body></html>` io.close();
); server.close();
}); }
// eslint-disable-next-line complexity
app.get('/ssh/host/:host?', (req, res) => {
res.sendFile(path.join(path.join(publicPath, 'client.htm')));
// capture, assign, and validate variables
req.session.ssh = {
host:
config.ssh.host ||
(validator.isIP(`${req.params.host}`) && req.params.host) ||
(validator.isFQDN(req.params.host) && req.params.host) ||
(/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.params.host) && req.params.host),
port:
(validator.isInt(`${req.query.port}`, { min: 1, max: 65535 }) && req.query.port) ||
config.ssh.port,
localAddress: config.ssh.localAddress,
localPort: config.ssh.localPort,
header: {
name: req.query.header || config.header.text,
background: req.query.headerBackground || config.header.background,
},
algorithms: config.algorithms,
keepaliveInterval: config.ssh.keepaliveInterval,
keepaliveCountMax: config.ssh.keepaliveCountMax,
allowedSubnets: config.ssh.allowedSubnets,
term:
(/^(([a-z]|[A-Z]|[0-9]|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm) && req.query.sshterm) ||
config.ssh.term,
terminal: {
cursorBlink: validator.isBoolean(`${req.query.cursorBlink}`)
? myutil.parseBool(req.query.cursorBlink)
: config.terminal.cursorBlink,
scrollback:
validator.isInt(`${req.query.scrollback}`, { min: 1, max: 200000 }) && req.query.scrollback
? req.query.scrollback
: config.terminal.scrollback,
tabStopWidth:
validator.isInt(`${req.query.tabStopWidth}`, { min: 1, max: 100 }) && req.query.tabStopWidth
? req.query.tabStopWidth
: config.terminal.tabStopWidth,
bellStyle:
req.query.bellStyle && ['sound', 'none'].indexOf(req.query.bellStyle) > -1
? req.query.bellStyle
: config.terminal.bellStyle,
},
allowreplay:
config.options.challengeButton ||
(validator.isBoolean(`${req.headers.allowreplay}`)
? myutil.parseBool(req.headers.allowreplay)
: false),
allowreauth: config.options.allowreauth || false,
mrhsession:
validator.isAlphanumeric(`${req.headers.mrhsession}`) && req.headers.mrhsession
? req.headers.mrhsession
: 'none',
serverlog: {
client: config.serverlog.client || false,
server: config.serverlog.server || false,
},
readyTimeout:
(validator.isInt(`${req.query.readyTimeout}`, { min: 1, max: 300000 }) &&
req.query.readyTimeout) ||
config.ssh.readyTimeout,
};
if (req.session.ssh.header.name) validator.escape(req.session.ssh.header.name);
if (req.session.ssh.header.background) validator.escape(req.session.ssh.header.background);
});
// express error handling
app.use((req, res) => {
res.status(404).send("Sorry, can't find that!");
});
app.use((err, req, res) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// bring up socket // bring up socket
io.on('connection', appSocket); io.on('connection', appSocket);
@ -169,38 +69,43 @@ io.use((socket, next) => {
socket.request.res ? session(socket.request, socket.request.res, next) : next(next); // eslint disable-line socket.request.res ? session(socket.request, socket.request.res, next) : next(next); // eslint disable-line
}); });
io.on('connection', (socket) => { function countdownTimer() {
connectionCount += 1; if (!shutdownMode) clearInterval(shutdownInterval);
remainingSeconds -= 1;
if (remainingSeconds <= 0) {
stopApp('Countdown is over');
} else io.emit('shutdownCountdownUpdate', remainingSeconds);
}
const signals = ['SIGTERM', 'SIGINT'];
signals.forEach((signal) =>
process.on(signal, () => {
if (shutdownMode) stopApp('Safe shutdown aborted, force quitting');
if (!connectionCount > 0) stopApp('All connections ended');
shutdownMode = true;
console.error(
`\r\n${connectionCount} client(s) are still connected.\r\nStarting a ${remainingSeconds} seconds countdown.\r\nPress Ctrl+C again to force quit`
);
if (!shutdownInterval) shutdownInterval = setInterval(countdownTimer, 1000);
})
);
module.exports = { server, config };
const onConnection = (socket) => {
connectionCount += 1;
socket.on('disconnect', () => { socket.on('disconnect', () => {
connectionCount -= 1; connectionCount -= 1;
if (connectionCount <= 0 && shutdownMode) { if (connectionCount <= 0 && shutdownMode) {
stopApp('All clients disconnected'); stopApp('All clients disconnected');
} }
}); });
}); socket.on('geometry', (cols, rows) => {
// TODO need to rework how we pass settings to ssh2, this is less than ideal
socket.request.session.ssh.cols = cols;
socket.request.session.ssh.rows = rows;
webssh2debug(socket, `SOCKET GEOMETRY: termCols = ${cols}, termRows = ${rows}`);
});
};
const signals = ['SIGTERM', 'SIGINT']; io.on('connection', onConnection);
signals.forEach((signal) =>
process.on(signal, () => {
if (shutdownMode) stopApp('Safe shutdown aborted, force quitting');
else if (connectionCount > 0) {
let remainingSeconds = config.safeShutdownDuration;
shutdownMode = true;
const message =
connectionCount === 1 ? ' client is still connected' : ' clients are still connected';
console.error(connectionCount + message);
console.error(`Starting a ${remainingSeconds} seconds countdown`);
console.error('Press Ctrl+C again to force quit');
shutdownInterval = setInterval(() => {
remainingSeconds -= 1;
if (remainingSeconds <= 0) {
stopApp('Countdown is over');
} else {
io.sockets.emit('shutdownCountdownUpdate', remainingSeconds);
}
}, 1000);
} else stopApp();
})
);

View file

@ -1,20 +1,45 @@
/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }], /* eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }],
no-console: ["error", { allow: ["warn", "error"] }] */ no-console: ["error", { allow: ["warn", "error", "info"] }] */
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const debugWebSSH2 = require('debug')('WebSSH2');
const crypto = require('crypto');
const util = require('util');
const readconfig = require('read-config-ng');
const nodeRoot = path.dirname(require.main.filename); const nodeRoot = path.dirname(require.main.filename);
const configPath = path.join(nodeRoot, 'config.json'); const configPath = path.join(nodeRoot, 'config.json');
// sane defaults if config.json or parts are missing let myConfig;
let config = { // establish defaults
const configDefault = {
listen: { listen: {
ip: '0.0.0.0', ip: '0.0.0.0',
port: 2222, port: 2222,
}, },
http: { socketio: {
serveClient: false,
path: '/ssh/socket.io',
origins: ['localhost:2222'], origins: ['localhost:2222'],
}, },
express: {
secret: crypto.randomBytes(20).toString('hex'),
name: 'WebSSH2',
resave: true,
saveUninitialized: false,
unset: 'destroy',
ssh: {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1s',
redirect: false,
setHeaders(res) {
res.set('x-timestamp', Date.now());
},
},
},
user: { user: {
name: null, name: null,
password: null, password: null,
@ -40,10 +65,6 @@ let config = {
text: null, text: null,
background: 'green', background: 'green',
}, },
session: {
name: 'WebSSH2',
secret: 'mysecret',
},
options: { options: {
challengeButton: true, challengeButton: true,
allowreauth: true, allowreauth: true,
@ -80,23 +101,36 @@ let config = {
// test if config.json exists, if not provide error message but try to run anyway // test if config.json exists, if not provide error message but try to run anyway
try { try {
if (fs.existsSync(configPath)) { if (!fs.existsSync(configPath)) {
// eslint-disable-next-line no-console
console.info(`WebSSH2 service reading config from: ${configPath}`);
// eslint-disable-next-line global-require
config = require('read-config-ng')(configPath);
} else {
console.error( console.error(
`\n\nERROR: Missing config.json for WebSSH2. Current config: ${JSON.stringify(config)}` `\n\nERROR: Missing config.json for WebSSH2. Current config: ${util.inspect(myConfig)}`
); );
console.error('\n See config.json.sample for details\n\n'); console.error('\n See config.json.sample for details\n\n');
} }
console.info(`WebSSH2 service reading config from: ${configPath}`);
const configFile = readconfig(configPath, { override: true });
// myConfig = merger.mergeObjects([configDefault, configFile]);
myConfig = { ...configDefault, ...configFile };
debugWebSSH2(`\nCurrent config: ${util.inspect(myConfig)}`);
} catch (err) { } catch (err) {
myConfig = configDefault;
console.error( console.error(
`\n\nERROR: Missing config.json for WebSSH2. Current config: ${JSON.stringify(config)}` `\n\nERROR: Missing config.json for WebSSH2. Current config: ${util.inspect(myConfig)}`
); );
console.error('\n See config.json.sample for details\n\n'); console.error('\n See config.json.sample for details\n\n');
console.error(`ERROR:\n\n ${err}`); console.error(`ERROR:\n\n ${err}`);
} }
const config = myConfig;
if (process.env.LISTEN) config.listen.ip = process.env.LISTEN;
if (process.env.PORT) config.listen.port = process.env.PORT;
if (process.env.SOCKETIO_ORIGINS) config.socketio.origins = process.env.SOCKETIO_ORIGINS;
if (process.env.SOCKETIO_PATH) config.socketio.path = process.env.SOCKETIO_PATH;
if (process.env.SOCKETIO_SERVECLIENT)
config.socketio.serveClient = process.env.SOCKETIO_SERVECLIENT;
module.exports = config; module.exports = config;

View file

@ -1,11 +0,0 @@
module.exports = {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1s',
redirect: false,
setHeaders(res) {
res.set('x-timestamp', Date.now());
},
};

36
app/server/form.html Normal file
View file

@ -0,0 +1,36 @@
<head><title>Post Test</title></head>
<html>
<body>
<h1>Credentials over HTTP POST test</h1>
<p>This is a test to demonstrate sending credentials over POST instead of requiring HTTP Basic. If you use this, be sure to secure the app/site with HTTPS!</p>
<form method="POST" action="http://localhost:2222/ssh/host/192.168.0.1">
<p>
<label for="username">Username</label>
<input name="username">
</p>
<label for="userpassword">Password</label>
<input name="userpassword" type="password">
</p>
<p>
<label for="header">Header text</label>
<input name="header" value="This is a test">
<p>
<label for="headerBackground">Header Background Color</label>
<input name="headerBackground" value="red">
</p>
<fieldset>
<legend>Cursor Blink:</legend>
<div>
<input type="radio" id="false" name="cursorBlink" value="false"
checked>
<label for="false">False</label>
</div>
<div>
<input type="radio" id="true" name="cursorBlink" value="true">
<label for="true">True</label>
</div>
</fieldset>
<button>Login</button>
</form>
</body>
</html>

47
app/server/logging.js Normal file
View file

@ -0,0 +1,47 @@
/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true, "allowTernary": true }],
no-console: ["error", { allow: ["warn", "error", "info"] }] */
/* jshint esversion: 6, asi: true, node: true */
// logging.js
// private
const debug = require('debug');
const util = require('util');
/**
* generate consistent prefix for log messages
* with epress session id and socket session id
* @param {object} socket Socket information
*/
function prefix(socket) {
return `(${socket.request.sessionID}/${socket.id})`;
}
// public
function webssh2debug(socket, msg) {
debug('WebSSH2')(`${prefix(socket)} ${msg}`);
}
/**
* audit log to console
* @param {object} socket Socket information
* @param {object} msg log message
*/
function auditLog(socket, msg) {
console.info(`WebSSH2 ${prefix(socket)} AUDIT: ${msg}`);
}
/**
* logs error to socket client (if connected)
* and console.
* @param {object} socket Socket information
* @param {string} myFunc Function calling this function
* @param {object} err error object or error message
*/
function logError(socket, myFunc, err) {
console.error(`WebSSH2 ${prefix(socket)} ERROR: ${myFunc}: ${err}`);
webssh2debug(socket, `logError: ${myFunc}: ${util.inspect(err)}`);
if (!socket.request.session) return;
socket.emit('ssherror', `SSH ${myFunc}: ${err}`);
}
module.exports = { logError, auditLog, webssh2debug };

203
app/server/routes.js Normal file
View file

@ -0,0 +1,203 @@
/* eslint-disable no-console */
// ssh.js
const validator = require('validator');
const path = require('path');
const nodeRoot = path.dirname(require.main.filename);
const publicPath = path.join(nodeRoot, 'client', 'public');
const { parseBool } = require('./util');
const config = require('./config');
exports.reauth = function reauth(req, res) {
let { referer } = req.headers;
if (!validator.isURL(referer, { host_whitelist: ['localhost'] })) {
console.error(
`WebSSH2 (${req.sessionID}) ERROR: Referrer '${referer}' for '/reauth' invalid. Setting to '/' which will probably fail.`
);
referer = '/';
}
res
.status(401)
.send(
`<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=${referer}"></head><body bgcolor="#000"></body></html>`
);
};
exports.connect = function connect(req, res) {
res.sendFile(path.join(path.join(publicPath, 'client.htm')));
let { host, port } = config.ssh;
let { text: header, background: headerBackground } = config.header;
let { term: sshterm, readyTimeout } = config.ssh;
let {
cursorBlink,
scrollback,
tabStopWidth,
bellStyle,
fontSize,
fontFamily,
letterSpacing,
lineHeight,
} = config.terminal;
// capture, assign, and validate variables
if (req.params?.host) {
if (
validator.isIP(`${req.params.host}`) ||
validator.isFQDN(req.params.host) ||
/^(([a-z]|[A-Z]|\d|[!^(){}\-_~])+)?\w$/.test(req.params.host)
) {
host = req.params.host;
}
}
if (req.method === 'POST' && req.body.username && req.body.userpassword) {
req.session.username = req.body.username;
req.session.userpassword = req.body.userpassword;
if (req.body.port && validator.isInt(`${req.body.port}`, { min: 1, max: 65535 }))
port = req.body.port;
if (req.body.header) header = req.body.header;
if (req.body.headerBackground) {
headerBackground = req.body.headerBackground;
console.log(`background: ${req.body.headerBackground}`);
}
if (req.body.sshterm && /^(([a-z]|[A-Z]|\d|[!^(){}\-_~])+)?\w$/.test(req.body.sshterm))
sshterm = req.body.sshterm;
if (req.body.cursorBlink && validator.isBoolean(`${req.body.cursorBlink}`))
cursorBlink = parseBool(req.body.cursorBlink);
if (req.body.scrollback && validator.isInt(`${req.body.scrollback}`, { min: 1, max: 200000 }))
scrollback = req.body.scrollback;
if (req.body.tabStopWidth && validator.isInt(`${req.body.tabStopWidth}`, { min: 1, max: 100 }))
tabStopWidth = req.body.tabStopWidth;
if (req.body.bellStyle && ['sound', 'none'].indexOf(req.body.bellStyle) > -1)
bellStyle = req.body.bellStyle;
if (
req.body.readyTimeout &&
validator.isInt(`${req.body.readyTimeout}`, { min: 1, max: 300000 })
)
readyTimeout = req.body.readyTimeout;
if (req.body.fontSize && validator.isNumeric(`${req.body.fontSize}`))
fontSize = req.body.fontSize;
if (req.body.fontFamily) fontFamily = req.body.fontFamily;
if (req.body.letterSpacing && validator.isNumeric(`${req.body.letterSpacing}`))
letterSpacing = req.body.letterSpacing;
if (req.body.lineHeight && validator.isNumeric(`${req.body.lineHeight}`))
lineHeight = req.body.lineHeight;
}
if (req.method === 'GET') {
if (req.query?.port && validator.isInt(`${req.query.port}`, { min: 1, max: 65535 }))
port = req.query.port;
if (req.query?.header) header = req.query.header;
if (req.query?.headerBackground) headerBackground = req.query.headerBackground;
if (req.query?.sshterm && /^(([a-z]|[A-Z]|\d|[!^(){}\-_~])+)?\w$/.test(req.query.sshterm))
sshterm = req.query.sshterm;
if (req.query?.cursorBlink && validator.isBoolean(`${req.query.cursorBlink}`))
cursorBlink = parseBool(req.query.cursorBlink);
if (
req.query?.scrollback &&
validator.isInt(`${req.query.scrollback}`, { min: 1, max: 200000 })
)
scrollback = req.query.scrollback;
if (
req.query?.tabStopWidth &&
validator.isInt(`${req.query.tabStopWidth}`, { min: 1, max: 100 })
)
tabStopWidth = req.query.tabStopWidth;
if (req.query?.bellStyle && ['sound', 'none'].indexOf(req.query.bellStyle) > -1)
bellStyle = req.query.bellStyle;
if (
req.query?.readyTimeout &&
validator.isInt(`${req.query.readyTimeout}`, { min: 1, max: 300000 })
)
readyTimeout = req.query.readyTimeout;
if (req.query?.fontSize && validator.isNumeric(`${req.query.fontSize}`))
fontSize = req.query.fontSize;
if (req.query?.fontFamily) fontFamily = req.query.fontFamily;
if (req.query?.lineHeight && validator.isNumeric(`${req.query.lineHeight}`))
lineHeight = req.query.lineHeight;
if (req.query?.letterSpacing && validator.isNumeric(`${req.query.letterSpacing}`))
letterSpacing = req.query.letterSpacing;
}
req.session.ssh = {
host,
port,
localAddress: config.ssh.localAddress,
localPort: config.ssh.localPort,
header: {
name: header,
background: headerBackground,
},
algorithms: config.algorithms,
keepaliveInterval: config.ssh.keepaliveInterval,
keepaliveCountMax: config.ssh.keepaliveCountMax,
allowedSubnets: config.ssh.allowedSubnets,
term: sshterm,
terminal: {
cursorBlink,
scrollback,
tabStopWidth,
bellStyle,
fontSize,
fontFamily,
letterSpacing,
lineHeight,
},
cols: null,
rows: null,
allowreplay:
config.options.challengeButton ||
(validator.isBoolean(`${req.headers.allowreplay}`)
? parseBool(req.headers.allowreplay)
: false),
allowreauth: config.options.allowreauth || false,
mrhsession:
validator.isAlphanumeric(`${req.headers.mrhsession}`) && req.headers.mrhsession
? req.headers.mrhsession
: 'none',
serverlog: {
client: config.serverlog.client || false,
server: config.serverlog.server || false,
},
readyTimeout,
};
if (req.session.ssh.header.name) validator.escape(req.session.ssh.header.name);
if (req.session.ssh.header.background) validator.escape(req.session.ssh.header.background);
};
exports.notfound = function notfound(_req, res) {
res.status(404).send("Sorry, can't find that!");
};
exports.handleErrors = function handleErrors(err, _req, res) {
console.error(err.stack);
res.status(500).send('Something broke!');
};

View file

@ -6,84 +6,50 @@
// private // private
const debug = require('debug'); const debug = require('debug');
const debugWebSSH2 = require('debug')('WebSSH2');
const SSH = require('ssh2').Client; const SSH = require('ssh2').Client;
const CIDRMatcher = require('cidr-matcher'); const CIDRMatcher = require('cidr-matcher');
const validator = require('validator'); const validator = require('validator');
const dnsPromises = require('dns').promises; const dnsPromises = require('dns').promises;
const util = require('util');
const { webssh2debug, auditLog, logError } = require('./logging');
// var fs = require('fs') /**
// var hostkeys = JSON.parse(fs.readFileSync('./hostkeyhashes.json', 'utf8')) * parse conn errors
let termCols; * @param {object} socket Socket object
let termRows; * @param {object} err Error object
// public
module.exports = function appSocket(socket) {
async function setupConnection() {
// if websocket connection arrives without an express session, kill it
if (!socket.request.session) {
socket.emit('401 UNAUTHORIZED');
debugWebSSH2('SOCKET: No Express Session / REJECTED');
socket.disconnect(true);
return;
}
/**
* Error handling for various events. Outputs error to client, logs to
* server, destroys session and disconnects socket.
* @param {string} myFunc Function calling this function
* @param {object} err error object or error message
*/ */
// eslint-disable-next-line complexity function connError(socket, err) {
function SSHerror(myFunc, err) { let msg = util.inspect(err);
let theError; const { session } = socket.request;
if (socket.request.session) { if (err?.level === 'client-authentication') {
// we just want the first error of the session to pass to the client msg = `Authentication failure user=${session.username} from=${socket.handshake.address}`;
const firstError = socket.request.session.error || (err ? err.message : undefined); socket.emit('allowreauth', session.ssh.allowreauth);
theError = firstError ? `: ${firstError}` : '';
// log unsuccessful login attempt
if (err && err.level === 'client-authentication') {
console.error(
`WebSSH2 ${'error: Authentication failure'.red.bold} user=${
socket.request.session.username.yellow.bold.underline
} from=${socket.handshake.address.yellow.bold.underline}`
);
socket.emit('allowreauth', socket.request.session.ssh.allowreauth);
socket.emit('reauth'); socket.emit('reauth');
} else {
// eslint-disable-next-line no-console
console.log(
`WebSSH2 Logout: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} sessionID=${socket.request.sessionID}/${socket.id} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`
);
if (err) {
theError = err ? `: ${err.message}` : '';
console.error(`WebSSH2 error${theError}`);
} }
if (err?.code === 'ENOTFOUND') {
msg = `Host not found: ${err.hostname}`;
} }
socket.emit('ssherror', `SSH ${myFunc}${theError}`); if (err?.level === 'client-timeout') {
socket.request.session.destroy(); msg = `Connection Timeout: ${session.ssh.host}`;
socket.disconnect(true);
} else {
theError = err ? `: ${err.message}` : '';
socket.disconnect(true);
} }
debugWebSSH2(`SSHerror ${myFunc}${theError}`); logError(socket, 'CONN ERROR', msg);
} }
// If configured, check that requsted host is in a permitted subnet
if ( /**
(((socket.request.session || {}).ssh || {}).allowedSubnets || {}).length && * check ssh host is in allowed subnet
socket.request.session.ssh.allowedSubnets.length > 0 * @param {object} socket Socket information
) { */
async function checkSubnet(socket) {
let ipaddress = socket.request.session.ssh.host; let ipaddress = socket.request.session.ssh.host;
if (!validator.isIP(`${ipaddress}`)) { if (!validator.isIP(`${ipaddress}`)) {
try { try {
const result = await dnsPromises.lookup(socket.request.session.ssh.host); const result = await dnsPromises.lookup(socket.request.session.ssh.host);
ipaddress = result.address; ipaddress = result.address;
} catch (err) { } catch (err) {
console.error( logError(
`WebSSH2 ${`error: ${err.code} ${err.hostname}`.red.bold} user=${ socket,
socket.request.session.username.yellow.bold.underline 'CHECK SUBNET',
} from=${socket.handshake.address.yellow.bold.underline}` `${err.code}: ${err.hostname} user=${socket.request.session.username} from=${socket.handshake.address}`
); );
socket.emit('ssherror', '404 HOST IP NOT FOUND'); socket.emit('ssherror', '404 HOST IP NOT FOUND');
socket.disconnect(true); socket.disconnect(true);
@ -93,36 +59,56 @@ module.exports = function appSocket(socket) {
const matcher = new CIDRMatcher(socket.request.session.ssh.allowedSubnets); const matcher = new CIDRMatcher(socket.request.session.ssh.allowedSubnets);
if (!matcher.contains(ipaddress)) { if (!matcher.contains(ipaddress)) {
console.error( logError(
`WebSSH2 ${ socket,
`error: Requested host ${ipaddress} outside configured subnets / REJECTED`.red.bold 'CHECK SUBNET',
} user=${socket.request.session.username.yellow.bold.underline} from=${ `Requested host ${ipaddress} outside configured subnets / REJECTED user=${socket.request.session.username} from=${socket.handshake.address}`
socket.handshake.address.yellow.bold.underline
}`
); );
socket.emit('ssherror', '401 UNAUTHORIZED'); socket.emit('ssherror', '401 UNAUTHORIZED');
socket.disconnect(true); socket.disconnect(true);
}
}
// public
module.exports = function appSocket(socket) {
let login = false;
socket.once('disconnecting', (reason) => {
webssh2debug(socket, `SOCKET DISCONNECTING: ${reason}`);
if (login === true) {
auditLog(
socket,
`LOGOUT user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
);
login = false;
}
});
async function setupConnection() {
// if websocket connection arrives without an express session, kill it
if (!socket.request.session) {
socket.emit('401 UNAUTHORIZED');
webssh2debug(socket, 'SOCKET: No Express Session / REJECTED');
socket.disconnect(true);
return; return;
} }
// If configured, check that requsted host is in a permitted subnet
if (socket.request.session?.ssh?.allowedSubnets?.length > 0) {
checkSubnet(socket);
} }
const conn = new SSH(); const conn = new SSH();
socket.on('geometry', (cols, rows) => {
termCols = cols;
termRows = rows;
});
conn.on('banner', (data) => { conn.on('banner', (data) => {
// need to convert to cr/lf for proper formatting // need to convert to cr/lf for proper formatting
socket.emit('data', data.replace(/\r?\n/g, '\r\n').toString('utf-8')); socket.emit('data', data.replace(/\r?\n/g, '\r\n').toString('utf-8'));
}); });
conn.on('ready', () => { conn.on('handshake', () => {
debugWebSSH2( socket.emit('setTerminalOpts', socket.request.session.ssh.terminal);
`WebSSH2 Login: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} sessionID=${socket.request.sessionID}/${socket.id} mrhsession=${socket.request.session.ssh.mrhsession} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`
);
socket.emit('menu'); socket.emit('menu');
socket.emit('allowreauth', socket.request.session.ssh.allowreauth); socket.emit('allowreauth', socket.request.session.ssh.allowreauth);
socket.emit('setTerminalOpts', socket.request.session.ssh.terminal);
socket.emit('title', `ssh://${socket.request.session.ssh.host}`); socket.emit('title', `ssh://${socket.request.session.ssh.host}`);
if (socket.request.session.ssh.header.background) if (socket.request.session.ssh.header.background)
socket.emit('headerBackground', socket.request.session.ssh.header.background); socket.emit('headerBackground', socket.request.session.ssh.header.background);
@ -132,86 +118,99 @@ module.exports = function appSocket(socket) {
'footer', 'footer',
`ssh://${socket.request.session.username}@${socket.request.session.ssh.host}:${socket.request.session.ssh.port}` `ssh://${socket.request.session.username}@${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
); );
});
conn.on('ready', () => {
webssh2debug(
socket,
`CONN READY: LOGIN: user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host} port=${socket.request.session.ssh.port} allowreplay=${socket.request.session.ssh.allowreplay} term=${socket.request.session.ssh.term}`
);
auditLog(
socket,
`LOGIN user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
);
login = true;
socket.emit('status', 'SSH CONNECTION ESTABLISHED'); socket.emit('status', 'SSH CONNECTION ESTABLISHED');
socket.emit('statusBackground', 'green'); socket.emit('statusBackground', 'green');
socket.emit('allowreplay', socket.request.session.ssh.allowreplay); socket.emit('allowreplay', socket.request.session.ssh.allowreplay);
conn.shell( const { term, cols, rows } = socket.request.session.ssh;
{ conn.shell({ term, cols, rows }, (err, stream) => {
term: socket.request.session.ssh.term,
cols: termCols,
rows: termRows,
},
(err, stream) => {
if (err) { if (err) {
SSHerror(`EXEC ERROR${err}`); logError(socket, `EXEC ERROR`, err);
conn.end(); conn.end();
socket.disconnect(true);
return; return;
} }
socket.on('data', (data) => { socket.once('disconnect', (reason) => {
stream.write(data); webssh2debug(socket, `CLIENT SOCKET DISCONNECT: ${util.inspect(reason)}`);
conn.end();
socket.request.session.destroy();
});
socket.on('error', (errMsg) => {
webssh2debug(socket, `SOCKET ERROR: ${errMsg}`);
logError(socket, 'SOCKET ERROR', errMsg);
conn.end();
socket.disconnect(true);
}); });
socket.on('control', (controlData) => { socket.on('control', (controlData) => {
switch (controlData) { if (controlData === 'replayCredentials' && socket.request.session.ssh.allowreplay) {
case 'replayCredentials':
if (socket.request.session.ssh.allowreplay) {
stream.write(`${socket.request.session.userpassword}\n`); stream.write(`${socket.request.session.userpassword}\n`);
} }
/* falls through */ if (controlData === 'reauth' && socket.request.session.username && login === true) {
default: auditLog(
debugWebSSH2(`controlData: ${controlData}`); socket,
`LOGOUT user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
);
login = false;
conn.end();
socket.disconnect(true);
} }
webssh2debug(socket, `SOCKET CONTROL: ${controlData}`);
}); });
socket.on('resize', (data) => { socket.on('resize', (data) => {
stream.setWindow(data.rows, data.cols); stream.setWindow(data.rows, data.cols);
webssh2debug(socket, `SOCKET RESIZE: ${JSON.stringify([data.rows, data.cols])}`);
}); });
socket.on('disconnecting', (reason) => { socket.on('data', (data) => {
debugWebSSH2(`SOCKET DISCONNECTING: ${reason}`); stream.write(data);
}); });
socket.on('disconnect', (reason) => {
debugWebSSH2(`SOCKET DISCONNECT: ${reason}`);
const errMsg = { message: reason };
SSHerror('CLIENT SOCKET DISCONNECT', errMsg);
conn.end();
// socket.request.session.destroy()
});
socket.on('error', (errMsg) => {
SSHerror('SOCKET ERROR', errMsg);
conn.end();
});
stream.on('data', (data) => { stream.on('data', (data) => {
socket.emit('data', data.toString('utf-8')); socket.emit('data', data.toString('utf-8'));
}); });
stream.on('close', (code, signal) => { stream.on('close', (code, signal) => {
const errMsg = { webssh2debug(socket, `STREAM CLOSE: ${util.inspect([code, signal])}`);
message: if (socket.request.session?.username && login === true) {
code || signal auditLog(
? (code ? `CODE: ${code}` : '') + socket,
(code && signal ? ' ' : '') + `LOGOUT user=${socket.request.session.username} from=${socket.handshake.address} host=${socket.request.session.ssh.host}:${socket.request.session.ssh.port}`
(signal ? `SIGNAL: ${signal}` : '') );
: undefined, login = false;
}; }
SSHerror('STREAM CLOSE', errMsg); if (code !== 0 && typeof code !== 'undefined')
logError(socket, 'STREAM CLOSE', util.inspect({ message: [code, signal] }));
socket.disconnect(true);
conn.end(); conn.end();
}); });
stream.stderr.on('data', (data) => { stream.stderr.on('data', (data) => {
console.error(`STDERR: ${data}`); console.error(`STDERR: ${data}`);
}); });
} });
);
}); });
conn.on('end', (err) => { conn.on('end', (err) => {
SSHerror('CONN END BY HOST', err); if (err) logError(socket, 'CONN END BY HOST', err);
webssh2debug(socket, 'CONN END BY HOST');
socket.disconnect(true);
}); });
conn.on('close', (err) => { conn.on('close', (err) => {
SSHerror('CONN CLOSE', err); if (err) logError(socket, 'CONN CLOSE', err);
webssh2debug(socket, 'CONN CLOSE');
socket.disconnect(true);
}); });
conn.on('error', (err) => { conn.on('error', (err) => connError(socket, err));
SSHerror('CONN ERROR', err);
}); conn.on('keyboard-interactive', (_name, _instructions, _instructionsLang, _prompts, finish) => {
conn.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => { webssh2debug(socket, 'CONN keyboard-interactive');
debugWebSSH2("conn.on('keyboard-interactive')");
finish([socket.request.session.userpassword]); finish([socket.request.session.userpassword]);
}); });
if ( if (
@ -220,24 +219,16 @@ module.exports = function appSocket(socket) {
socket.request.session.ssh socket.request.session.ssh
) { ) {
// console.log('hostkeys: ' + hostkeys[0].[0]) // console.log('hostkeys: ' + hostkeys[0].[0])
conn.connect({ const { ssh } = socket.request.session;
host: socket.request.session.ssh.host, ssh.username = socket.request.session.username;
port: socket.request.session.ssh.port, ssh.password = socket.request.session.userpassword;
localAddress: socket.request.session.ssh.localAddress, ssh.tryKeyboard = true;
localPort: socket.request.session.ssh.localPort, ssh.debug = debug('ssh2');
username: socket.request.session.username, conn.connect(ssh);
password: socket.request.session.userpassword,
privateKey: socket.request.session.privatekey,
tryKeyboard: true,
algorithms: socket.request.session.ssh.algorithms,
readyTimeout: socket.request.session.ssh.readyTimeout,
keepaliveInterval: socket.request.session.ssh.keepaliveInterval,
keepaliveCountMax: socket.request.session.ssh.keepaliveCountMax,
debug: debug('ssh2'),
});
} else { } else {
debugWebSSH2( webssh2debug(
`Attempt to connect without session.username/password or session varialbles defined, potentially previously abandoned client session. disconnecting websocket client.\r\nHandshake information: \r\n ${JSON.stringify( socket,
`CONN CONNECT: Attempt to connect without session.username/password or session varialbles defined, potentially previously abandoned client session. disconnecting websocket client.\r\nHandshake information: \r\n ${util.inspect(
socket.handshake socket.handshake
)}` )}`
); );

View file

@ -2,41 +2,34 @@
// util.js // util.js
// private // private
require('colors'); // allow for color property extensions in log messages
const debug = require('debug')('WebSSH2'); const debug = require('debug')('WebSSH2');
const Auth = require('basic-auth'); const Auth = require('basic-auth');
const defaultCredentials = { username: null, password: null, privatekey: null }; let defaultCredentials = { username: null, password: null, privatekey: null };
exports.setDefaultCredentials = function setDefaultCredentials( exports.setDefaultCredentials = function setDefaultCredentials({
username, name: username,
password, password,
privatekey, privatekey,
overridebasic overridebasic,
) { }) {
defaultCredentials.username = username; defaultCredentials = { username, password, privatekey, overridebasic };
defaultCredentials.password = password;
defaultCredentials.privatekey = privatekey;
defaultCredentials.overridebasic = overridebasic;
}; };
exports.basicAuth = function basicAuth(req, res, next) { exports.basicAuth = function basicAuth(req, res, next) {
const myAuth = Auth(req); const myAuth = Auth(req);
// If Authorize: Basic header exists and the password isn't blank // If Authorize: Basic header exists and the password isn't blank
// AND config.user.overridebasic is false, extract basic credentials // AND config.user.overridebasic is false, extract basic credentials
// from client // from client]
if (myAuth && myAuth.pass !== '' && !defaultCredentials.overridebasic) { const { username, password, privatekey, overridebasic } = defaultCredentials;
if (myAuth && myAuth.pass !== '' && !overridebasic) {
req.session.username = myAuth.name; req.session.username = myAuth.name;
req.session.userpassword = myAuth.pass; req.session.userpassword = myAuth.pass;
debug( debug(`myAuth.name: ${myAuth.name} and password ${myAuth.pass ? 'exists' : 'is blank'}`);
`myAuth.name: ${myAuth.name.yellow.bold.underline} and password ${
myAuth.pass ? 'exists'.yellow.bold.underline : 'is blank'.underline.red.bold
}`
);
} else { } else {
req.session.username = defaultCredentials.username; req.session.username = username;
req.session.userpassword = defaultCredentials.password; req.session.userpassword = password;
req.session.privatekey = defaultCredentials.privatekey; req.session.privatekey = privatekey;
} }
if (!req.session.userpassword && !req.session.privatekey) { if (!req.session.userpassword && !req.session.privatekey) {
res.statusCode = 401; res.statusCode = 401;

Binary file not shown.

View file

@ -1 +0,0 @@
b512ae8f04eba0eab29e026542fab1063b1bb4ae6db04e3613a8939260fe031c Build/Release/BIG-IP-ILX-WebSSH2-0.2.9.tgz

BIN
bun.lockb Executable file

Binary file not shown.

6
package.json Normal file
View file

@ -0,0 +1,6 @@
{
"dependencies": {},
"devDependencies": {
"bun-types": "^1.0.1"
}
}

View file

@ -0,0 +1,14 @@
{
"changelogPath": "CHANGELOG.md",
"include-v-in-tags": false,
"prerelease": true,
"packages": {
"app": {
"releaseType": "node",
"draft": false,
"bumpMinorPreMajor": false,
"bumpPatchForMinorPreMajor": false,
"versioning": "default"
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB