sshd.om (44187B)
1 func read_line(fd: int, buf: *byte, max: int): int { 2 var len: int; 3 var ret: int; 4 var c: byte; 5 len = 0; 6 loop { 7 if len == max { 8 return 0; 9 } 10 11 ret = read(fd, &c, 1); 12 13 if ret == -EINTR { 14 continue; 15 } 16 17 if ret == 0 { 18 return 0; 19 } 20 21 if c == '\n' as byte { 22 buf[len] = 0 as byte; 23 return len; 24 } 25 26 if c == '\r' as byte { 27 continue; 28 } 29 30 buf[len] = c; 31 len = len + 1; 32 } 33 } 34 35 func writeall(fd: int, buf: *byte, n: int): int { 36 var ret: int; 37 loop { 38 if n == 0 { 39 return 0; 40 } 41 42 ret = write(fd, buf, n); 43 if ret == -EINTR { 44 continue; 45 } 46 if ret < 0 { 47 return ret; 48 } 49 50 buf = &buf[ret]; 51 n = n - ret; 52 } 53 } 54 55 func read_fill(fd: int, buf: *byte, n: int): int { 56 var ret: int; 57 loop { 58 if n == 0 { 59 return 0; 60 } 61 62 ret = read(fd, buf, n); 63 if ret == -EINTR { 64 continue; 65 } 66 67 if ret <= 0 { 68 return -1; 69 } 70 71 buf = &buf[ret]; 72 n = n - ret; 73 } 74 } 75 76 func read_rand(buf: *byte, n: int) { 77 if getrandom(buf, n, 0) != n { 78 die("getrandom"); 79 } 80 } 81 82 struct _ssh_nonce { 83 x0: int; 84 x1: int; 85 } 86 87 func read_frame(ctx: *sshd_ctx) { 88 var len: int; 89 var padlen: int; 90 var minlen: int; 91 var align: int; 92 var maclen: int; 93 var tmp: int; 94 var _nonce: _ssh_nonce; 95 var nonce: *byte; 96 var seq: int; 97 var _mackey: _sha512_digest; 98 var mackey: *byte; 99 var _mac: _sha256_digest; 100 var mac: *byte; 101 102 nonce = (&_nonce) as *byte; 103 mackey = (&_mackey) as *byte; 104 mac = (&_mac) as *byte; 105 106 if read_fill(ctx.fd, ctx.buf, 4) != 0 { 107 die("truncated"); 108 } 109 110 if ctx.en_client_to_server { 111 nonce[0] = 0 as byte; 112 nonce[1] = 0 as byte; 113 nonce[2] = 0 as byte; 114 nonce[3] = 0 as byte; 115 nonce[4] = (ctx.seq_client_to_server >> 56) as byte; 116 nonce[5] = (ctx.seq_client_to_server >> 48) as byte; 117 nonce[6] = (ctx.seq_client_to_server >> 40) as byte; 118 nonce[7] = (ctx.seq_client_to_server >> 32) as byte; 119 nonce[8] = (ctx.seq_client_to_server >> 24) as byte; 120 nonce[9] = (ctx.seq_client_to_server >> 16) as byte; 121 nonce[10] = (ctx.seq_client_to_server >> 8) as byte; 122 nonce[11] = ctx.seq_client_to_server as byte; 123 124 seq = 0; 125 chacha20_stream((&tmp) as *byte, ctx.buf, 4, &seq, &((&ctx.ek_client_to_server) as *byte)[32], nonce); 126 127 minlen = 16; 128 align = 8; 129 maclen = 16; 130 131 len = ((&tmp) as *byte)[3] as int 132 | (((&tmp) as *byte)[2] as int << 8) 133 | (((&tmp) as *byte)[1] as int << 16) 134 | (((&tmp) as *byte)[0] as int << 24); 135 136 if len % align != 0 { 137 die("not aligned"); 138 } 139 } else { 140 minlen = 16; 141 align = 8; 142 maclen = 0; 143 144 len = ctx.buf[3] as int 145 | (ctx.buf[2] as int << 8) 146 | (ctx.buf[1] as int << 16) 147 | (ctx.buf[0] as int << 24); 148 149 if (len + 4) % align != 0 { 150 die("not aligned"); 151 } 152 } 153 154 if len > ctx.bufsz - 4 - maclen { 155 die("too long"); 156 } 157 158 if len < minlen - 4 { 159 die("too short"); 160 } 161 162 if read_fill(ctx.fd, &ctx.buf[4], len + maclen) != 0 { 163 die("truncated"); 164 } 165 166 if ctx.en_client_to_server { 167 bzero(mackey, 64); 168 seq = 0; 169 chacha20_stream(mackey, mackey, 64, &seq, (&ctx.ek_client_to_server) as *byte, nonce); 170 poly1305(mac, mackey, ctx.buf, len + 4); 171 if memcmp(mac, &ctx.buf[len + 4], 16) { 172 die("mac"); 173 } 174 memcpy(ctx.buf, (&tmp) as *byte, 4); 175 seq = 64; 176 chacha20_stream(&ctx.buf[4], &ctx.buf[4], len, &seq, (&ctx.ek_client_to_server) as *byte, nonce); 177 } 178 179 padlen = ctx.buf[4] as int; 180 181 if padlen < 4 || padlen > len - 1 { 182 die("bad padding"); 183 } 184 185 ctx.seq_client_to_server = (ctx.seq_client_to_server + 1) & (-1 >> 32); 186 ctx.frame = &ctx.buf[5]; 187 ctx.framelen = len - padlen - 1; 188 ctx.index = 0; 189 } 190 191 func write_frame(ctx: *sshd_ctx) { 192 var len: int; 193 var padlen: int; 194 var minlen: int; 195 var align: int; 196 var maclen: int; 197 var _nonce: _ssh_nonce; 198 var nonce: *byte; 199 var seq: int; 200 var _mackey: _sha512_digest; 201 var mackey: *byte; 202 203 nonce = (&_nonce) as *byte; 204 mackey = (&_mackey) as *byte; 205 206 if ctx.en_server_to_client { 207 minlen = 16; 208 align = 8; 209 maclen = 16; 210 padlen = align - ((ctx.framelen + 1) % align); 211 212 nonce[0] = 0 as byte; 213 nonce[1] = 0 as byte; 214 nonce[2] = 0 as byte; 215 nonce[3] = 0 as byte; 216 nonce[4] = (ctx.seq_server_to_client >> 56) as byte; 217 nonce[5] = (ctx.seq_server_to_client >> 48) as byte; 218 nonce[6] = (ctx.seq_server_to_client >> 40) as byte; 219 nonce[7] = (ctx.seq_server_to_client >> 32) as byte; 220 nonce[8] = (ctx.seq_server_to_client >> 24) as byte; 221 nonce[9] = (ctx.seq_server_to_client >> 16) as byte; 222 nonce[10] = (ctx.seq_server_to_client >> 8) as byte; 223 nonce[11] = ctx.seq_server_to_client as byte; 224 } else { 225 minlen = 16; 226 align = 8; 227 maclen = 0; 228 padlen = align - ((ctx.framelen + 5) % align); 229 } 230 231 if padlen < 4 { 232 padlen = padlen + align; 233 } 234 235 if ctx.framelen + padlen + 5 < minlen { 236 padlen = padlen + align; 237 } 238 239 if padlen + ctx.framelen + 5 + maclen > ctx.bufsz { 240 die("write too large"); 241 } 242 243 if padlen > 255 { 244 die("padding too large"); 245 } 246 247 len = padlen + ctx.framelen + 1; 248 249 ctx.frame = &ctx.frame[-5]; 250 ctx.frame[0] = (len >> 24) as byte; 251 ctx.frame[1] = (len >> 16) as byte; 252 ctx.frame[2] = (len >> 8) as byte; 253 ctx.frame[3] = len as byte; 254 ctx.frame[4] = padlen as byte; 255 read_rand(&ctx.frame[ctx.framelen + 5], padlen); 256 ctx.framelen = ctx.framelen + 5 + padlen; 257 258 if ctx.en_server_to_client { 259 seq = 0; 260 chacha20_stream(ctx.buf, ctx.buf, 4, &seq, &((&ctx.ek_server_to_client) as *byte)[32], nonce); 261 seq = 0; 262 chacha20_stream(mackey, mackey, 64, &seq, (&ctx.ek_server_to_client) as *byte, nonce); 263 seq = 64; 264 chacha20_stream(&ctx.buf[4], &ctx.buf[4], len, &seq, (&ctx.ek_server_to_client) as *byte, nonce); 265 poly1305(&ctx.buf[len + 4], mackey, ctx.buf, len + 4); 266 } 267 268 ctx.seq_server_to_client = (ctx.seq_server_to_client + 1) & (-1 >> 32); 269 270 if writeall(ctx.fd, ctx.frame, len + 4 + maclen) != 0 { 271 die("write truncated"); 272 } 273 } 274 275 enum { 276 SSH_MSG_DISCONNECT = 0x01, 277 SSH_MSG_SERVICE_REQUEST = 0x05, 278 SSH_MSG_SERVICE_ACCEPT = 0x06, 279 SSH_MSG_KEXINIT = 0x14, 280 SSH_MSG_NEWKEYS = 0x15, 281 SSH_MSG_ECDH_INIT = 0x1e, 282 SSH_MSG_ECDH_REPLY = 0x1f, 283 SSH_MSG_USERAUTH_REQUEST = 0x32, 284 SSH_MSG_USERAUTH_FAILURE = 0x33, 285 SSH_MSG_USERAUTH_SUCCESS = 0x34, 286 SSH_MSG_USERAUTH_PK_OK = 0x3c, 287 SSH_MSG_CHANNEL_OPEN = 0x5a, 288 SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 0x5b, 289 SSH_MSG_CHANNEL_OPEN_FAILURE = 0x5c, 290 SSH_MSG_CHANNEL_WINDOW_ADJUST = 0x5d, 291 SSH_MSG_CHANNEL_DATA = 0x5e, 292 SSH_MSG_CHANNEL_EXTENDED_DATA = 0x5f, 293 SSH_MSG_CHANNEL_EOF = 0x60, 294 SSH_MSG_CHANNEL_CLOSE = 0x61, 295 SSH_MSG_CHANNEL_REQUEST = 0x62, 296 SSH_MSG_CHANNEL_SUCCESS = 0x63, 297 SSH_MSG_CHANNEL_FAILURE = 0x64, 298 } 299 300 enum { 301 SSH_CR_UNKNOWN, 302 SSH_CR_PTY, 303 SSH_CR_SHELL, 304 SSH_CR_EXEC, 305 SSH_CR_WINCH, 306 SSH_CR_SIGNAL, 307 SSH_CR_EXIT_STATUS, 308 SSH_CR_EXIT_SIGNAL, 309 } 310 311 struct ssh_cr_pty { 312 term: ssh_str; 313 cx: int; 314 cy: int; 315 px: int; 316 py: int; 317 modes: ssh_str; 318 } 319 320 struct ssh_cr_shell { 321 } 322 323 struct ssh_cr_exec { 324 command: ssh_str; 325 } 326 327 struct ssh_cr_winch { 328 cx: int; 329 cy: int; 330 px: int; 331 py: int; 332 } 333 334 struct ssh_cr_signal { 335 name: ssh_str; 336 } 337 338 struct ssh_cr_exit { 339 status: int; 340 } 341 342 struct ssh_cr_exit_signal { 343 name: ssh_str; 344 core_dumpped: int; 345 message: ssh_str; 346 lang: ssh_str; 347 } 348 349 func doversion(ctx: *sshd_ctx) { 350 var ident: *byte; 351 var n: int; 352 353 //SSH-2.0-VERSION<CR><LF> 354 n = read_line(ctx.fd, ctx.buf, ctx.bufsz); 355 if n < 8 || memcmp(ctx.buf, "SSH-2.0-", 8) != 0 { 356 die("bad version"); 357 } 358 359 ctx.cver = alloc(ctx.a, n + 1); 360 memcpy(ctx.cver, ctx.buf, n); 361 ctx.cver[n] = 0 as byte; 362 363 if writeall(ctx.fd, ctx.sver, strlen(ctx.sver)) != 0 { 364 die("write truncated"); 365 } 366 367 if writeall(ctx.fd, "\r\n", 2) != 0 { 368 die("write truncated"); 369 } 370 } 371 372 struct ssh_str { 373 len: int; 374 s: *byte; 375 } 376 377 struct ssh_disconnect { 378 reason: int; 379 description: ssh_str; 380 lang: ssh_str; 381 } 382 383 func decode_disconnect(p: *ssh_disconnect, ctx: *sshd_ctx) { 384 var tag: int; 385 decode_u8(&tag, ctx); 386 if tag != SSH_MSG_DISCONNECT { 387 die("not a ssh_disconnect"); 388 } 389 decode_u32(&p.reason, ctx); 390 decode_str(&p.description, ctx); 391 decode_str(&p.lang, ctx); 392 if ctx.index != ctx.framelen { 393 die("trailing data"); 394 } 395 } 396 397 func encode_disconnect(p: *ssh_disconnect, ctx: *sshd_ctx) { 398 var tag: int; 399 clear_frame(ctx); 400 tag = SSH_MSG_DISCONNECT; 401 encode_u32(&p.reason, ctx); 402 encode_str(&p.description, ctx); 403 encode_str(&p.lang, ctx); 404 finish_frame(ctx); 405 } 406 407 struct ssh_kexinit { 408 cookie: ssh_str; 409 kex_algorithms: ssh_str; 410 server_host_key_algorithms: ssh_str; 411 encryption_algorithms_client_to_server: ssh_str; 412 encryption_algorithms_server_to_client: ssh_str; 413 mac_algorithms_client_to_server: ssh_str; 414 mac_algorithms_server_to_client: ssh_str; 415 compression_algorithms_client_to_server: ssh_str; 416 compression_algorithms_server_to_client: ssh_str; 417 languages_client_to_server: ssh_str; 418 languages_server_to_client: ssh_str; 419 first_kex_packet_follows: int; 420 reserved: int; 421 } 422 423 func decode_u8(s: *int, ctx: *sshd_ctx) { 424 if ctx.framelen < 1 || ctx.index > ctx.framelen - 1 { 425 die("u8 truncated"); 426 } 427 *s = ctx.frame[ctx.index] as int; 428 ctx.index = ctx.index + 1; 429 } 430 431 func decode_u32(s: *int, ctx: *sshd_ctx) { 432 if ctx.framelen < 4 || ctx.index > ctx.framelen - 4 { 433 die("u32 truncated"); 434 } 435 *s = (ctx.frame[ctx.index] as int << 24) 436 | (ctx.frame[ctx.index + 1] as int << 16) 437 | (ctx.frame[ctx.index + 2] as int << 8) 438 | ctx.frame[ctx.index + 3] as int; 439 ctx.index = ctx.index + 4; 440 } 441 442 func decode_str(s: *ssh_str, ctx: *sshd_ctx) { 443 decode_u32(&s.len, ctx); 444 if s.len < 0 || ctx.framelen < s.len || ctx.index > ctx.framelen - s.len { 445 die("str truncated"); 446 } 447 s.s = &ctx.frame[ctx.index]; 448 ctx.index = ctx.index + s.len; 449 } 450 451 func decode_cookie(s: *ssh_str, ctx: *sshd_ctx) { 452 if ctx.framelen < 16 || ctx.index > ctx.framelen - 16 { 453 die("cookie truncated"); 454 } 455 s.s = &ctx.frame[ctx.index]; 456 s.len = 16; 457 ctx.index = ctx.index + 16; 458 } 459 460 func decode_bool(s: *int, ctx: *sshd_ctx) { 461 decode_u8(s, ctx); 462 *s = (*s != 0); 463 } 464 465 func decode_kexinit(kex: *ssh_kexinit, ctx: *sshd_ctx) { 466 var tag: int; 467 decode_u8(&tag, ctx); 468 if tag != SSH_MSG_KEXINIT { 469 die("not a kexinit"); 470 } 471 decode_cookie(&kex.cookie, ctx); 472 decode_str(&kex.kex_algorithms, ctx); 473 decode_str(&kex.server_host_key_algorithms, ctx); 474 decode_str(&kex.encryption_algorithms_client_to_server, ctx); 475 decode_str(&kex.encryption_algorithms_server_to_client, ctx); 476 decode_str(&kex.mac_algorithms_client_to_server, ctx); 477 decode_str(&kex.mac_algorithms_server_to_client, ctx); 478 decode_str(&kex.compression_algorithms_client_to_server, ctx); 479 decode_str(&kex.compression_algorithms_server_to_client, ctx); 480 decode_str(&kex.languages_client_to_server, ctx); 481 decode_str(&kex.languages_server_to_client, ctx); 482 decode_bool(&kex.first_kex_packet_follows, ctx); 483 decode_u32(&kex.reserved, ctx); 484 if ctx.index != ctx.framelen { 485 die("trailing data"); 486 } 487 } 488 489 func decode_newkeys(kex: *ssh_newkeys, ctx: *sshd_ctx) { 490 var tag: int; 491 decode_u8(&tag, ctx); 492 if tag != SSH_MSG_NEWKEYS { 493 die("not a newkeys"); 494 } 495 if ctx.index != ctx.framelen { 496 die("trailing data"); 497 } 498 } 499 500 struct ssh_ecdh_init { 501 qc: ssh_str; 502 } 503 504 func decode_ecdh_init(dh: *ssh_ecdh_init, ctx: *sshd_ctx) { 505 var tag: int; 506 decode_u8(&tag, ctx); 507 if tag != SSH_MSG_ECDH_INIT { 508 die("not a ecdh_init"); 509 } 510 decode_str(&dh.qc, ctx); 511 if ctx.index != ctx.framelen { 512 die("trailing data"); 513 } 514 } 515 516 struct ssh_service_request { 517 name: ssh_str; 518 } 519 520 func decode_service_request(sr: *ssh_service_request, ctx: *sshd_ctx) { 521 var tag: int; 522 decode_u8(&tag, ctx); 523 if tag != SSH_MSG_SERVICE_REQUEST { 524 die("not a ecdh_init"); 525 } 526 decode_str(&sr.name, ctx); 527 if ctx.index != ctx.framelen { 528 die("trailing data"); 529 } 530 } 531 532 struct ssh_userauth_request { 533 user: ssh_str; 534 service: ssh_str; 535 method: ssh_str; 536 has_sig: int; 537 alg: ssh_str; 538 pub: ssh_str; 539 sig: ssh_str; 540 } 541 542 func decode_userauth_request(ar: *ssh_userauth_request, ctx: *sshd_ctx) { 543 var tag: int; 544 decode_u8(&tag, ctx); 545 if tag != SSH_MSG_USERAUTH_REQUEST { 546 die("not a userauth_request"); 547 } 548 549 decode_str(&ar.user, ctx); 550 decode_str(&ar.service, ctx); 551 decode_str(&ar.method, ctx); 552 553 if ssh_streq(&ar.method, "none") { 554 ar.has_sig = 0; 555 set_str(&ar.alg, ""); 556 set_str(&ar.pub, ""); 557 set_str(&ar.sig, ""); 558 } else if ssh_streq(&ar.method, "publickey") { 559 decode_bool(&ar.has_sig, ctx); 560 decode_str(&ar.alg, ctx); 561 decode_str(&ar.pub, ctx); 562 if ar.has_sig { 563 decode_str(&ar.sig, ctx); 564 } else { 565 set_str(&ar.sig, ""); 566 } 567 } else { 568 die("unknown method"); 569 } 570 571 if ctx.index != ctx.framelen { 572 die("trailing data"); 573 } 574 } 575 576 func set_str(s: *ssh_str, v: *byte) { 577 s.s = v; 578 s.len = strlen(v); 579 } 580 581 struct _ssh_cookie { 582 x0: int; 583 x1: int; 584 } 585 586 func clear_frame(ctx: *sshd_ctx) { 587 ctx.frame = &ctx.buf[5]; 588 ctx.framelen = ctx.bufsz - 5; 589 ctx.index = 0; 590 } 591 592 func finish_frame(ctx: *sshd_ctx) { 593 ctx.framelen = ctx.index; 594 } 595 596 func encode_u8(x: *int, ctx: *sshd_ctx) { 597 if ctx.framelen < 1 || ctx.index > ctx.framelen - 1 { 598 die("u8 truncated"); 599 } 600 ctx.frame[ctx.index] = (*x) as byte; 601 ctx.index = ctx.index + 1; 602 } 603 604 func encode_cookie(x: *ssh_str, ctx: *sshd_ctx) { 605 if x.len != 16 || ctx.framelen < 16 || ctx.index > ctx.framelen - 16 { 606 die("cookie truncated"); 607 } 608 memcpy(&ctx.frame[ctx.index], x.s, 16); 609 ctx.index = ctx.index + 16; 610 } 611 612 func encode_bool(x: *int, ctx: *sshd_ctx) { 613 var y: int; 614 y = *x != 0; 615 encode_u8(&y, ctx); 616 } 617 618 func encode_u32(x: *int, ctx: *sshd_ctx) { 619 if ctx.framelen < 4 || ctx.index > ctx.framelen - 4 { 620 die("u32 truncated"); 621 } 622 ctx.frame[ctx.index] = (*x >> 24) as byte; 623 ctx.frame[ctx.index + 1] = (*x >> 16) as byte; 624 ctx.frame[ctx.index + 2] = (*x >> 8) as byte; 625 ctx.frame[ctx.index + 3] = (*x) as byte; 626 ctx.index = ctx.index + 4; 627 } 628 629 func encode_blob(x: *ssh_blob, ctx: *sshd_ctx) { 630 var len: int; 631 len = x.alg.len + x.blob.len + 8; 632 encode_u32(&len, ctx); 633 encode_str(&x.alg, ctx); 634 encode_str(&x.blob, ctx); 635 } 636 637 func encode_str(x: *ssh_str, ctx: *sshd_ctx) { 638 encode_u32(&x.len, ctx); 639 if ctx.framelen < x.len || ctx.index > ctx.framelen - x.len { 640 die("str truncated"); 641 } 642 memcpy(&ctx.frame[ctx.index], x.s, x.len); 643 ctx.index = ctx.index + x.len; 644 } 645 646 func encode_kexinit(kex: *ssh_kexinit, ctx: *sshd_ctx) { 647 var tag: int; 648 clear_frame(ctx); 649 tag = SSH_MSG_KEXINIT; 650 encode_u8(&tag, ctx); 651 encode_cookie(&kex.cookie, ctx); 652 encode_str(&kex.kex_algorithms, ctx); 653 encode_str(&kex.server_host_key_algorithms, ctx); 654 encode_str(&kex.encryption_algorithms_client_to_server, ctx); 655 encode_str(&kex.encryption_algorithms_server_to_client, ctx); 656 encode_str(&kex.mac_algorithms_client_to_server, ctx); 657 encode_str(&kex.mac_algorithms_server_to_client, ctx); 658 encode_str(&kex.compression_algorithms_client_to_server, ctx); 659 encode_str(&kex.compression_algorithms_server_to_client, ctx); 660 encode_str(&kex.languages_client_to_server, ctx); 661 encode_str(&kex.languages_server_to_client, ctx); 662 encode_bool(&kex.first_kex_packet_follows, ctx); 663 encode_u32(&kex.reserved, ctx); 664 finish_frame(ctx); 665 } 666 667 struct ssh_newkeys { 668 } 669 670 func encode_newkeys(kex: *ssh_newkeys, ctx: *sshd_ctx) { 671 var tag: int; 672 clear_frame(ctx); 673 tag = SSH_MSG_NEWKEYS; 674 encode_u8(&tag, ctx); 675 finish_frame(ctx); 676 } 677 678 struct ssh_service_accept { 679 name: ssh_str; 680 } 681 682 func encode_service_accept(sa: *ssh_service_accept, ctx: *sshd_ctx) { 683 var tag: int; 684 clear_frame(ctx); 685 tag = SSH_MSG_SERVICE_ACCEPT; 686 encode_u8(&tag, ctx); 687 encode_str(&sa.name, ctx); 688 finish_frame(ctx); 689 } 690 691 struct ssh_userauth_failure { 692 methods: ssh_str; 693 partial_success: int; 694 } 695 696 func encode_userauth_failure(uf: *ssh_userauth_failure, ctx: *sshd_ctx) { 697 var tag: int; 698 clear_frame(ctx); 699 tag = SSH_MSG_USERAUTH_FAILURE; 700 encode_u8(&tag, ctx); 701 encode_str(&uf.methods, ctx); 702 encode_bool(&uf.partial_success, ctx); 703 finish_frame(ctx); 704 } 705 706 struct ssh_userauth_success { 707 } 708 709 func encode_userauth_success(us: *ssh_userauth_success, ctx: *sshd_ctx) { 710 var tag: int; 711 clear_frame(ctx); 712 tag = SSH_MSG_USERAUTH_SUCCESS; 713 encode_u8(&tag, ctx); 714 finish_frame(ctx); 715 } 716 717 struct ssh_userauth_pk_ok { 718 alg: ssh_str; 719 pub: ssh_str; 720 } 721 722 func encode_userauth_pk_ok(ok: *ssh_userauth_pk_ok, ctx: *sshd_ctx) { 723 var tag: int; 724 clear_frame(ctx); 725 tag = SSH_MSG_USERAUTH_PK_OK; 726 encode_u8(&tag, ctx); 727 encode_str(&ok.alg, ctx); 728 encode_str(&ok.pub, ctx); 729 finish_frame(ctx); 730 } 731 732 struct ssh_blob { 733 alg: ssh_str; 734 blob: ssh_str; 735 } 736 737 struct ssh_ecdh_reply { 738 ks: ssh_blob; 739 qs: ssh_str; 740 sig: ssh_blob; 741 } 742 743 func set_blob(d: *ssh_blob, alg: *byte, b: *byte, n: int) { 744 set_str(&d.alg, alg); 745 d.blob.s = b; 746 d.blob.len = n; 747 } 748 749 func encode_ecdh_reply(dh: *ssh_ecdh_reply, ctx: *sshd_ctx) { 750 var tag: int; 751 clear_frame(ctx); 752 tag = SSH_MSG_ECDH_REPLY; 753 encode_u8(&tag, ctx); 754 encode_blob(&dh.ks, ctx); 755 encode_str(&dh.qs, ctx); 756 encode_blob(&dh.sig, ctx); 757 finish_frame(ctx); 758 } 759 760 func ssh_u32_sha256_update(ctx: *sha256_ctx, n: int) { 761 var a: byte; 762 a = (n >> 24) as byte; 763 sha256_update(ctx, &a, 1); 764 a = (n >> 16) as byte; 765 sha256_update(ctx, &a, 1); 766 a = (n >> 8) as byte; 767 sha256_update(ctx, &a, 1); 768 a = n as byte; 769 sha256_update(ctx, &a, 1); 770 } 771 772 func ssh_blob_sha256_update(ctx: *sha256_ctx, b: *ssh_blob) { 773 ssh_u32_sha256_update(ctx, b.alg.len + b.blob.len + 8); 774 ssh_str_sha256_update(ctx, b.alg.s, b.alg.len); 775 ssh_str_sha256_update(ctx, b.blob.s, b.blob.len); 776 } 777 778 func ssh_str_sha256_update(ctx: *sha256_ctx, b: *byte, n: int) { 779 ssh_u32_sha256_update(ctx, n); 780 sha256_update(ctx, b, n); 781 } 782 783 func ssh_mpint_sha256_update(ctx: *sha256_ctx, b: *byte, n: int) { 784 var a: byte; 785 786 loop { 787 if n == 1 { 788 break; 789 } 790 791 if b[0] as int != 0 { 792 break; 793 } 794 795 b = &b[1]; 796 n = n - 1; 797 } 798 799 if b[0] as int & 128 { 800 ssh_u32_sha256_update(ctx, n + 1); 801 a = 0 as byte; 802 sha256_update(ctx, &a, 1); 803 sha256_update(ctx, b, n); 804 } else { 805 ssh_u32_sha256_update(ctx, n); 806 sha256_update(ctx, b, n); 807 } 808 } 809 810 struct ssh_channel_open { 811 channel_type: ssh_str; 812 channel: int; 813 initial_window_size: int; 814 maximum_packet_size: int; 815 } 816 817 func decode_channel_open(p: *ssh_channel_open, ctx: *sshd_ctx) { 818 var tag: int; 819 decode_u8(&tag, ctx); 820 if tag != SSH_MSG_CHANNEL_OPEN { 821 die("not a channel_open"); 822 } 823 824 decode_str(&p.channel_type, ctx); 825 decode_u32(&p.channel, ctx); 826 decode_u32(&p.initial_window_size, ctx); 827 decode_u32(&p.maximum_packet_size, ctx); 828 829 if ctx.index != ctx.framelen { 830 die("trailing data"); 831 } 832 } 833 834 struct ssh_channel_open_confirmation { 835 channel: int; 836 sender_channel: int; 837 initial_window_size: int; 838 maximum_packet_size: int; 839 } 840 841 func encode_channel_open_confirmation(p: *ssh_channel_open_confirmation, ctx: *sshd_ctx) { 842 var tag: int; 843 clear_frame(ctx); 844 tag = SSH_MSG_CHANNEL_OPEN_CONFIRMATION; 845 encode_u8(&tag, ctx); 846 encode_u32(&p.channel, ctx); 847 encode_u32(&p.sender_channel, ctx); 848 encode_u32(&p.initial_window_size, ctx); 849 encode_u32(&p.maximum_packet_size, ctx); 850 finish_frame(ctx); 851 if ctx.index != ctx.framelen { 852 die("trailing data"); 853 } 854 } 855 856 struct ssh_channel_open_failure { 857 channel: int; 858 reason: int; 859 description: ssh_str; 860 lang: ssh_str; 861 } 862 863 func encode_channel_open_failure(p: *ssh_channel_open_failure, ctx: *sshd_ctx) { 864 var tag: int; 865 clear_frame(ctx); 866 tag = SSH_MSG_CHANNEL_OPEN_FAILURE; 867 encode_u8(&tag, ctx); 868 encode_u32(&p.channel, ctx); 869 encode_u32(&p.reason, ctx); 870 encode_str(&p.description, ctx); 871 encode_str(&p.lang, ctx); 872 finish_frame(ctx); 873 } 874 875 struct ssh_channel_window_adjust { 876 channel: int; 877 window: int; 878 } 879 880 func decode_channel_window_adjust(p: *ssh_channel_window_adjust, ctx: *sshd_ctx) { 881 var tag: int; 882 decode_u8(&tag, ctx); 883 if tag != SSH_MSG_CHANNEL_WINDOW_ADJUST { 884 die("not a channel_window_adjust"); 885 } 886 decode_u32(&p.channel, ctx); 887 decode_u32(&p.window, ctx); 888 if ctx.index != ctx.framelen { 889 die("trailing data"); 890 } 891 } 892 893 func encode_channel_window_adjust(p: *ssh_channel_window_adjust, ctx: *sshd_ctx) { 894 var tag: int; 895 clear_frame(ctx); 896 tag = SSH_MSG_CHANNEL_WINDOW_ADJUST; 897 encode_u8(&tag, ctx); 898 encode_u32(&p.channel, ctx); 899 encode_u32(&p.window, ctx); 900 finish_frame(ctx); 901 } 902 903 struct ssh_channel_data { 904 channel: int; 905 data: ssh_str; 906 } 907 908 func decode_channel_data(p: *ssh_channel_data, ctx: *sshd_ctx) { 909 var tag: int; 910 decode_u8(&tag, ctx); 911 if tag != SSH_MSG_CHANNEL_DATA { 912 die("not a channel_data"); 913 } 914 decode_u32(&p.channel, ctx); 915 decode_str(&p.data, ctx); 916 if ctx.index != ctx.framelen { 917 die("trailing data"); 918 } 919 } 920 921 func encode_channel_data(p: *ssh_channel_data, ctx: *sshd_ctx) { 922 var tag: int; 923 clear_frame(ctx); 924 tag = SSH_MSG_CHANNEL_DATA; 925 encode_u8(&tag, ctx); 926 encode_u32(&p.channel, ctx); 927 encode_str(&p.data, ctx); 928 finish_frame(ctx); 929 } 930 931 struct ssh_channel_extended_data { 932 channel: int; 933 code: int; 934 data: ssh_str; 935 } 936 937 func encode_channel_extended_data(p: *ssh_channel_extended_data, ctx: *sshd_ctx) { 938 var tag: int; 939 clear_frame(ctx); 940 tag = SSH_MSG_CHANNEL_EXTENDED_DATA; 941 encode_u8(&tag, ctx); 942 encode_u32(&p.channel, ctx); 943 encode_u32(&p.code, ctx); 944 encode_str(&p.data, ctx); 945 finish_frame(ctx); 946 } 947 948 struct ssh_channel_eof { 949 channel: int; 950 } 951 952 func decode_channel_eof(p: *ssh_channel_eof, ctx: *sshd_ctx) { 953 var tag: int; 954 decode_u8(&tag, ctx); 955 if tag != SSH_MSG_CHANNEL_EOF { 956 die("not a channel_eof"); 957 } 958 decode_u32(&p.channel, ctx); 959 if ctx.index != ctx.framelen { 960 die("trailing data"); 961 } 962 } 963 964 func encode_channel_eof(p: *ssh_channel_eof, ctx: *sshd_ctx) { 965 var tag: int; 966 clear_frame(ctx); 967 tag = SSH_MSG_CHANNEL_EOF; 968 encode_u8(&tag, ctx); 969 encode_u32(&p.channel, ctx); 970 finish_frame(ctx); 971 } 972 973 struct ssh_channel_close { 974 channel: int; 975 } 976 977 func decode_channel_close(p: *ssh_channel_close, ctx: *sshd_ctx) { 978 var tag: int; 979 decode_u8(&tag, ctx); 980 if tag != SSH_MSG_CHANNEL_CLOSE { 981 die("not a channel_close"); 982 } 983 decode_u32(&p.channel, ctx); 984 if ctx.index != ctx.framelen { 985 die("trailing data"); 986 } 987 } 988 989 func encode_channel_close(p: *ssh_channel_close, ctx: *sshd_ctx) { 990 var tag: int; 991 clear_frame(ctx); 992 tag = SSH_MSG_CHANNEL_CLOSE; 993 encode_u8(&tag, ctx); 994 encode_u32(&p.channel, ctx); 995 finish_frame(ctx); 996 } 997 998 struct ssh_channel_request { 999 channel: int; 1000 request: ssh_str; 1001 want_reply: int; 1002 kind: int; 1003 unknown: ssh_str; 1004 pty: ssh_cr_pty; 1005 shell: ssh_cr_shell; 1006 exec: ssh_cr_exec; 1007 winch: ssh_cr_winch; 1008 signal: ssh_cr_signal; 1009 exit: ssh_cr_exit; 1010 exit_signal: ssh_cr_exit_signal; 1011 } 1012 1013 func decode_channel_request(p: *ssh_channel_request, ctx: *sshd_ctx) { 1014 var tag: int; 1015 bzero(p as *byte, sizeof(*p)); 1016 decode_u8(&tag, ctx); 1017 if tag != SSH_MSG_CHANNEL_REQUEST { 1018 die("not a channel_request"); 1019 } 1020 decode_u32(&p.channel, ctx); 1021 decode_str(&p.request, ctx); 1022 decode_bool(&p.want_reply, ctx); 1023 if ssh_streq(&p.request, "pty-req") { 1024 p.kind = SSH_CR_PTY; 1025 decode_str(&p.pty.term, ctx); 1026 decode_u32(&p.pty.cx, ctx); 1027 decode_u32(&p.pty.cy, ctx); 1028 decode_u32(&p.pty.px, ctx); 1029 decode_u32(&p.pty.py, ctx); 1030 decode_str(&p.pty.modes, ctx); 1031 } else if ssh_streq(&p.request, "shell") { 1032 p.kind = SSH_CR_SHELL; 1033 } else if ssh_streq(&p.request, "exec") { 1034 p.kind = SSH_CR_EXEC; 1035 decode_str(&p.exec.command, ctx); 1036 } else if ssh_streq(&p.request, "window-change") { 1037 p.kind = SSH_CR_WINCH; 1038 decode_u32(&p.winch.cx, ctx); 1039 decode_u32(&p.winch.cy, ctx); 1040 decode_u32(&p.winch.px, ctx); 1041 decode_u32(&p.winch.py, ctx); 1042 } else if ssh_streq(&p.request, "signal") { 1043 p.kind = SSH_CR_SIGNAL; 1044 decode_str(&p.signal.name, ctx); 1045 } else { 1046 p.kind = SSH_CR_UNKNOWN; 1047 p.unknown.s = &ctx.frame[ctx.index]; 1048 p.unknown.len = ctx.framelen - ctx.index; 1049 ctx.index = ctx.framelen; 1050 } 1051 if ctx.index != ctx.framelen { 1052 die("trailing data"); 1053 } 1054 } 1055 1056 func encode_channel_request(p: *ssh_channel_request, ctx: *sshd_ctx) { 1057 var tag: int; 1058 clear_frame(ctx); 1059 tag = SSH_MSG_CHANNEL_REQUEST; 1060 encode_u8(&tag, ctx); 1061 encode_u32(&p.channel, ctx); 1062 if p.kind == SSH_CR_EXIT_STATUS { 1063 set_str(&p.request, "exit-status"); 1064 encode_str(&p.request, ctx); 1065 p.want_reply = 0; 1066 encode_bool(&p.want_reply, ctx); 1067 encode_u32(&p.exit.status, ctx); 1068 } else if p.kind == SSH_CR_EXIT_SIGNAL { 1069 set_str(&p.request, "exit-signal"); 1070 encode_str(&p.request, ctx); 1071 p.want_reply = 0; 1072 encode_bool(&p.want_reply, ctx); 1073 encode_str(&p.exit_signal.name, ctx); 1074 encode_bool(&p.exit_signal.core_dumpped, ctx); 1075 encode_str(&p.exit_signal.message, ctx); 1076 encode_str(&p.exit_signal.lang, ctx); 1077 } else { 1078 encode_str(&p.request, ctx); 1079 encode_bool(&p.want_reply, ctx); 1080 } 1081 finish_frame(ctx); 1082 } 1083 1084 struct ssh_channel_success { 1085 channel: int; 1086 } 1087 1088 func encode_channel_success(p: *ssh_channel_success, ctx: *sshd_ctx) { 1089 var tag: int; 1090 clear_frame(ctx); 1091 tag = SSH_MSG_CHANNEL_SUCCESS; 1092 encode_u8(&tag, ctx); 1093 encode_u32(&p.channel, ctx); 1094 finish_frame(ctx); 1095 } 1096 1097 struct ssh_channel_failure { 1098 channel: int; 1099 } 1100 1101 func encode_channel_failure(p: *ssh_channel_failure, ctx: *sshd_ctx) { 1102 var tag: int; 1103 clear_frame(ctx); 1104 tag = SSH_MSG_CHANNEL_FAILURE; 1105 encode_u8(&tag, ctx); 1106 encode_u32(&p.channel, ctx); 1107 finish_frame(ctx); 1108 } 1109 1110 func dokex(ctx: *sshd_ctx) { 1111 var cookie: _ssh_cookie; 1112 var ckex: ssh_kexinit; 1113 var skex: ssh_kexinit; 1114 var newkeys: ssh_newkeys; 1115 var cdh: ssh_ecdh_init; 1116 var sdh: ssh_ecdh_reply; 1117 var rs: _ed25519_point; 1118 var qs: _ed25519_point; 1119 var k: _ed25519_point; 1120 var ehctx: sha256_ctx; 1121 var eh: _sha256_digest; 1122 var sig: _ed25519_sig; 1123 1124 // <- SSH_MSG_KEXINIT 1125 decode_kexinit(&ckex, ctx); 1126 memcpy(ctx.ckex, ctx.frame, ctx.framelen); 1127 ctx.ckexlen = ctx.framelen; 1128 1129 if ckex.first_kex_packet_follows { 1130 die("first_kex_packet_follows not implemented"); 1131 } 1132 1133 // -> SSH_MSG_KEXINIT 1134 read_rand((&cookie) as *byte, 16); 1135 skex.cookie.len = 16; 1136 skex.cookie.s = (&cookie) as *byte; 1137 set_str(&skex.kex_algorithms, "curve25519-sha256"); 1138 set_str(&skex.server_host_key_algorithms, "ssh-ed25519"); 1139 set_str(&skex.encryption_algorithms_client_to_server, "chacha20-poly1305@openssh.com"); 1140 set_str(&skex.encryption_algorithms_server_to_client, "chacha20-poly1305@openssh.com"); 1141 set_str(&skex.mac_algorithms_client_to_server, "none"); 1142 set_str(&skex.mac_algorithms_server_to_client, "none"); 1143 set_str(&skex.compression_algorithms_client_to_server, "none"); 1144 set_str(&skex.compression_algorithms_server_to_client, "none"); 1145 set_str(&skex.languages_client_to_server, ""); 1146 set_str(&skex.languages_server_to_client, ""); 1147 skex.first_kex_packet_follows = 0; 1148 skex.reserved = 0; 1149 1150 encode_kexinit(&skex, ctx); 1151 memcpy(ctx.skex, ctx.frame, ctx.framelen); 1152 ctx.skexlen = ctx.index; 1153 1154 write_frame(ctx); 1155 1156 // <- SSH_MSG_ECDH_INIT 1157 read_frame(ctx); 1158 decode_ecdh_init(&cdh, ctx); 1159 1160 if cdh.qc.len != 32 { 1161 die("bad ecdh_init"); 1162 } 1163 1164 read_rand((&rs) as *byte, 32); 1165 1166 x25519_base((&qs) as *byte); 1167 1168 if !x25519((&qs) as *byte, (&qs) as *byte, (&rs) as *byte) { 1169 die("bad x25519 server"); 1170 } 1171 1172 if !x25519((&k) as *byte, cdh.qc.s, (&rs) as *byte) { 1173 die("bad x25519 client"); 1174 } 1175 1176 set_blob(&sdh.ks, "ssh-ed25519", (&ctx.pub) as *byte, 32); 1177 sdh.qs.s = (&qs) as *byte; 1178 sdh.qs.len = 32; 1179 set_blob(&sdh.sig, "ssh-ed25519", (&sig) as *byte, 64); 1180 1181 sha256_init(&ehctx); 1182 ssh_str_sha256_update(&ehctx, ctx.cver, strlen(ctx.cver)); 1183 ssh_str_sha256_update(&ehctx, ctx.sver, strlen(ctx.sver)); 1184 ssh_str_sha256_update(&ehctx, ctx.ckex, ctx.ckexlen); 1185 ssh_str_sha256_update(&ehctx, ctx.skex, ctx.skexlen); 1186 ssh_blob_sha256_update(&ehctx, &sdh.ks); 1187 ssh_str_sha256_update(&ehctx, cdh.qc.s, 32); 1188 ssh_str_sha256_update(&ehctx, (&qs) as *byte, 32); 1189 ssh_mpint_sha256_update(&ehctx, (&k) as *byte, 32); 1190 sha256_final((&eh) as *byte, &ehctx); 1191 1192 ed25519_sign((&sig) as *byte, (&ctx.priv) as *byte, (&eh) as *byte, 32); 1193 1194 // -> SSH_MSG_ECDH_REPLY 1195 encode_ecdh_reply(&sdh, ctx); 1196 write_frame(ctx); 1197 1198 if !ctx.has_session_id { 1199 memcpy((&ctx.session_id) as *byte, (&eh) as *byte, 32); 1200 ctx.has_session_id = 1; 1201 } 1202 1203 memcpy((&ctx.eh) as *byte, (&eh) as *byte, 32); 1204 memcpy((&ctx.k) as *byte, (&k) as *byte, 32); 1205 1206 kex_key((&ctx.iv_client_to_server) as *byte, "A", ctx); 1207 kex_key((&ctx.iv_server_to_client) as *byte, "B", ctx); 1208 kex_key((&ctx.ek_client_to_server) as *byte, "C", ctx); 1209 kex_key((&ctx.ek_server_to_client) as *byte, "D", ctx); 1210 kex_key((&ctx.ik_client_to_server) as *byte, "E", ctx); 1211 kex_key((&ctx.ik_server_to_client) as *byte, "F", ctx); 1212 1213 // -> SSH_MSG_NEWKEYS 1214 encode_newkeys(&newkeys, ctx); 1215 write_frame(ctx); 1216 ctx.en_server_to_client = 1; 1217 1218 // <- SSH_MSG_NEWKEYS 1219 read_frame(ctx); 1220 decode_newkeys(&newkeys, ctx); 1221 ctx.en_client_to_server = 1; 1222 } 1223 1224 func kex_key(key: *byte, a: *byte, ctx: *sshd_ctx) { 1225 var h: sha256_ctx; 1226 1227 sha256_init(&h); 1228 ssh_mpint_sha256_update(&h, (&ctx.k) as *byte, 32); 1229 sha256_update(&h, (&ctx.eh) as *byte, 32); 1230 sha256_update(&h, a, 1); 1231 sha256_update(&h, (&ctx.session_id) as *byte, 32); 1232 sha256_final(key, &h); 1233 1234 sha256_init(&h); 1235 ssh_mpint_sha256_update(&h, (&ctx.k) as *byte, 32); 1236 sha256_update(&h, (&ctx.eh) as *byte, 32); 1237 sha256_update(&h, key, 32); 1238 sha256_final(&key[32], &h); 1239 } 1240 1241 func ssh_streq(a: *ssh_str, b: *byte): int { 1242 var len: int; 1243 len = strlen(b); 1244 return a.len == len && memcmp(a.s, b, len) == 0; 1245 } 1246 1247 func doauth(ctx: *sshd_ctx) { 1248 var csr: ssh_service_request; 1249 var cua: ssh_userauth_request; 1250 var ssa: ssh_service_accept; 1251 var suf: ssh_userauth_failure; 1252 var sus: ssh_userauth_success; 1253 var sok: ssh_userauth_pk_ok; 1254 var sig: _ed25519_sig; 1255 var b: int; 1256 var s: ssh_str; 1257 1258 // <- SSH_MSG_SERVICE_REQUEST 1259 decode_service_request(&csr, ctx); 1260 if !ssh_streq(&csr.name, "ssh-userauth") { 1261 die("not ssh-userauth"); 1262 } 1263 1264 // -> SSH_MSG_SERVICE_ACCEPT 1265 set_str(&ssa.name, "ssh-userauth"); 1266 encode_service_accept(&ssa, ctx); 1267 write_frame(ctx); 1268 1269 loop { 1270 1271 // <- SSH_MSG_USERAUTH_REQUEST 1272 read_frame(ctx); 1273 decode_userauth_request(&cua, ctx); 1274 if !ssh_streq(&cua.service, "ssh-connection") || !ssh_streq(&cua.user, ctx.username) { 1275 die("bad auth"); 1276 } 1277 1278 if !ssh_streq(&cua.method, "publickey") || !ssh_streq(&cua.alg, "ssh-ed25519") { 1279 // -> SSH_MSG_USERAUTH_FAILURE("publickey") 1280 set_str(&suf.methods, "publickey"); 1281 suf.partial_success = 0; 1282 encode_userauth_failure(&suf, ctx); 1283 write_frame(ctx); 1284 continue; 1285 } 1286 1287 if cua.pub.len != ctx.userkeylen || memcmp(cua.pub.s, ctx.userkey, ctx.userkeylen) { 1288 // -> SSH_MSG_USERAUTH_FAILURE("publickey") 1289 set_str(&suf.methods, "publickey"); 1290 suf.partial_success = 0; 1291 encode_userauth_failure(&suf, ctx); 1292 write_frame(ctx); 1293 continue; 1294 } 1295 1296 if !cua.has_sig { 1297 // -> SSH_MSG_USERAUTH_PK_OK 1298 set_str(&sok.alg, "ssh-ed25519"); 1299 sok.pub.s = ctx.userkey; 1300 sok.pub.len = ctx.userkeylen; 1301 encode_userauth_pk_ok(&sok, ctx); 1302 write_frame(ctx); 1303 continue; 1304 } 1305 1306 break; 1307 } 1308 1309 if cua.sig.len != 83 { 1310 die("sig wrong length"); 1311 } 1312 1313 memcpy((&sig) as *byte, &cua.sig.s[19], 64); 1314 1315 clear_frame(ctx); 1316 s.s = (&ctx.session_id) as *byte; 1317 s.len = 32; 1318 encode_str(&s, ctx); 1319 b = SSH_MSG_USERAUTH_REQUEST; 1320 encode_u8(&b, ctx); 1321 set_str(&s, ctx.username); 1322 encode_str(&s, ctx); 1323 set_str(&s, "ssh-connection"); 1324 encode_str(&s, ctx); 1325 set_str(&s, "publickey"); 1326 encode_str(&s, ctx); 1327 b = 1; 1328 encode_bool(&b, ctx); 1329 set_str(&s, "ssh-ed25519"); 1330 encode_str(&s, ctx); 1331 s.s = ctx.userkey; 1332 s.len = ctx.userkeylen; 1333 encode_str(&s, ctx); 1334 finish_frame(ctx); 1335 1336 if !ed25519_verify((&sig) as *byte, (&ctx.userpub) as *byte, ctx.frame, ctx.framelen) { 1337 die("bad signature"); 1338 } 1339 1340 encode_userauth_success(&sus, ctx); 1341 write_frame(ctx); 1342 } 1343 1344 func dosession(ctx: *sshd_ctx) { 1345 var cco: ssh_channel_open; 1346 var scc: ssh_channel_open_confirmation; 1347 var ccr: ssh_channel_request; 1348 var scs: ssh_channel_success; 1349 var scf: ssh_channel_failure; 1350 1351 decode_channel_open(&cco, ctx); 1352 if !ssh_streq(&cco.channel_type, "session") || cco.channel != 0 { 1353 die("not session"); 1354 } 1355 1356 ctx.stdout_window = cco.initial_window_size; 1357 if cco.maximum_packet_size < 1024 { 1358 die("max packet size too small"); 1359 } 1360 1361 scc.channel = 0; 1362 scc.sender_channel = 0; 1363 scc.initial_window_size = ctx.stdin_size; 1364 scc.maximum_packet_size = ctx.bufsz - 64; 1365 1366 encode_channel_open_confirmation(&scc, ctx); 1367 write_frame(ctx); 1368 } 1369 1370 func dodisconnect(ctx: *sshd_ctx) { 1371 var d: ssh_disconnect; 1372 decode_disconnect(&d, ctx); 1373 exit(0); 1374 } 1375 1376 func dowindow(ctx: *sshd_ctx) { 1377 var cwa: ssh_channel_window_adjust; 1378 decode_channel_window_adjust(&cwa, ctx); 1379 ctx.stdout_window = ctx.stdout_window + cwa.window; 1380 } 1381 1382 func dodata(ctx: *sshd_ctx) { 1383 var cd: ssh_channel_data; 1384 decode_channel_data(&cd, ctx); 1385 if ctx.stdin_eof { 1386 return; 1387 } 1388 if cd.data.len > ctx.stdin_size - ctx.stdin_fill { 1389 die("stdin overflow"); 1390 } 1391 memcpy(&ctx.stdin_buf[ctx.stdin_fill], cd.data.s, cd.data.len); 1392 ctx.stdin_fill = ctx.stdin_fill + cd.data.len; 1393 } 1394 1395 func doeof(ctx: *sshd_ctx) { 1396 var ce: ssh_channel_eof; 1397 decode_channel_eof(&ce, ctx); 1398 ctx.stdin_eof = 1; 1399 } 1400 1401 func doclose(ctx: *sshd_ctx) { 1402 var cc: ssh_channel_close; 1403 decode_channel_close(&cc, ctx); 1404 exit(0); 1405 } 1406 1407 struct _argv4 { 1408 arg0: *byte; 1409 arg1: *byte; 1410 arg2: *byte; 1411 arg3: *byte; 1412 } 1413 1414 func ssh_spawn(ctx: *sshd_ctx, argv: **byte) { 1415 var pid: int; 1416 var stdin_read: int; 1417 var stdin_write: int; 1418 var stdout_read: int; 1419 var stdout_write: int; 1420 var stderr_read: int; 1421 var stderr_write: int; 1422 1423 if ctx.has_child { 1424 die("already spawned"); 1425 } 1426 1427 if pipe(&stdin_read, &stdin_write) != 0 { 1428 die("stdin pipe failed"); 1429 } 1430 1431 if pipe(&stdout_read, &stdout_write) != 0 { 1432 die("stdout pipe failed"); 1433 } 1434 1435 if pipe(&stderr_read, &stderr_write) != 0 { 1436 die("stderr pipe failed"); 1437 } 1438 1439 pid = fork(); 1440 if pid < 0 { 1441 die("fork failed"); 1442 } 1443 1444 if pid == 0 { 1445 close(ctx.fd); 1446 1447 close(stdin_write); 1448 close(stdout_read); 1449 close(stderr_read); 1450 1451 dup2(stdin_read, 0); 1452 dup2(stdout_write, 1); 1453 dup2(stderr_write, 2); 1454 1455 close(stdin_read); 1456 close(stdout_write); 1457 close(stderr_write); 1458 1459 exec(argv[0], argv, nil); 1460 1461 exit(255); 1462 } 1463 1464 close(stdin_read); 1465 close(stdout_write); 1466 close(stderr_write); 1467 1468 ctx.has_child = 1; 1469 ctx.child_pid = pid; 1470 ctx.child_stdin = stdin_write; 1471 ctx.child_stdout = stdout_read; 1472 ctx.child_stderr = stderr_read; 1473 } 1474 1475 func dopty(cr: *ssh_cr_pty, ctx: *sshd_ctx): int { 1476 // allocate pty 1477 return 0; 1478 } 1479 1480 func doshell(cr: *ssh_cr_shell, ctx: *sshd_ctx): int { 1481 var argv: _argv4; 1482 argv.arg0 = "/bin/sh"; 1483 argv.arg1 = nil; 1484 ssh_spawn(ctx, &argv.arg0); 1485 return 1; 1486 } 1487 1488 func doexec(cr: *ssh_cr_exec, ctx: *sshd_ctx): int { 1489 var argv: _argv4; 1490 var cmd: *byte; 1491 cmd = alloc(ctx.a, cr.command.len + 1); 1492 memcpy(cmd, cr.command.s, cr.command.len); 1493 cmd[cr.command.len] = 0 as byte; 1494 argv.arg0 = "/bin/sh"; 1495 argv.arg1 = "-c"; 1496 argv.arg2 = cmd; 1497 argv.arg3 = nil; 1498 ssh_spawn(ctx, &argv.arg0); 1499 free(ctx.a, cmd); 1500 return 1; 1501 } 1502 1503 func dowinch(cr: *ssh_cr_winch, ctx: *sshd_ctx): int { 1504 // window change 1505 return 0; 1506 } 1507 1508 func dosignal(cr: *ssh_cr_signal, ctx: *sshd_ctx): int { 1509 // signal 1510 return 0; 1511 } 1512 1513 func dorequest(ctx: *sshd_ctx) { 1514 var cr: ssh_channel_request; 1515 var ss: ssh_channel_success; 1516 var sf: ssh_channel_failure; 1517 var ok: int; 1518 decode_channel_request(&cr, ctx); 1519 1520 if cr.kind == SSH_CR_PTY { 1521 ok = dopty(&cr.pty, ctx); 1522 } else if cr.kind == SSH_CR_SHELL { 1523 ok = doshell(&cr.shell, ctx); 1524 } else if cr.kind == SSH_CR_EXEC { 1525 ok = doexec(&cr.exec, ctx); 1526 } else if cr.kind == SSH_CR_WINCH { 1527 ok = dowinch(&cr.winch, ctx); 1528 } else if cr.kind == SSH_CR_SIGNAL { 1529 ok = dosignal(&cr.signal, ctx); 1530 } else { 1531 //die("unknown request"); 1532 if cr.want_reply { 1533 sf.channel = 0; 1534 encode_channel_failure(&sf, ctx); 1535 write_frame(ctx); 1536 return; 1537 } 1538 } 1539 1540 if cr.want_reply { 1541 if ok { 1542 ss.channel = 0; 1543 encode_channel_success(&ss, ctx); 1544 write_frame(ctx); 1545 } else { 1546 sf.channel = 0; 1547 encode_channel_failure(&sf, ctx); 1548 write_frame(ctx); 1549 } 1550 } 1551 } 1552 1553 struct pfd4 { 1554 p0: int; 1555 p1: int; 1556 p2: int; 1557 p3: int; 1558 } 1559 1560 func reset_pfd(pfd: *int, ctx: *sshd_ctx): int { 1561 var n: int; 1562 var events: int; 1563 1564 n = 0; 1565 1566 if ( 1567 // There is a window update to send 1568 (ctx.stdin_window > 1024) 1569 // There is stdout to send 1570 || (ctx.stdout_fill > 0 && ctx.stdout_window > 0) 1571 // There is stderr to send 1572 || (ctx.stderr_fill > 0 && ctx.stdout_window > 0) 1573 // Child exited and there's no more stdout/stderr 1574 || (ctx.has_child 1575 && ctx.stdout_fill == 0 1576 && ctx.stderr_fill == 0 1577 && ctx.child_stdout == -1 1578 && ctx.child_stderr == -1 1579 && ctx.child_pid == -1) 1580 ) { 1581 events = POLLIN | POLLOUT; 1582 } else { 1583 events = POLLIN; 1584 } 1585 pfd[n] = ctx.fd | (events << 32); 1586 n = n + 1; 1587 1588 if ctx.child_stdin >= 0 && (ctx.stdin_fill > 0 || ctx.stdin_eof) { 1589 events = POLLOUT; 1590 pfd[n] = ctx.child_stdin | (events << 32); 1591 n = n + 1; 1592 } 1593 1594 if ctx.child_stdout >= 0 && ctx.stdout_fill < ctx.stderr_size { 1595 events = POLLIN; 1596 pfd[n] = ctx.child_stdout | (events << 32); 1597 n = n + 1; 1598 } 1599 1600 if ctx.child_stderr >= 0 && ctx.stderr_fill < ctx.stderr_size { 1601 events = POLLIN; 1602 pfd[n] = ctx.child_stderr | (events << 32); 1603 n = n + 1; 1604 } 1605 1606 return n; 1607 } 1608 1609 func poll_client(revents: int, ctx: *sshd_ctx) { 1610 var tag: int; 1611 var len: int; 1612 var swa: ssh_channel_window_adjust; 1613 var sd: ssh_channel_data; 1614 var sed: ssh_channel_extended_data; 1615 var sr: ssh_channel_request; 1616 var sc: ssh_channel_close; 1617 var se: ssh_channel_eof; 1618 if revents & POLLOUT { 1619 if ctx.stdin_window > 1024 { 1620 swa.channel = 0; 1621 swa.window = ctx.stdin_window; 1622 encode_channel_window_adjust(&swa, ctx); 1623 write_frame(ctx); 1624 ctx.stdin_window = 0; 1625 } else if ctx.stdout_fill > 0 && ctx.stdout_window > 0 { 1626 len = ctx.stdout_fill; 1627 if len > 1024 { 1628 len = 1024; 1629 } 1630 1631 if len > ctx.stdout_window { 1632 len = ctx.stdout_window; 1633 } 1634 1635 sd.channel = 0; 1636 sd.data.s = ctx.stdout_buf; 1637 sd.data.len = len; 1638 1639 memcpy(ctx.stdout_buf, &ctx.stdout_buf[len], ctx.stdout_fill - len); 1640 ctx.stdout_window = ctx.stdout_window - len; 1641 ctx.stdout_fill = ctx.stdout_fill - len; 1642 1643 encode_channel_data(&sd, ctx); 1644 write_frame(ctx); 1645 } else if ctx.stderr_fill > 0 && ctx.stdout_window > 0 { 1646 len = ctx.stderr_fill; 1647 if len > 1024 { 1648 len = 1024; 1649 } 1650 1651 if len > ctx.stdout_window { 1652 len = ctx.stdout_window; 1653 } 1654 1655 sed.channel = 0; 1656 sed.code = 1; 1657 sed.data.s = ctx.stderr_buf; 1658 sed.data.len = len; 1659 1660 memcpy(ctx.stderr_buf, &ctx.stderr_buf[len], ctx.stderr_fill - len); 1661 ctx.stdout_window = ctx.stdout_window - len; 1662 ctx.stderr_fill = ctx.stderr_fill - len; 1663 1664 encode_channel_extended_data(&sed, ctx); 1665 write_frame(ctx); 1666 } else { 1667 se.channel = 0; 1668 encode_channel_eof(&se, ctx); 1669 write_frame(ctx); 1670 1671 sr.channel = 0; 1672 sr.want_reply = 0; 1673 sr.kind = SSH_CR_EXIT_STATUS; 1674 sr.exit.status = ctx.exit_status; 1675 encode_channel_request(&sr, ctx); 1676 write_frame(ctx); 1677 1678 sc.channel = 0; 1679 encode_channel_close(&sc, ctx); 1680 write_frame(ctx); 1681 1682 loop { 1683 read_frame(ctx); 1684 if ctx.frame[0] as int == SSH_MSG_DISCONNECT { 1685 break; 1686 } 1687 } 1688 1689 exit(0); 1690 } 1691 } else { 1692 read_frame(ctx); 1693 1694 tag = ctx.frame[0] as int; 1695 if tag == SSH_MSG_DISCONNECT { 1696 dodisconnect(ctx); 1697 } else if tag == SSH_MSG_KEXINIT { 1698 dokex(ctx); 1699 } else if tag == SSH_MSG_CHANNEL_WINDOW_ADJUST { 1700 dowindow(ctx); 1701 } else if tag == SSH_MSG_CHANNEL_DATA { 1702 dodata(ctx); 1703 } else if tag == SSH_MSG_CHANNEL_EOF { 1704 doeof(ctx); 1705 } else if tag == SSH_MSG_CHANNEL_CLOSE { 1706 doclose(ctx); 1707 } else if tag == SSH_MSG_CHANNEL_REQUEST { 1708 dorequest(ctx); 1709 } else { 1710 die("invalid packet"); 1711 } 1712 } 1713 } 1714 1715 func poll_stdin(revents: int, ctx: *sshd_ctx) { 1716 var ret: int; 1717 if ctx.stdin_fill == 0 && ctx.stdin_eof { 1718 close(ctx.child_stdin); 1719 ctx.child_stdin = -1; 1720 return; 1721 } 1722 ret = write(ctx.child_stdin, ctx.stdin_buf, ctx.stdin_fill); 1723 if ret == -EINTR { 1724 return; 1725 } 1726 if ret == -EPIPE { 1727 close(ctx.child_stdin); 1728 ctx.child_stdin = -1; 1729 return; 1730 } 1731 memcpy(ctx.stdin_buf, &ctx.stdin_buf[ret], ctx.stdin_fill - ret); 1732 ctx.stdin_fill = ctx.stdin_fill - ret; 1733 ctx.stdin_window = ctx.stdin_window + ret; 1734 } 1735 1736 func poll_stdout(revents: int, ctx: *sshd_ctx) { 1737 var ret: int; 1738 ret = read(ctx.child_stdout, &ctx.stdout_buf[ctx.stdout_fill], ctx.stdout_size - ctx.stdout_fill); 1739 if ret == -EINTR { 1740 return; 1741 } 1742 if ret == 0 { 1743 close(ctx.child_stdout); 1744 ctx.child_stdout = -1; 1745 return; 1746 } 1747 ctx.stdout_fill = ctx.stdout_fill + ret; 1748 } 1749 1750 func poll_stderr(revents: int, ctx: *sshd_ctx) { 1751 var ret: int; 1752 ret = read(ctx.child_stderr, &ctx.stderr_buf[ctx.stderr_fill], ctx.stderr_size - ctx.stderr_fill); 1753 if ret == -EINTR { 1754 return; 1755 } 1756 if ret == 0 { 1757 close(ctx.child_stderr); 1758 ctx.child_stderr = -1; 1759 return; 1760 } 1761 ctx.stderr_fill = ctx.stderr_fill + ret; 1762 } 1763 1764 func poll_exit(ctx: *sshd_ctx) { 1765 var ret: int; 1766 var status: int; 1767 loop { 1768 ret = wait(-1, &status, WNOHANG); 1769 if ret <= 0 { 1770 break; 1771 } 1772 if ret == ctx.child_pid { 1773 ctx.child_pid = -1; 1774 ctx.exit_status = status; 1775 } 1776 } 1777 } 1778 1779 func client_loop(ctx: *sshd_ctx) { 1780 var _p: pfd4; 1781 var p: *int; 1782 var n: int; 1783 var i: int; 1784 var fd: int; 1785 var revents: int; 1786 1787 p = &_p.p0; 1788 1789 loop { 1790 poll_exit(ctx); 1791 1792 n = reset_pfd(p, ctx); 1793 if poll(p, n, -1) == -EINTR { 1794 continue; 1795 } 1796 1797 i = 0; 1798 loop { 1799 if i == n { 1800 break; 1801 } 1802 1803 fd = p[i] & (-1 >> 32); 1804 revents = p[i] >> 48; 1805 i = i + 1; 1806 1807 if !revents { 1808 continue; 1809 } 1810 1811 if fd == ctx.fd { 1812 poll_client(revents, ctx); 1813 } 1814 1815 if fd == ctx.child_stdin { 1816 poll_stdin(revents, ctx); 1817 } 1818 1819 if fd == ctx.child_stdout { 1820 poll_stdout(revents, ctx); 1821 } 1822 1823 if fd == ctx.child_stderr { 1824 poll_stderr(revents, ctx); 1825 } 1826 } 1827 } 1828 } 1829 1830 func cmain(ctx: *sshd_ctx) { 1831 doversion(ctx); 1832 1833 read_frame(ctx); 1834 dokex(ctx); 1835 1836 read_frame(ctx); 1837 doauth(ctx); 1838 1839 read_frame(ctx); 1840 dosession(ctx); 1841 1842 client_loop(ctx); 1843 } 1844 1845 struct sockaddr { 1846 fpa: int; 1847 pad: int; 1848 } 1849 1850 struct sshd_ctx { 1851 fd: int; 1852 a: *alloc; 1853 priv: _ed25519_priv; 1854 pub: _ed25519_pub; 1855 userpub: _ed25519_pub; 1856 hostkey: *byte; 1857 hostkeylen: int; 1858 username: *byte; 1859 userkey: *byte; 1860 userkeylen: int; 1861 buf: *byte; 1862 bufsz: int; 1863 frame: *byte; 1864 framelen: int; 1865 index: int; 1866 sver: *byte; 1867 cver: *byte; 1868 skex: *byte; 1869 skexlen: int; 1870 ckex: *byte; 1871 ckexlen: int; 1872 macsize: int; 1873 has_session_id: int; 1874 session_id: _sha256_digest; 1875 eh: _sha256_digest; 1876 k: _ed25519_point; 1877 iv_client_to_server: _sha512_digest; 1878 iv_server_to_client: _sha512_digest; 1879 ek_client_to_server: _sha512_digest; 1880 ek_server_to_client: _sha512_digest; 1881 ik_client_to_server: _sha512_digest; 1882 ik_server_to_client: _sha512_digest; 1883 en_client_to_server: int; 1884 en_server_to_client: int; 1885 seq_client_to_server: int; 1886 seq_server_to_client: int; 1887 has_child: int; 1888 child_pid: int; 1889 child_stdin: int; 1890 child_stdout: int; 1891 child_stderr: int; 1892 stdin_window: int; 1893 stdout_window: int; 1894 stdin_buf: *byte; 1895 stdin_size: int; 1896 stdin_fill: int; 1897 stdin_eof: int; 1898 stdout_buf: *byte; 1899 stdout_fill: int; 1900 stdout_size: int; 1901 stderr_buf: *byte; 1902 stderr_fill: int; 1903 stderr_size: int; 1904 exit_status: int; 1905 } 1906 1907 func format_key(d: **byte, dlen: *int, k: *byte, ctx: *sshd_ctx) { 1908 var s: ssh_str; 1909 clear_frame(ctx); 1910 set_str(&s, "ssh-ed25519"); 1911 encode_str(&s, ctx); 1912 s.s = k; 1913 s.len = 32; 1914 encode_str(&s, ctx); 1915 finish_frame(ctx); 1916 *d = alloc(ctx.a, ctx.framelen); 1917 memcpy(*d, ctx.frame, ctx.framelen); 1918 *dlen = ctx.framelen; 1919 clear_frame(ctx); 1920 } 1921 1922 func dosigchld() { 1923 } 1924 1925 func _restorer(); 1926 1927 func signal(sig: int, handler: func()) { 1928 var act: sigaction; 1929 act.handler = dosigchld as int; 1930 act.flags = 1 << 26; 1931 act.restorer = _restorer as int; 1932 act.mask = 0; 1933 sigaction(sig, &act, nil); 1934 } 1935 1936 func main(argc: int, argv: **byte, envp: **byte) { 1937 var fd: int; 1938 var cfd: int; 1939 var port: int; 1940 var sa: sockaddr; 1941 var ctx: sshd_ctx; 1942 var a: alloc; 1943 setup_alloc(&a); 1944 1945 signal(SIGCHLD, dosigchld); 1946 signal(SIGPIPE, SIG_IGN as func()); 1947 1948 bzero((&ctx) as *byte, sizeof(ctx)); 1949 1950 if unhex((&ctx.userpub) as *byte, "5afb3032d86d60d700e1782bfe8083ff95504cecbda531bef5ba8cdd20f34c82") != 32 { 1951 die("invalid userpub"); 1952 } 1953 1954 ed25519_pub((&ctx.pub) as *byte, (&ctx.priv) as *byte); 1955 1956 ctx.child_pid = -1; 1957 ctx.child_stdin = -1; 1958 ctx.child_stdout = -1; 1959 ctx.child_stderr = -1; 1960 1961 ctx.a = &a; 1962 ctx.bufsz = 64 * 1024; 1963 ctx.buf = alloc(ctx.a, ctx.bufsz); 1964 ctx.skex = alloc(ctx.a, 4096); 1965 ctx.ckex = alloc(ctx.a, 4096); 1966 ctx.sver = "SSH-2.0-omiltem"; 1967 1968 ctx.stdin_size = 64 * 1024; 1969 ctx.stdin_buf = alloc(ctx.a, ctx.stdin_size); 1970 ctx.stdout_size = 64 * 1024; 1971 ctx.stdout_buf = alloc(ctx.a, ctx.stdout_size); 1972 ctx.stderr_size = 64 * 1024; 1973 ctx.stderr_buf = alloc(ctx.a, ctx.stderr_size); 1974 1975 ctx.username = "erai"; 1976 format_key(&ctx.hostkey, &ctx.hostkeylen, (&ctx.pub) as *byte, &ctx); 1977 format_key(&ctx.userkey, &ctx.userkeylen, (&ctx.userpub) as *byte, &ctx); 1978 1979 fd = socket(AF_INET, SOCK_STREAM, 0); 1980 if fd < 0 { 1981 die("failed to open socket"); 1982 } 1983 1984 port = 2222; 1985 sa.fpa = AF_INET | ((port & 0xff) << 24) | (((port >> 8) & 0xff) << 16); 1986 sa.pad = 0; 1987 if bind(fd, (&sa) as *byte, sizeof(sa)) != 0 { 1988 die("failed to bind"); 1989 } 1990 1991 if listen(fd, 128) != 0 { 1992 die("failed to listen"); 1993 } 1994 1995 loop { 1996 loop { 1997 if wait(-1, nil, WNOHANG) <= 0 { 1998 break; 1999 } 2000 } 2001 2002 ctx.fd = accept(fd, nil, nil); 2003 if ctx.fd == -EINTR { 2004 continue; 2005 } 2006 2007 if ctx.fd < 0 { 2008 exit(1); 2009 } 2010 2011 if fork() == 0 { 2012 close(fd); 2013 cmain(&ctx); 2014 die("cmain returned"); 2015 } 2016 2017 close(ctx.fd); 2018 } 2019 }