constants.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. 'use strict';
  2. const crypto = require('crypto');
  3. let cpuInfo;
  4. try {
  5. cpuInfo = require('cpu-features')();
  6. } catch {}
  7. const { bindingAvailable } = require('./crypto.js');
  8. const eddsaSupported = (() => {
  9. if (typeof crypto.sign === 'function'
  10. && typeof crypto.verify === 'function') {
  11. const key =
  12. '-----BEGIN PRIVATE KEY-----\r\nMC4CAQAwBQYDK2VwBCIEIHKj+sVa9WcD'
  13. + '/q2DJUJaf43Kptc8xYuUQA4bOFj9vC8T\r\n-----END PRIVATE KEY-----';
  14. const data = Buffer.from('a');
  15. let sig;
  16. let verified;
  17. try {
  18. sig = crypto.sign(null, data, key);
  19. verified = crypto.verify(null, data, key, sig);
  20. } catch {}
  21. return (Buffer.isBuffer(sig) && sig.length === 64 && verified === true);
  22. }
  23. return false;
  24. })();
  25. const curve25519Supported = (typeof crypto.diffieHellman === 'function'
  26. && typeof crypto.generateKeyPairSync === 'function'
  27. && typeof crypto.createPublicKey === 'function');
  28. const DEFAULT_KEX = [
  29. // https://tools.ietf.org/html/rfc5656#section-10.1
  30. 'ecdh-sha2-nistp256',
  31. 'ecdh-sha2-nistp384',
  32. 'ecdh-sha2-nistp521',
  33. // https://tools.ietf.org/html/rfc4419#section-4
  34. 'diffie-hellman-group-exchange-sha256',
  35. // https://tools.ietf.org/html/rfc8268
  36. 'diffie-hellman-group14-sha256',
  37. 'diffie-hellman-group15-sha512',
  38. 'diffie-hellman-group16-sha512',
  39. 'diffie-hellman-group17-sha512',
  40. 'diffie-hellman-group18-sha512',
  41. ];
  42. if (curve25519Supported) {
  43. DEFAULT_KEX.unshift('curve25519-sha256');
  44. DEFAULT_KEX.unshift('curve25519-sha256@libssh.org');
  45. }
  46. const SUPPORTED_KEX = DEFAULT_KEX.concat([
  47. // https://tools.ietf.org/html/rfc4419#section-4
  48. 'diffie-hellman-group-exchange-sha1',
  49. 'diffie-hellman-group14-sha1', // REQUIRED
  50. 'diffie-hellman-group1-sha1', // REQUIRED
  51. ]);
  52. const DEFAULT_SERVER_HOST_KEY = [
  53. 'ecdsa-sha2-nistp256',
  54. 'ecdsa-sha2-nistp384',
  55. 'ecdsa-sha2-nistp521',
  56. 'rsa-sha2-512', // RFC 8332
  57. 'rsa-sha2-256', // RFC 8332
  58. 'ssh-rsa',
  59. ];
  60. if (eddsaSupported)
  61. DEFAULT_SERVER_HOST_KEY.unshift('ssh-ed25519');
  62. const SUPPORTED_SERVER_HOST_KEY = DEFAULT_SERVER_HOST_KEY.concat([
  63. 'ssh-dss',
  64. ]);
  65. const DEFAULT_CIPHER = [
  66. // http://tools.ietf.org/html/rfc5647
  67. 'aes128-gcm',
  68. 'aes128-gcm@openssh.com',
  69. 'aes256-gcm',
  70. 'aes256-gcm@openssh.com',
  71. // http://tools.ietf.org/html/rfc4344#section-4
  72. 'aes128-ctr',
  73. 'aes192-ctr',
  74. 'aes256-ctr',
  75. ];
  76. if (cpuInfo && cpuInfo.flags && !cpuInfo.flags.aes) {
  77. // We know for sure the CPU does not support AES acceleration
  78. if (bindingAvailable)
  79. DEFAULT_CIPHER.unshift('chacha20-poly1305@openssh.com');
  80. else
  81. DEFAULT_CIPHER.push('chacha20-poly1305@openssh.com');
  82. } else if (bindingAvailable && cpuInfo && cpuInfo.arch === 'x86') {
  83. // Places chacha20-poly1305 immediately after GCM ciphers since GCM ciphers
  84. // seem to outperform it on x86, but it seems to be faster than CTR ciphers
  85. DEFAULT_CIPHER.splice(4, 0, 'chacha20-poly1305@openssh.com');
  86. } else {
  87. DEFAULT_CIPHER.push('chacha20-poly1305@openssh.com');
  88. }
  89. const SUPPORTED_CIPHER = DEFAULT_CIPHER.concat([
  90. 'aes256-cbc',
  91. 'aes192-cbc',
  92. 'aes128-cbc',
  93. 'blowfish-cbc',
  94. '3des-cbc',
  95. // http://tools.ietf.org/html/rfc4345#section-4:
  96. 'arcfour256',
  97. 'arcfour128',
  98. 'cast128-cbc',
  99. 'arcfour',
  100. ]);
  101. const DEFAULT_MAC = [
  102. 'hmac-sha2-256-etm@openssh.com',
  103. 'hmac-sha2-512-etm@openssh.com',
  104. 'hmac-sha1-etm@openssh.com',
  105. 'hmac-sha2-256',
  106. 'hmac-sha2-512',
  107. 'hmac-sha1',
  108. ];
  109. const SUPPORTED_MAC = DEFAULT_MAC.concat([
  110. 'hmac-md5',
  111. 'hmac-sha2-256-96', // first 96 bits of HMAC-SHA256
  112. 'hmac-sha2-512-96', // first 96 bits of HMAC-SHA512
  113. 'hmac-ripemd160',
  114. 'hmac-sha1-96', // first 96 bits of HMAC-SHA1
  115. 'hmac-md5-96', // first 96 bits of HMAC-MD5
  116. ]);
  117. const DEFAULT_COMPRESSION = [
  118. 'none',
  119. 'zlib@openssh.com', // ZLIB (LZ77) compression, except
  120. // compression/decompression does not start until after
  121. // successful user authentication
  122. 'zlib', // ZLIB (LZ77) compression
  123. ];
  124. const SUPPORTED_COMPRESSION = DEFAULT_COMPRESSION.concat([
  125. ]);
  126. const COMPAT = {
  127. BAD_DHGEX: 1 << 0,
  128. OLD_EXIT: 1 << 1,
  129. DYN_RPORT_BUG: 1 << 2,
  130. BUG_DHGEX_LARGE: 1 << 3,
  131. };
  132. module.exports = {
  133. MESSAGE: {
  134. // Transport layer protocol -- generic (1-19)
  135. DISCONNECT: 1,
  136. IGNORE: 2,
  137. UNIMPLEMENTED: 3,
  138. DEBUG: 4,
  139. SERVICE_REQUEST: 5,
  140. SERVICE_ACCEPT: 6,
  141. // Transport layer protocol -- algorithm negotiation (20-29)
  142. KEXINIT: 20,
  143. NEWKEYS: 21,
  144. // Transport layer protocol -- key exchange method-specific (30-49)
  145. KEXDH_INIT: 30,
  146. KEXDH_REPLY: 31,
  147. KEXDH_GEX_GROUP: 31,
  148. KEXDH_GEX_INIT: 32,
  149. KEXDH_GEX_REPLY: 33,
  150. KEXDH_GEX_REQUEST: 34,
  151. KEXECDH_INIT: 30,
  152. KEXECDH_REPLY: 31,
  153. // User auth protocol -- generic (50-59)
  154. USERAUTH_REQUEST: 50,
  155. USERAUTH_FAILURE: 51,
  156. USERAUTH_SUCCESS: 52,
  157. USERAUTH_BANNER: 53,
  158. // User auth protocol -- user auth method-specific (60-79)
  159. USERAUTH_PASSWD_CHANGEREQ: 60,
  160. USERAUTH_PK_OK: 60,
  161. USERAUTH_INFO_REQUEST: 60,
  162. USERAUTH_INFO_RESPONSE: 61,
  163. // Connection protocol -- generic (80-89)
  164. GLOBAL_REQUEST: 80,
  165. REQUEST_SUCCESS: 81,
  166. REQUEST_FAILURE: 82,
  167. // Connection protocol -- channel-related (90-127)
  168. CHANNEL_OPEN: 90,
  169. CHANNEL_OPEN_CONFIRMATION: 91,
  170. CHANNEL_OPEN_FAILURE: 92,
  171. CHANNEL_WINDOW_ADJUST: 93,
  172. CHANNEL_DATA: 94,
  173. CHANNEL_EXTENDED_DATA: 95,
  174. CHANNEL_EOF: 96,
  175. CHANNEL_CLOSE: 97,
  176. CHANNEL_REQUEST: 98,
  177. CHANNEL_SUCCESS: 99,
  178. CHANNEL_FAILURE: 100
  179. // Reserved for client protocols (128-191)
  180. // Local extensions (192-155)
  181. },
  182. DISCONNECT_REASON: {
  183. HOST_NOT_ALLOWED_TO_CONNECT: 1,
  184. PROTOCOL_ERROR: 2,
  185. KEY_EXCHANGE_FAILED: 3,
  186. RESERVED: 4,
  187. MAC_ERROR: 5,
  188. COMPRESSION_ERROR: 6,
  189. SERVICE_NOT_AVAILABLE: 7,
  190. PROTOCOL_VERSION_NOT_SUPPORTED: 8,
  191. HOST_KEY_NOT_VERIFIABLE: 9,
  192. CONNECTION_LOST: 10,
  193. BY_APPLICATION: 11,
  194. TOO_MANY_CONNECTIONS: 12,
  195. AUTH_CANCELED_BY_USER: 13,
  196. NO_MORE_AUTH_METHODS_AVAILABLE: 14,
  197. ILLEGAL_USER_NAME: 15,
  198. },
  199. DISCONNECT_REASON_STR: undefined,
  200. CHANNEL_OPEN_FAILURE: {
  201. ADMINISTRATIVELY_PROHIBITED: 1,
  202. CONNECT_FAILED: 2,
  203. UNKNOWN_CHANNEL_TYPE: 3,
  204. RESOURCE_SHORTAGE: 4
  205. },
  206. TERMINAL_MODE: {
  207. TTY_OP_END: 0, // Indicates end of options.
  208. VINTR: 1, // Interrupt character; 255 if none. Similarly for the
  209. // other characters. Not all of these characters are
  210. // supported on all systems.
  211. VQUIT: 2, // The quit character (sends SIGQUIT signal on POSIX
  212. // systems).
  213. VERASE: 3, // Erase the character to left of the cursor.
  214. VKILL: 4, // Kill the current input line.
  215. VEOF: 5, // End-of-file character (sends EOF from the
  216. // terminal).
  217. VEOL: 6, // End-of-line character in addition to carriage
  218. // return and/or linefeed.
  219. VEOL2: 7, // Additional end-of-line character.
  220. VSTART: 8, // Continues paused output (normally control-Q).
  221. VSTOP: 9, // Pauses output (normally control-S).
  222. VSUSP: 10, // Suspends the current program.
  223. VDSUSP: 11, // Another suspend character.
  224. VREPRINT: 12, // Reprints the current input line.
  225. VWERASE: 13, // Erases a word left of cursor.
  226. VLNEXT: 14, // Enter the next character typed literally, even if
  227. // it is a special character
  228. VFLUSH: 15, // Character to flush output.
  229. VSWTCH: 16, // Switch to a different shell layer.
  230. VSTATUS: 17, // Prints system status line (load, command, pid,
  231. // etc).
  232. VDISCARD: 18, // Toggles the flushing of terminal output.
  233. IGNPAR: 30, // The ignore parity flag. The parameter SHOULD be 0
  234. // if this flag is FALSE, and 1 if it is TRUE.
  235. PARMRK: 31, // Mark parity and framing errors.
  236. INPCK: 32, // Enable checking of parity errors.
  237. ISTRIP: 33, // Strip 8th bit off characters.
  238. INLCR: 34, // Map NL into CR on input.
  239. IGNCR: 35, // Ignore CR on input.
  240. ICRNL: 36, // Map CR to NL on input.
  241. IUCLC: 37, // Translate uppercase characters to lowercase.
  242. IXON: 38, // Enable output flow control.
  243. IXANY: 39, // Any char will restart after stop.
  244. IXOFF: 40, // Enable input flow control.
  245. IMAXBEL: 41, // Ring bell on input queue full.
  246. ISIG: 50, // Enable signals INTR, QUIT, [D]SUSP.
  247. ICANON: 51, // Canonicalize input lines.
  248. XCASE: 52, // Enable input and output of uppercase characters by
  249. // preceding their lowercase equivalents with "\".
  250. ECHO: 53, // Enable echoing.
  251. ECHOE: 54, // Visually erase chars.
  252. ECHOK: 55, // Kill character discards current line.
  253. ECHONL: 56, // Echo NL even if ECHO is off.
  254. NOFLSH: 57, // Don't flush after interrupt.
  255. TOSTOP: 58, // Stop background jobs from output.
  256. IEXTEN: 59, // Enable extensions.
  257. ECHOCTL: 60, // Echo control characters as ^(Char).
  258. ECHOKE: 61, // Visual erase for line kill.
  259. PENDIN: 62, // Retype pending input.
  260. OPOST: 70, // Enable output processing.
  261. OLCUC: 71, // Convert lowercase to uppercase.
  262. ONLCR: 72, // Map NL to CR-NL.
  263. OCRNL: 73, // Translate carriage return to newline (output).
  264. ONOCR: 74, // Translate newline to carriage return-newline
  265. // (output).
  266. ONLRET: 75, // Newline performs a carriage return (output).
  267. CS7: 90, // 7 bit mode.
  268. CS8: 91, // 8 bit mode.
  269. PARENB: 92, // Parity enable.
  270. PARODD: 93, // Odd parity, else even.
  271. TTY_OP_ISPEED: 128, // Specifies the input baud rate in bits per second.
  272. TTY_OP_OSPEED: 129, // Specifies the output baud rate in bits per second.
  273. },
  274. CHANNEL_EXTENDED_DATATYPE: {
  275. STDERR: 1,
  276. },
  277. SIGNALS: [
  278. 'ABRT', 'ALRM', 'FPE', 'HUP', 'ILL', 'INT', 'QUIT', 'SEGV', 'TERM', 'USR1',
  279. 'USR2', 'KILL', 'PIPE'
  280. ].reduce((cur, val) => ({ ...cur, [val]: 1 }), {}),
  281. COMPAT,
  282. COMPAT_CHECKS: [
  283. [ 'Cisco-1.25', COMPAT.BAD_DHGEX ],
  284. [ /^Cisco-1\./, COMPAT.BUG_DHGEX_LARGE ],
  285. [ /^[0-9.]+$/, COMPAT.OLD_EXIT ], // old SSH.com implementations
  286. [ /^OpenSSH_5\.\d+/, COMPAT.DYN_RPORT_BUG ],
  287. ],
  288. // KEX proposal-related
  289. DEFAULT_KEX,
  290. SUPPORTED_KEX,
  291. DEFAULT_SERVER_HOST_KEY,
  292. SUPPORTED_SERVER_HOST_KEY,
  293. DEFAULT_CIPHER,
  294. SUPPORTED_CIPHER,
  295. DEFAULT_MAC,
  296. SUPPORTED_MAC,
  297. DEFAULT_COMPRESSION,
  298. SUPPORTED_COMPRESSION,
  299. curve25519Supported,
  300. eddsaSupported,
  301. };
  302. module.exports.DISCONNECT_REASON_BY_VALUE =
  303. Array.from(Object.entries(module.exports.DISCONNECT_REASON))
  304. .reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {});